Пример #1
0
def generate(name):
    '''
	Summary:
	Generates a configuration file for a specified device.

	Takes: 
	name: Device to generate configuration for
	'''
    Device.get_devices_from_file()

    if os.path.isfile(METADATA_PATH + name + '_metadata.yaml'):
        with open(METADATA_PATH + name + '_metadata.yaml', 'r') as metadata:
            device_metadata = (yaml.safe_load(metadata))
    else:
        log('[{}] Metadata does not exist'.format(name), 'info')
        sys.exit(1)

    device_os = Device.get_device_information(name)['os']

    environment = MODULE_PATH + device_os + '/'

    j2_env = Environment(loader=FileSystemLoader(environment),
                         trim_blocks=True,
                         lstrip_blocks=True)

    for device, data in device_metadata.items():
        configuration = j2_env.get_template('template.j2').render(data)

    with open(CONFIG_PATH + name + '_generated.txt',
              'w') as generated_config_file:
        generated_config_file.write(configuration)

    log('[{}] Generated configuration'.format(name), 'info')
Пример #2
0
    def check_configuration_line(device, device_connection, os,
                                 configuration_line):
        '''
			Summary:
			Checks if configuration line has been pushed to device.

			Takes:
			device: Device name
			device_connection: Device connection object
			os: Operating system of device
			configuration_line: Configuration line to check for
		'''
        with open(MODULE_PATH + os + '/commands.json') as command_file_temp:
            command_file = json.load(command_file_temp)

        configuration = device_connection.send_command(
            command_file['commands']['config'])

        if configuration_line in configuration:
            log(
                "[{}] Configuration check passed for '{}'".format(
                    device, configuration_line), 'info')
            return False
        else:
            log(
                "[{}] Configuration check failed for '{}', rolling back".
                format(device, configuration_line), 'info')
            Configuration.rollback_configuration(device, os, device_connection)
            return True
Пример #3
0
    def delete_rollback_configuration(device):
        '''
			Summary:
			Delete rollback configuration once deployment succeeds..

			Takes:
			device: Device name
		'''
        os.remove(CONFIG_PATH + device + '_rollback.txt')
        log("[{}] Removed rollback file".format(device), 'info')
Пример #4
0
	def close_connection(self, connection):
		'''
		Summary:
		Closes an SSH connection to a device.

		Takes:
		connection: Connection object to close
		'''
		connection.disconnect()

		log('[{}] Disconnected'.format(self.name), 'info')
Пример #5
0
    def rollback_configuration(device, os, device_connection):
        '''
			Summary:
			Performs a rollback of device configuration.

			Takes:
			device: Device name
			device_connection: Device connection object
		'''
        try:
            with open(CONFIG_PATH + device +
                      '_custom_commands.txt') as custom_commands_from_file:
                command_list_temp = custom_commands_from_file.read(
                ).splitlines()

            if os == 'cisco_ios':
                command_list = [
                    'no ' + command for command in command_list_temp
                ]
            elif os == 'vyos':
                command_list = [
                    command.replace('set', 'delete')
                    for command in command_list_temp
                ]

            device_connection.send_config_set(command_list)

            if os == 'vyos':
                device_connection.send_config_set(['commit', 'save'])
            elif os == 'cisco_ios':
                output = device_connection.send_command_timing(
                    'copy run start')
                if 'Destination filename' in output:
                    device_connection.send_command_timing("\n",
                                                          strip_prompt=False,
                                                          strip_command=False)
                if 'Overwrite the previous' in output:
                    device_connection.send_command_timing("\n",
                                                          strip_prompt=False,
                                                          strip_command=False)
                if 'Warning: Attempting to overwrite an NVRAM configuration previously written' in output:
                    device_connection.send_command_timing("\n",
                                                          strip_prompt=False,
                                                          strip_command=False)

            log('[{}] Device configuration rolled back'.format(device), 'info')
        except AttributeError:
            log(
                '[{}] Could not send commands, device unreachable'.format(
                    device), 'error')
Пример #6
0
    def save_deployments_to_file():
        '''
		Summary:
		Saves deployment data to an encrypted file.
		'''
        deployments_to_save = []

        for deployment in deployments:
            for deployment_name, deployment_object in deployment.items():
                deployments_to_save.append(deployment_object.all())

        Crypt.create_encrypted_file('deployments', deployments_to_save)

        log('Saved deployments to file', 'info')
