Results 1 to 2 of 2
  1. #1
    Newbie
    Join Date
    Dec 2017
    Posts
    5

    Default Untangle Import Bash Script

    I'm sure there are better ways to do this and other examples in this forum - but I thought I'd share my Untangle import file generation script in case someone else can get some mileage out of it.

    • The list uses a single JSON file as input. This source file contains device information.
    • The script produces three import files: static DNS, static DHCP, and Name Map (Reports)
    • Bash isn't good at JSON. There are some ugly hacks that deal with commas, spaces, etc.
    • If any device names contain spaces, the spaces need to be replaced with underscores in the input file (see example). The script will translate the underscores into spaces.
    • The script needs to know the hostname for the last device listed in your input file (see script below).


    So, for a "devices.json" file formatted like this:


    Code:
    {
      
      "ab:cd:ef:12:34:56" : {
        "Name"    : "Home_Server",
        "Host"    : "server",
        "Address" : "192.168.0.100"
      },
      
      "78:90:ab:cd:ef:12" : {
        "Name"    : "Smart_Device",
        "Host"    : "smart",
        "Address" : "192.168.0.101"
      },
      
      "34:56:78:90:ab:cd" : {
        "Name"    : "Laptop",
        "Host"    : "laptop",
        "Address" : "192.168.0.102"
      }
      
    }
    ...you can use the following script to generate the three import files:

    Code:
    #!/bin/bash
    
    dhcp=untangle-dhcp.json
    dns=untangle-dns.json
    map=untangle-map.json
    lastdev='laptop'
    
    # create dhcp
    echo "[" > $dhcp
    echo "" >> $dhcp
    
    # create dns
    echo "[" > $dns
    echo "" >> $dns
    
    # create map
    echo "[" > $map
    echo "" >> $map
    
    # parse device index
    while read device; do
      
      if [[ $device == '"'* ]]; then
        
        if [[ $device == *'"Name"'* ]]; then name="$(echo -e "${device:13: -2}" | tr -d '[[:space:]]')" # parse for Name
        elif [[ $device == *'"Host"'* ]]; then host="$(echo -e "${device:13: -2}" | tr -d '[[:space:]]')" # parse for Host
        elif [[ $device == *'"Address"'* ]]; then
          
          # check for last entry
          if [ $host == $lastdev ]; then div=''; else div='###'; fi
          
          # parse for IP Address
          ip="$(echo -e "${device:13: -1}" | tr -d '[[:space:]]')";
          
          # dhcp
          echo "  {" >> $dhcp
          echo "    \"macAddress\"  : \"$mac\"," >> $dhcp
          echo "    \"address\"     : \"$ip\"," >> $dhcp
          echo "    \"javaClass\"   : \"com.untangle.uvm.network.DhcpStaticEntry\"," >> $dhcp
          echo "    \"description\" : \"$name\"" >> $dhcp
          echo "  }$div" >> $dhcp
          echo "" >> $dhcp
          
          # dns
          echo "  {" >> $dns
          echo "    \"address\"     : \"$ip\"," >> $dns
          echo "    \"javaClass\"   : \"com.untangle.uvm.network.DnsStaticEntry\"," >> $dns
          echo "    \"name\"        : \"$host.home.lan\"" >> $dns
          echo "  }$div" >> $dns
          echo "" >> $dns
          
          # map
          echo "  {" >> $map
          echo "    \"hostname\"    : \"$name\"," >> $map
          echo "    \"address\"     : \"$ip\"," >> $map
          echo "    \"javaClass\"   : \"com.untangle.app.reports.ReportsHostnameMapEntry\"" >> $map
          echo "  }$div" >> $map
          echo "" >> $map
          
        else mac="$(echo -e "${device:1: -5}" | tr -d '[[:space:]]')"; fi # parse for MAC Address
        
      fi
      
    done <devices.json
    
    # close dhcp
    echo "]" >> $dhcp
    sed -i -e 's/###/,/g' $dhcp
    sed -i -e 's/_/\ /g' $dhcp
    
    # close dns
    echo "]" >> $dns
    sed -i -e 's/###/,/g' $dns
    sed -i -e 's/_/\ /g' $dns
    
    # close map
    echo "]" >> $map
    sed -i -e 's/###/,/g' $map
    sed -i -e 's/_/\ /g' $map
    
    exit 0
    The script is brittle; it will probably need some modification for your needs. But in any case, hopefully it will be a useful starting point for someone.
    Last edited by nmax; 12-23-2017 at 09:59 AM. Reason: Typography

  2. #2
    Newbie
    Join Date
    Dec 2017
    Posts
    10

    Post unimdeli.py

    Made the same thing for Python, I guess not as brittle and slightly more dynamic.
    Code:
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    """
    unimdeli - Untangle Import Device List
    """
    import argparse
    import json
    from collections import OrderedDict as OCD
    import re
    
    
    translator = OCD({"dhcp": OCD([("macAddress", "[key]"), ("address", "[address]"), ("javaClass", "com.untangle.uvm.network.DhcpStaticEntry"), ("description", "[name]")]), 
    "dns": OCD([("address", "[address]"), ("javaClass", "com.untangle.uvm.network.DnsStaticEntry"), ("name", "[host].home.lan")]),
    "map": OCD([("hostname", "[name]"), ("address", "[address]"), ("javaClass", "com.untangle.app.reports.ReportsHostnameMapEntry")])
    })
    
    def lower_keys(x):  # https://stackoverflow.com/questions/...-are-lowercase
        if isinstance(x, list):
            return [lower_keys(v) for v in x]
        elif isinstance(x, dict) or isinstance(x, OCD):
            return OCD((k.lower(), lower_keys(v)) for k, v in x.items())
        else:
            return x
    
    def main(args):
        """
        :param args:
        :return:
        """
        devices = lower_keys(json.load(open(args.filename), object_pairs_hook=OCD))
        for device in devices:
            devices[device]["key"] = re.sub('[^0-9a-fA-F]+', args.mac_seperator, device)
            if "name" in devices[device]:
                devices[device]["name"] = re.sub('[^0-9a-zA-Z]+', ' ', devices[device]["name"])
        for item in translator:
            outl = []
            for key in devices:
                outd = OCD()
                for new, val in translator[item].items():
                    b, e = val.find('['), val.find(']')
                    val = val.replace(val[b:e + 1], devices[key][val[b + 1:e]] if val[b + 1:e] in devices[key] else '')
                    outd[new] = val
                outl.append(outd)
            json.dump(outl, open('untangle-%s.json' % item, 'w'), indent=2)
    
    
    if __name__ == '__main__':
        parser = argparse.ArgumentParser()
        parser.add_argument('filename', help="input file")
        # IEEE 802 standard MAC-48 format is six groups of two hex digits, separated by hyphens (-) in transmission order (e.g. 01-23-45-67-89-ab).
        parser.add_argument('--sep', dest='mac_seperator', default='-', help="mac address seperator, to be implemented")
        args = parser.parse_args()
        main(args)

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  

SEO by vBSEO 3.6.0 PL2