Пример #7
0
    def save_devices_to_file():
        '''
		Summary:
		Saves device data to an encrypted file.
		'''
        devices_to_save = []

        for device in devices:
            for device_name, device_object in device.items():
                devices_to_save.append(device_object.all())

        Crypt.create_encrypted_file('devices', devices_to_save)

        log('Saved devices to file', 'info')
Пример #8
0
    def get_devices_from_file():
        '''
		Summary:
		Gets device data from an encrypted file and creates an object stored in the devices list.
		'''
        if os.path.isfile(DB_PATH + 'devices'):
            devices_temp_file = Crypt.get_encrypted_file_contents('devices')
            for device in devices_temp_file:
                device_object = Device(device['name'], device['ip'],
                                       device['username'], device['password'],
                                       device['os'])
                devices.append({device['name']: device_object})
            log('Got devices from file', 'info')
        else:
            log('No devices to get from file', 'info')
Пример #9
0
def run(name):
    '''
	Summary:
	Calls the run method on a Deployment object.

	Takes:
	name: Name of deployment to run
	'''
    Device.get_devices_from_file()
    Deployment.get_deployments_from_file()
    for deployment in deployments:
        if name in deployment:
            deployment[name].run()
            Deployment.save_deployments_to_file()
            return
    log('[{}] Deployment does not exist'.format(name), 'error')
Пример #10
0
def remove(name):
    '''
	Summary:
	Removes a device.

	Takes:
	name: Name of device to remove
	'''
    Device.get_devices_from_file()
    for device in devices:
        if name in device:
            devices.remove(device)
            log('[{}] Device removed successfully'.format(name), 'info')
            Device.save_devices_to_file()
            return

    log('[{}] Device does not exist'.format(name), 'error')
Пример #11
0
def remove(name):
    '''
	Summary:
	Removes a deployment.

	Takes:
	name: Name of deployment to remove
	'''
    Deployment.get_deployments_from_file()
    for deployment in deployments:
        if name in deployment:
            deployments.remove(deployment)
            log('[{}] Deployment removed successfully'.format(name), 'info')
            Deployment.save_deployments_to_file()
            return

    log('[{}] Deployment does not exist'.format(name), 'error')
Пример #12
0
    def deploy_custom_configuration(device):
        '''
			Summary:
			Deploys custom configuration from a file to a device.

			Takes:
			device: Device to deploy configuration to
		'''
        rolled_back = False
        device_information = Device.get_device_information(device)

        connection_object = Connection(device_information['name'],
                                       device_information['ip'],
                                       device_information['username'],
                                       device_information['password'],
                                       device_information['os'])
        device_connection = connection_object.get_connection()

        try:
            Configuration.snapshot_configuration(device, device_connection,
                                                 device_information['os'])

            with open(CONFIG_PATH + device +
                      '_custom_commands.txt') as custom_commands_from_file:
                command_list = custom_commands_from_file.read().splitlines()

            log('[{}] Pushing configuration...'.format(device), 'info')
            device_connection.send_config_set(command_list)

            Configuration.save_configuration(device_information['os'],
                                             device_connection)

            for command in command_list:
                if command != 'no shutdown' and rolled_back == False:
                    rolled_back = Configuration.check_configuration_line(
                        device, device_connection, device_information['os'],
                        command)

            connection_object.close_connection(device_connection)

            Configuration.delete_rollback_configuration(device)
        except AttributeError:
            log('[{}] Could not send commands'.format(device), 'error')
Пример #13
0
def decrypt(filename):
    '''
		Summary:
		Create a decrypted copy of a file in JSON format.

		Takes: 
		filename: Name of decrypted file
	'''
    key = Crypt.get_key()

    with open(DB_PATH + filename, 'rb') as encrypted_file:
        data = encrypted_file.read()

    fernet = Fernet(key)
    decrypted_data = literal_eval(fernet.decrypt(data).decode())

    with open(DB_PATH + filename + '.decrypted', 'w') as decrypted_file:
        json.dump(decrypted_data, decrypted_file, indent=4)

    log('Generated decrypted file {}.decrypted'.format(filename), 'info')
Пример #14
0
    def mark_configuration_as_deployed(device):
        '''
			Summary:
			Marks a generated configuration file as deployed.

			Takes:
			device: Name of device to mark configuration as deployed for
		'''
        with open(CONFIG_PATH + device +
                  '_generated.txt') as generated_configuration_file:
            deployed_configuration = generated_configuration_file.read()

        with open(
                CONFIG_PATH + device + '_deployed_' +
                datetime.now().strftime('%Y-%m-%d_%H:%M:%S') + '.txt',
                'w') as deployed_configuration_file:
            deployed_configuration_file.write(deployed_configuration)

        log('[{}] Marked generated configuration as deployed'.format(device),
            'info')
Пример #15
0
    def get_deployments_from_file():
        '''
		Summary:
		Gets deployment data from an encrypted file and creates an object stored in the deployments list.
		'''
        if os.path.isfile(DB_PATH + 'deployments'):
            deployments_temp_file = Crypt.get_encrypted_file_contents(
                'deployments')
            for deployment in deployments_temp_file:
                deployment_object = Deployment(
                    deployment['name'],
                    deployment['targets'],
                    deployment['action'],
                    deployment_id=deployment['deployment_id'],
                    status=deployment['status'],
                )
                deployments.append({deployment['name']: deployment_object})

            log('Got deployments from file', 'info')
        else:
            log('No deployments to get from file', 'info')
Пример #16
0
def add(name, targets, action):
    '''
	Summary:
	Adds a deployment.

	Takes:
	name: Name of deployment
	targets: Devices to target with the deployment
	action: Action to perform get|deploy_generated|deploy_custom
	'''
    Deployment.get_deployments_from_file()
    for deployment in deployments:
        if name in deployment:
            log('[{}] Deployment already exists'.format(name), 'info')
            sys.exit(1)
    deployment_object = Deployment(name, list(targets), action)
    deployments.append({name: deployment_object})
    log(
        '[{}] Deployment added successfully with ID {}'.format(
            name, deployment_object.deployment_id), 'info')
    Deployment.save_deployments_to_file()
Пример #17
0
def add(name, ip, username, password, os):
    '''
	Summary:
	Adds a device.

	Takes: 
	name: Name of device
	ip: Management IP address of device
	username: Username to authenticate against
	password: Password to authenticate with
	os: Operating system of device cisco_ios|vyos
	'''
    Device.get_devices_from_file()
    for device in devices:
        if name in device:
            log('[{}] Device already exists'.format(name), 'info')
            sys.exit(1)
    device_object = Device(name, ip, username, password, os)
    devices.append({name: device_object})
    log('[{}] Device added successfully'.format(name), 'info')
    Device.save_devices_to_file()
Пример #18
0
def add_from_file(filename):
    Device.get_devices_from_file()
    file_path = DB_PATH + filename
    if os.path.isfile(file_path):
        log("Adding devices from '{}'".format(file_path), 'info')
        with open(file_path, 'r') as devices_file:
            all_lines = [line.strip() for line in devices_file.readlines()]
            for device_attribute in range(0, len(all_lines), 5):
                device_exists = False
                for device in devices:
                    if all_lines[device_attribute] in device:
                        log(
                            '[{}] Device already exists'.format(
                                all_lines[device_attribute]), 'info')
                        device_exists = True
                if device_exists == False:
                    device_object = Device(all_lines[device_attribute],
                                           all_lines[device_attribute + 1],
                                           all_lines[device_attribute + 2],
                                           all_lines[device_attribute + 3],
                                           all_lines[device_attribute + 4])
                    devices.append(
                        {all_lines[device_attribute]: device_object})
                    log(
                        '[{}] Device added successfully'.format(
                            all_lines[device_attribute]), 'info')
    Device.save_devices_to_file()
Пример #19
0
    def deploy_generated_configuration(device):
        '''
			Summary:
			Deploys configuration generated from device metadata to a device.

			Takes:
			device: Device to deploy configuration to
		'''
        device_information = Device.get_device_information(device)

        connection_object = Connection(device_information['name'],
                                       device_information['ip'],
                                       device_information['username'],
                                       device_information['password'],
                                       device_information['os'])
        device_connection = connection_object.get_connection()

        try:
            Configuration.snapshot_configuration(device, device_connection,
                                                 device_information['os'])

            log('[{}] Pushing configuration...'.format(device), 'info')
            device_connection.send_config_from_file(CONFIG_PATH + device +
                                                    '_generated.txt')

            Configuration.save_configuration(device_information['os'],
                                             device_connection)

            pushed_successfully = Configuration.check_full_configuration(
                device, device_connection, device_information['os'])

            if pushed_successfully == True:
                Configuration.mark_configuration_as_deployed(device)
                Configuration.delete_rollback_configuration(device)

            connection_object.close_connection(device_connection)
        except AttributeError:
            log(
                '[{}] Could not send commands, device unreachable'.format(
                    device), 'error')
Пример #20
0
    def snapshot_configuration(device, device_connection, os):
        '''
			Summary:
			Takes a snapshot of device configuration for rollback configuration.

			Takes:
			device: Device name
		'''
        try:
            with open(MODULE_PATH + os +
                      '/commands.json') as command_list_from_file:
                command_list = json.load(command_list_from_file)

            log('[{}] Creating configuration snapshot...'.format(device),
                'info')

            output = device_connection.send_command(
                command_list['commands']['config'])

            configuration_lines = output.splitlines()

            with open(CONFIG_PATH + device + '_rollback.txt',
                      'w+') as configuration_file:
                for line in configuration_lines:
                    configuration_file.write(line + '\n')

            log(
                '[{}] Configuration snapshot stored as {}_rollback.txt in {}'.
                format(device, device, CONFIG_PATH), 'info')
        except AttributeError:
            log(
                '[{}] Could not send commands, device unreachable'.format(
                    device), 'error')
Пример #21
0
	def get_connection(self):
		'''
		Summary:
		Tests device connectivity then creates an SSH connection if successful.

		Returns:
		Connection object
		'''
		ping_result = ping(self.ip, count=1)

		if 'Request timed out' not in str(ping_result):
			log('[{}] Reachable, getting connection...'.format(self.name), 'info')

			connection = Netmiko(
				self.ip,
				username=self.username,
				password=self.password,
				device_type=self.os
			)

			log('[{}] Connected'.format(self.name), 'info')
			return connection
		else:
			log('[{}] Not reachable'.format(self.name), 'info')
			return
Пример #22
0
    def run(self):
        '''
		Summary:
		Runs a deployment.
		'''
        log('[{}] Running deployment'.format(self.name), 'info')

        self.status = 'In progress'
        log('[{}] Updated deployment status to In progress'.format(self.name),
            'info')

        if self.action == 'get':
            device_processes = [
                Process(target=Configuration.get_configuration,
                        args=(target_device, ))
                for target_device in self.targets
            ]
        elif self.action == 'deploy_generated':
            device_processes = [
                Process(target=Configuration.deploy_generated_configuration,
                        args=(target_device, ))
                for target_device in self.targets
            ]
        elif self.action == 'deploy_custom':
            device_processes = [
                Process(target=Configuration.deploy_custom_configuration,
                        args=(target_device, ))
                for target_device in self.targets
            ]

        for _process in device_processes:
            _process.start()

        for _process in device_processes:
            _process.join()

        self.status = 'Completed'
        log('[{}] Updated deployment status to Completed'.format(self.name),
            'info')

        log('[{}] Deployment completed'.format(self.name), 'info')
Пример #23
0
def stored():
    '''
	Summary:
	Lists all stored configuration files.

	Takes: 
	none
	'''
    configurations = os.listdir(CONFIG_PATH)

    if configurations:
        log('Stored configuration files:', 'info')
        for configuration_file in configurations:
            if configuration_file != '__init__.py':
                log(configuration_file, 'info')
    else:
        log('No configuration files stored', 'info')
Пример #24
0
    def get_configuration(device):
        '''
			Summary:
			Gets current configuration from a device and stores it in a file.

			Takes:
			device: Device to get configuration from
		'''
        device_information = Device.get_device_information(device)

        connection_object = Connection(device_information['name'],
                                       device_information['ip'],
                                       device_information['username'],
                                       device_information['password'],
                                       device_information['os'])
        device_connection = connection_object.get_connection()

        try:
            with open(MODULE_PATH + device_information['os'] +
                      '/commands.json') as command_list_from_file:
                command_list = json.load(command_list_from_file)

            log('[{}] Getting device configuration...'.format(device), 'info')

            output = device_connection.send_command(
                command_list['commands']['config'])

            configuration_lines = output.splitlines()

            with open(CONFIG_PATH + device + '_latest.txt',
                      'w+') as configuration_file:
                for line in configuration_lines:
                    configuration_file.write(line + '\n')

            log(
                '[{}] Device configuration stored as {}_latest.txt in {}'.
                format(device, device, CONFIG_PATH), 'info')

            connection_object.close_connection(device_connection)
        except AttributeError:
            log(
                '[{}] Could not send commands, device unreachable'.format(
                    device), 'error')
Пример #25
0
def diff(config1, config2):
    '''
	Summary:
	Outputs the difference between two device configuration files by comparing them line by line.

	Takes:
	config1: First configuration file
	config2: Configuration file to compare with
	'''
    config1_lines = open(CONFIG_PATH + config1).read().splitlines()
    config2_lines = open(CONFIG_PATH + config2).read().splitlines()
    diff = difflib.unified_diff(config1_lines, config2_lines)

    log('Diff for [{}] < > [{}]'.format(config1, config2), 'info')
    for line in diff:
        if line[0] == '+' and line[1] != '+':
            log('\033[0;32m{}\033[m'.format(line), 'info')
        elif line[0] == '-' and line[1] != '-':
            log('\033[0;31m{}\033[m'.format(line), 'info')
Пример #26
0
    def generate_key():
        '''
			Summary:
			Generate a key used for symmetric encryption, using the hash of a user entered password for the salt.

			Returns:
			Encryption key

			Encryption type: 
			128-bit AES
		'''
        if os.path.isfile(KEY_PATH):
            log(
                "Using existing key '{}' for encryption/decryption".format(
                    KEY_PATH), 'info')
            key = Crypt.get_key()

            return key
        else:
            log(
                "Attempting to use '{}' but no key found, create a new key or add an existing one"
                .format(KEY_PATH), 'info')

            password = getpass(prompt='New encryption key password: '******'wb') as encryption_key:
                encryption_key.write(key)

            log("Stored encryption key as '{}'".format(KEY_PATH), 'info')

            return key
Пример #27
0
    def check_full_configuration(device, device_connection, os):
        '''
			Summary:
			Checks if full configuration has been pushed to device.

			Takes:
			device: Device name
			device_connection: Device connection object
			os: Operating system of device
		'''
        full_configuration_pushed = True
        do_not_check = ['!', ' no shutdown']

        with open(MODULE_PATH + os + '/commands.json') as command_file_temp:
            command_file = json.load(command_file_temp)

        device_configuration = device_connection.send_command(
            command_file['commands']['config'])

        with open(CONFIG_PATH + device +
                  '_generated.txt') as pushed_configuration_temp:
            pushed_configuration = pushed_configuration_temp.read().splitlines(
            )

        log('[{}] Checking configuration...'.format(device), 'info')

        for configuration_line in pushed_configuration:
            if configuration_line not in device_configuration and configuration_line not in do_not_check:
                full_configuration_pushed = False

        if full_configuration_pushed == True:
            log('[{}] Configuration check was successful'.format(device),
                'info')
            return True
        else:
            log(
                '[{}] Configuration check failed, check configuration manually'
                .format(device), 'error')
            return False
Пример #28
0
def view(name):
    '''
	Summary:
	Prints attributes of a Deployment instance.
	
	Takes:
	name: Name of deployment to view information about
	'''
    Deployment.get_deployments_from_file()
    for deployment in deployments:
        if name in deployment:
            deployment_dict = deployment[name].all()
            log('Name: ' + str(deployment_dict['name']), 'info')
            log('Targets: ' + str(deployment_dict['targets']), 'info')
            log('Action: ' + str(deployment_dict['action']), 'info')
            log('ID: ' + str(deployment_dict['deployment_id']), 'info')
            log('Status: ' + str(deployment_dict['status']), 'info')
            return

    log('[{}] Deployment does not exist'.format(name), 'error')
Пример #29
0
def view(name):
    '''
	Summary:
	Prints attributes of a Device instance.

	Takes: 
	name: Name of device to view information about
	'''
    Device.get_devices_from_file()
    device_information = Device.get_device_information(name)
    if device_information != None:
        log('Name: ' + str(device_information['name']), 'info')
        log('IP: ' + str(device_information['ip']), 'info')
        log('Username: '******'username']), 'info')
        log('Password: '******'password']), 'info')
        log('OS: ' + str(device_information['os']), 'info')
    else:
        log('[{}] Device does not exist'.format(name), 'error')