def _delete_keys(stale_keys, minions): """ Delete the keys """ wheel = salt.wheel.WheelClient(__opts__) for k in stale_keys: log.info("Removing stale key for %s", k) wheel.cmd("key.delete", [salt.utils.stringutils.to_unicode(k)]) del minions[k] return minions
def start(interval=3600, expire=604800): ck = salt.utils.minions.CkMinions(__opts__) presence_file = '{0}/presence.p'.format(__opts__['cachedir']) wheel = salt.wheel.WheelClient(__opts__) while True: log.debug('Checking for present minions') minions = {} if os.path.exists(presence_file): try: with salt.utils.fopen(presence_file, 'r') as f: minions = msgpack.load(f) except IOError as e: log.error('Could not open presence file {0}: {1}'.format( presence_file, e)) time.sleep(interval) continue minion_keys = _get_keys() now = time.time() present = ck.connected_ids() # For our existing keys, check which are present for m in minion_keys: # If we have a key that's not in the presence file, it may be a new minion # It could also mean this is the first time this engine is running and no # presence file was found if m not in minions: minions[m] = now elif m in present: minions[m] = now log.debug('Finished checking for present minions') # Delete old keys stale_keys = [] for m, seen in six.iteritems(minions): if now - expire > seen: stale_keys.append(m) if len(stale_keys): for k in stale_keys: log.info('Removing stale key for {0}'.format(k)) wheel.cmd('key.delete', stale_keys) del minions[k] try: with salt.utils.fopen(presence_file, 'w') as f: msgpack.dump(minions, f) except IOError as e: log.error('Could not write to presence file {0}: {1}'.format( presence_file, e)) time.sleep(interval)
def start(interval=3600, expire=604800): ck = salt.utils.minions.CkMinions(__opts__) presence_file = "{0}/minions/presence.p".format(__opts__["cachedir"]) wheel = salt.wheel.WheelClient(__opts__) while True: log.debug("Checking for present minions") minions = {} if os.path.exists(presence_file): try: with salt.utils.fopen(presence_file, "r") as f: minions = msgpack.load(f) except IOError as e: log.error("Could not open presence file {0}: {1}".format(presence_file, e)) time.sleep(interval) continue minion_keys = _get_keys() now = time.time() present = ck.connected_ids() # For our existing keys, check which are present for m in minion_keys: # If we have a key that's not in the presence file, it may be a new minion # It could also mean this is the first time this engine is running and no # presence file was found if m not in minions: minions[m] = now elif m in present: minions[m] = now log.debug("Finished checking for present minions") # Delete old keys stale_keys = [] for m, seen in minions.iteritems(): if now - expire > seen: stale_keys.append(m) if len(stale_keys): for k in stale_keys: log.info("Removing stale key for {0}".format(k)) wheel.cmd("key.delete", stale_keys) del minions[k] try: with salt.utils.fopen(presence_file, "w") as f: msgpack.dump(minions, f) except IOError as e: log.error("Could not write to presence file {0}: {1}".format(presence_file, e)) time.sleep(interval)
def salt_keys_denied(): ret_denied = wheel.cmd('key.list', ['denied']) # if len(ret_denied['minions_denied']) == 0: # return None # else: # return ret_denied['minions_denied'] print ret_denied['minions_denied'] #def showkeys(): # shows = local.cmd('*', 'cmd.run', ['whoami']) ## local.cmd('*', 'cmd.run', ['whoami']) # print shows #salt_keys_denied() #keys_all() #keys_denied() #keys_acc() #keys_unacc() #keys_rej() #wheel.cmd('key.list_all') #import os #import os.path # #PATH='/var/run/salt-master.pid' # #if os.path.isfile(PATH) and os.access(PATH, os.R_OK): print "File exists and is readable"
def display_minions(): jj = _load_environment() context = {} context['conductors'] = list(conductors.keys()) key_states = wheel.cmd('key.list_all') context['key_states'] = key_states connected_minions = runner.cmd('manage.up') context['connected_minions'] = connected_minions page_template = jj.get_template('minions.j2') return page_template.render(context)
def wheel(self, fun, **kwargs): ''' Run :ref:`wheel modules <all-salt.wheel>` Wraps :py:meth:`salt.wheel.WheelClient.master_call`. :return: Returns the result from the wheel module ''' if kwargs.has_key('client'): kwargs.pop('client') kwargs['print_event'] = False wheel = salt.wheel.Wheel(self.opts) return wheel.cmd(fun, **kwargs)
def delete_salt_minion(minion_name): opts = salt.config.master_config('/etc/salt/master.d/susemanager.conf') wheel = salt.wheel.WheelClient(opts) minion_pre_list = wheel.cmd('key.list', ['pre']) if len(minion_pre_list['minions_pre']) > 0: for p in minion_pre_list['minions_pre']: if minion_name in p: p_dict = { 'minions_pre': [ p, ], } print("Deleting minion from pending key accept: %s" % p_dict) wheel.cmd_async({'fun': 'key.delete_dict', 'match': p_dict}) minion_denied_list = wheel.cmd('key.list', ['denied']) if len(minion_denied_list['minions_denied']) > 0: for p in minion_denied_list['minions_denied']: if minion_name in p: p_dict = { 'minions_denied': [ p, ], } print("Deleting minion from denied key: %s" % p_dict) wheel.cmd_async({'fun': 'key.delete_dict', 'match': p_dict}) minion_rejected_list = wheel.cmd('key.list', ['rejected']) if len(minion_rejected_list['minions_rejected']) > 0: for p in minion_rejected_list['minions_rejected']: if minion_name in p: p_dict = { 'minions_rejected': [ p, ], } print("Deleting minion from rejected key: %s" % p_dict) wheel.cmd_async({'fun': 'key.delete_dict', 'match': p_dict})
def get_minions(type='minions', use_cache=True): """ Build a cache using minions array. By default the type is minions and we use the cache """ global minions if use_cache and type in minions: return minions[type] wheel = salt.wheel.WheelClient(opts) keys = wheel.cmd('key.list_all') if type not in keys: raise SaltError('no key {0} in key.list_all'.format(type)) minions[type] = keys[type] return minions[type]
def clean_outfile(): try: with open('/tmp/total_down.json') as outfile: _total_down = json.load(outfile) except: log.error("Keys Maintenance Runner - can't open outfile") for minion in list(_total_down): ret = wheel.cmd('key.name_match', [minion]) if ret == {}: log.warning( "Keys Maintenance Runner - minion key %s does not exist, removing from json", minion) _total_down.pop(minion, None) return _total_down
def salt_call(minion_id, function=None, with_grains=True, with_pillar=True, preload_grains=True, preload_pillar=True, default_grains=None, default_pillar=None, cache_grains=False, cache_pillar=False, use_cached_grains=True, use_cached_pillar=True, use_existing_proxy=False, jid=None, args=(), **kwargs): ''' Invoke a Salt Execution Function that requires or invokes an NAPALM functionality (directly or indirectly). minion_id: The ID of the Minion to compile Pillar data for. function The name of the Salt function to invoke. preload_grains: ``True`` Whether to preload the Grains before establishing the connection with the remote network device. default_grains: Dictionary of the default Grains to make available within the functions loaded. with_grains: ``True`` Whether to load the Grains modules and collect Grains data and make it available inside the Execution Functions. The Grains will be loaded after opening the connection with the remote network device. preload_pillar: ``True`` Whether to preload Pillar data before opening the connection with the remote network device. default_pillar: Dictionary of the default Pillar data to make it available within the functions loaded. with_pillar: ``True`` Whether to load the Pillar modules and compile Pillar data and make it available inside the Execution Functions. use_cached_pillar: ``True`` Use cached Pillars whenever possible. If unable to gather cached data, it falls back to compiling the Pillar. use_cached_grains: ``True`` Use cached Grains whenever possible. If unable to gather cached data, it falls back to collecting Grains. cache_pillar: ``False`` Cache the compiled Pillar data before returning. .. warning:: This option may be dangerous when targeting a device that already has a Proxy Minion associated, however recommended otherwise. cache_grains: ``False`` Cache the collected Grains before returning. .. warning:: This option may be dangerous when targeting a device that already has a Proxy Minion associated, however recommended otherwise. use_existing_proxy: ``False`` Use the existing Proxy Minions when they are available (say on an already running Master). jid: ``None`` The JID to pass on, when executing. arg The list of arguments to send to the Salt function. kwargs Key-value arguments to send to the Salt function. CLI Example: .. code-block:: bash salt-run proxy.salt_call bgp.neighbors junos 1.2.3.4 test test123 salt-run proxy.salt_call net.load_config junos 1.2.3.4 test test123 text='set system ntp peer 1.2.3.4' ''' if use_existing_proxy: # When using the existing Proxies, simply send the command to the # Minion through the ``salt.execute`` Runner. # But first, check if the Minion ID is accepted, otherwise, continue # and execute the function withing this Runner. wheel = salt.wheel.WheelClient(__opts__) accepted_minions = wheel.cmd('key.list', ['accepted'], print_event=False).get('minions', []) if minion_id in accepted_minions: log.debug( '%s seems to be a valid Minion, trying to spread out the command', minion_id, ) log.info( 'If %s is not responding, you might want to run without --use-existing-proxy', minion_id, ) ret = __salt__['salt.execute'](minion_id, function, arg=args, kwarg=kwargs, jid=jid) return ret.get(minion_id) else: log.debug( '%s doesn\'t seem to be a valid existing Minion, executing locally', minion_id, ) opts = copy.deepcopy(__opts__) opts['id'] = minion_id opts['pillarenv'] = __opts__.get('pillarenv', 'base') opts['__cli'] = __opts__.get('__cli', 'salt-call') if 'saltenv' not in opts: opts['saltenv'] = 'base' if not default_grains: default_grains = {} if use_cached_grains or use_cached_pillar: minion_cache = __salt__['cache.fetch']('minions/{}'.format(minion_id), 'data') opts['grains'] = default_grains if not default_pillar: default_pillar = {} opts['pillar'] = default_pillar opts['proxy_load_pillar'] = with_pillar opts['proxy_load_grains'] = with_grains opts['proxy_preload_pillar'] = preload_pillar opts['proxy_preload_grains'] = preload_grains opts['proxy_cache_grains'] = cache_grains opts['proxy_cache_pillar'] = cache_pillar opts['proxy_use_cached_grains'] = use_cached_grains if use_cached_grains: opts['proxy_cached_grains'] = minion_cache.get('grains') opts['proxy_use_cached_pillar'] = use_cached_pillar if use_cached_pillar: opts['proxy_cached_pillar'] = minion_cache.get('pillar') sa_proxy = StandaloneProxy(opts) kwargs = clean_kwargs(**kwargs) ret = None try: ret = sa_proxy.functions[function](*args, **kwargs) except Exception as err: log.error(err, exc_info=True) finally: shut_fun = '{}.shutdown'.format(sa_proxy.opts['proxy']['proxytype']) sa_proxy.proxy[shut_fun](opts) if cache_grains: __salt__['cache.store']('minions/{}/data'.format(minion_id), 'grains', sa_proxy.opts['grains']) if cache_pillar: __salt__['cache.store']('minions/{}/data'.format(minion_id), 'pillar', sa_proxy.opts['pillar']) return ret
def salt_call( minion_id, function=None, unreachable_devices=None, failed_devices=None, with_grains=True, with_pillar=True, preload_grains=True, preload_pillar=True, default_grains=None, default_pillar=None, cache_grains=False, cache_pillar=False, use_cached_grains=True, use_cached_pillar=True, use_existing_proxy=False, no_connect=False, jid=None, roster_opts=None, test_ping=False, tgt=None, tgt_type=None, preload_targeting=False, invasive_targeting=False, failhard=False, timeout=60, returner='', returner_config='', returner_kwargs={}, args=(), **kwargs ): ''' Invoke a Salt Execution Function that requires or invokes an NAPALM functionality (directly or indirectly). minion_id: The ID of the Minion to compile Pillar data for. function The name of the Salt function to invoke. preload_grains: ``True`` Whether to preload the Grains before establishing the connection with the remote network device. default_grains: Dictionary of the default Grains to make available within the functions loaded. with_grains: ``True`` Whether to load the Grains modules and collect Grains data and make it available inside the Execution Functions. The Grains will be loaded after opening the connection with the remote network device. preload_pillar: ``True`` Whether to preload Pillar data before opening the connection with the remote network device. default_pillar: Dictionary of the default Pillar data to make it available within the functions loaded. with_pillar: ``True`` Whether to load the Pillar modules and compile Pillar data and make it available inside the Execution Functions. use_cached_pillar: ``True`` Use cached Pillars whenever possible. If unable to gather cached data, it falls back to compiling the Pillar. use_cached_grains: ``True`` Use cached Grains whenever possible. If unable to gather cached data, it falls back to collecting Grains. cache_pillar: ``False`` Cache the compiled Pillar data before returning. .. warning:: This option may be dangerous when targeting a device that already has a Proxy Minion associated, however recommended otherwise. cache_grains: ``False`` Cache the collected Grains before returning. .. warning:: This option may be dangerous when targeting a device that already has a Proxy Minion associated, however recommended otherwise. use_existing_proxy: ``False`` Use the existing Proxy Minions when they are available (say on an already running Master). no_connect: ``False`` Don't attempt to initiate the connection with the remote device. Default: ``False`` (it will initiate the connection). jid: ``None`` The JID to pass on, when executing. test_ping: ``False`` When using the existing Proxy Minion with the ``use_existing_proxy`` option, can use this argument to verify also if the Minion is responsive. arg The list of arguments to send to the Salt function. kwargs Key-value arguments to send to the Salt function. CLI Example: .. code-block:: bash salt-run proxy.salt_call bgp.neighbors junos 1.2.3.4 test test123 salt-run proxy.salt_call net.load_config junos 1.2.3.4 test test123 text='set system ntp peer 1.2.3.4' ''' if use_existing_proxy: # When using the existing Proxies, simply send the command to the # Minion through the ``salt.execute`` Runner. # But first, check if the Minion ID is accepted, otherwise, continue # and execute the function withing this Runner. wheel = salt.wheel.WheelClient(__opts__) accepted_minions = wheel.cmd('key.list', ['accepted'], print_event=False).get( 'minions', [] ) if minion_id in accepted_minions: log.debug( '%s seems to be a valid Minion, trying to spread out the command', minion_id, ) log.info( 'If %s is not responding, you might want to run without --use-existing-proxy, or with --test-ping', minion_id, ) test_ping_succeeded = True if test_ping: log.debug('Checking if the Minion %s is responsive', minion_id) ret = __salt__['salt.execute'](minion_id, 'test.ping', jid=jid) test_ping_succeeded = ret.get(minion_id, False) if test_ping_succeeded: ret = __salt__['salt.execute']( minion_id, function, arg=args, kwarg=kwargs, jid=jid ) return ret.get(minion_id) else: log.info( 'Looks like the Minion %s is not responsive, executing locally', minion_id, ) else: log.debug( '%s doesn\'t seem to be a valid existing Minion, executing locally', minion_id, ) opts = copy.deepcopy(__opts__) opts['id'] = minion_id opts['pillarenv'] = __opts__.get('pillarenv', 'base') opts['__cli'] = __opts__.get('__cli', 'salt-call') opts['__tgt'] = tgt opts['__tgt_type'] = tgt_type if 'saltenv' not in opts: opts['saltenv'] = 'base' if not default_grains: default_grains = {} if use_cached_grains or use_cached_pillar: minion_cache = __salt__['cache.fetch']('minions/{}'.format(minion_id), 'data') opts['grains'] = default_grains if not default_pillar: default_pillar = {} opts['pillar'] = default_pillar opts['proxy_load_pillar'] = with_pillar opts['proxy_load_grains'] = with_grains opts['proxy_preload_pillar'] = preload_pillar opts['proxy_preload_grains'] = preload_grains opts['proxy_cache_grains'] = cache_grains opts['proxy_cache_pillar'] = cache_pillar opts['preload_targeting'] = preload_targeting opts['invasive_targeting'] = invasive_targeting opts['proxy_use_cached_grains'] = use_cached_grains opts['proxy_no_connect'] = no_connect opts['proxy_test_ping'] = test_ping if use_cached_grains: opts['proxy_cached_grains'] = minion_cache.get('grains') opts['proxy_use_cached_pillar'] = use_cached_pillar if use_cached_pillar: opts['proxy_cached_pillar'] = minion_cache.get('pillar') opts['roster_opts'] = roster_opts opts['returner'] = returner minion_defaults = salt.config.DEFAULT_MINION_OPTS.copy() minion_defaults.update(salt.config.DEFAULT_PROXY_MINION_OPTS) for opt, val in six.iteritems(minion_defaults): if opt not in opts: opts[opt] = val sa_proxy = StandaloneProxy(opts, unreachable_devices) if not sa_proxy.ready: log.debug( 'The SProxy Minion for %s is not able to start up, aborting', opts['id'] ) return kwargs = clean_kwargs(**kwargs) ret = None try: ret = sa_proxy.functions[function](*args, **kwargs) except Exception as err: log.error('Exception while running %s on %s', function, opts['id']) log.error(err, exc_info=True) if failed_devices is not None: failed_devices.append(opts['id']) if failhard: raise else: if returner: returner_fun = '{}.returner'.format(returner) if returner_fun in sa_proxy.returners: log.error('Sending the response from %s to the %s Returner', opts['id'], returner) ret_data = { 'id': opts['id'], 'jid': jid, 'fun': function, 'fun_args': args, 'return': ret, 'ret_config': returner_config, 'ret_kwargs': returner_kwargs, } try: sa_proxy.returners[returner_fun](ret_data) except Exception as err: log.error('Exception while sending the response from %s to the %s returner', opts['id'], returner) log.error(err, exc_info=True) else: log.warning('Returner %s is not available. Check that the dependencies are properly installed') finally: if sa_proxy.connected: shut_fun = '{}.shutdown'.format(sa_proxy.opts['proxy']['proxytype']) sa_proxy.proxy[shut_fun](opts) if cache_grains: log.debug('Caching Grains for %s', minion_id) log.debug(sa_proxy.opts['grains']) cache_store = __salt__['cache.store']( 'minions/{}/data'.format(minion_id), 'grains', sa_proxy.opts['grains'] ) if cache_pillar: log.debug('Caching Pillar for %s', minion_id) cached_store = __salt__['cache.store']( 'minions/{}/data'.format(minion_id), 'pillar', sa_proxy.opts['pillar'] ) return ret
def delete_minion(): minion = request.form.get('minion') wheel.cmd('key.delete', [minion]) return "Salt Key for minion {} deleted".format(minion)
def keys_rej(): ret = wheel.cmd('key.list', ['rejected']) # wheel.cmd('key.list_all') return ret['minions_rejected']
def salt_keys_unaccepted(): ret_unacc = wheel.cmd('key.list', ['unaccepted']) # return ret_unacc['minions_pre'] return ret_unacc
def accept_minion(): minion = request.form.get('minion') wheel.cmd('key.accept', [minion]) return "Accepted Salt Key for minion {}".format(minion)
def key_create(id_, host, force=False): ''' Generates minion keypair, accepts it on master and injects it to minion via SSH. :param id_: expected minion ID of target node :param host: IP address or resolvable hostname/FQDN of target node CLI Examples: .. code-block:: bash salt-call saltkey.key_create <MINION_ID> <MINION_IP_ADDRESS> force=False ''' ret = { 'retcode': 0, 'msg': 'Salt Key for minion %s is already accepted' % id_, } opts = salt.config.master_config('/etc/salt/master') wheel = salt.wheel.WheelClient(opts) keys = wheel.cmd('key.gen_accept', arg=[id_], kwarg={'force': force}) pub_key = keys.get('pub', None) priv_key = keys.get('priv', None) if pub_key and priv_key: ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) # Establish SSH connection to minion try: ssh.connect(host) except paramiko.ssh_exception.AuthenticationException: msg = ( 'Could not establish SSH connection to minion "%s" on address %s, please ensure ' 'that current user\'s SSH key is present in minions authorized_keys.' ) % (id_, host) LOG.error(msg) ret['retcode'] = 1 ret['msg'] = msg wheel.cmd_async({'fun': 'key.delete', 'match': id_}) return ret except Exception as e: msg = ('Unknown error occured while establishing SSH connection ' 'to minion "%s" on address %s: %s') % (id_, host, repr(e)) LOG.error(msg) ret['retcode'] = 1 ret['msg'] = msg wheel.cmd_async({'fun': 'key.delete', 'match': id_}) return ret # Setup the keys on minion side the ugly way, nice one didn't work key_path = '/etc/salt/pki/minion' command = ( 'echo "%(pub_key)s" > %(pub_path)s && chmod 644 %(pub_path)s && ' 'echo "%(priv_key)s" > %(priv_path)s && chmod 400 %(priv_path)s && ' 'salt-call --local service.restart salt-minion') % { 'pub_path': os.path.join(key_path, 'minion.pub'), 'pub_key': pub_key, 'priv_path': os.path.join(key_path, 'minion.pem'), 'priv_key': priv_key } ssh_chan = ssh.get_transport().open_session() ssh_chan.exec_command(command) # Wait for command return while True: if ssh_chan.exit_status_ready(): exit_status = ssh_chan.recv_exit_status() stderr = ssh_chan.recv_stderr(1000) stdout = ssh_chan.recv(1000) break ssh.close() # Evaluate SSH command exit status if exit_status != 0: msg = 'Keypair injection to Salt minion failed on target with following error: %s' % stderr LOG.error(msg) ret['retcode'] = exit_status ret['msg'] = msg return ret ret['msg'] = 'Salt Key successfully created' return ret
def _delete_key(minion_id): # wheel = salt.wheel.Wheel(master_opts) # wheel.call_func('key.delete', match=minion) wheel = salt.wheel.WheelClient(master_opts) wheel.cmd('key.delete', [minion_id])
def saltstack_view(): error = None if request.method == 'GET': salt_svc_check = salt_service_check() salt_keys_acc = salt_keys_accepted() salt_keys_unacc = salt_keys_unaccepted() salt_keys_den = salt_keys_denied() salt_keys_rej = salt_keys_rejected() return render_template('saltstack.html', pxe_nodes=Saltstack_pxe_nodes.query.all(), salt_svc_check=salt_svc_check, salt_keys_acc=salt_keys_acc, salt_keys_unacc=salt_keys_unacc, salt_keys_den=salt_keys_den, salt_keys_rej=salt_keys_rej) elif request.method == 'POST': if 'salt_keys_denied_delete' in request.form: if not request.form['salt_keys_denied_delete'] or request.form[ 'key_ip'] == '': flash('Please fill all the fields before sending a request!', 'danger') return redirect(request.url) else: key_ip = request.form['key_ip'] wheel.cmd_async({'fun': 'key.delete', 'match': key_ip}) pxe_node = Saltstack_pxe_nodes.query.filter_by( pxeipaddr=key_ip).first() if str(key_ip) == str(pxe_node): db.session.delete(pxe_node) db.session.commit() flash('Requested key ' + key_ip + ' has been removed!', 'success') return redirect(request.url) elif 'salt_keys_rejected_delete' in request.form: if not request.form['salt_keys_rejected_delete'] or request.form[ 'key_ip'] == '': flash('Please fill all the fields before sending a request!', 'danger') return redirect(request.url) else: key_ip = request.form['key_ip'] wheel.cmd_async({'fun': 'key.delete', 'match': key_ip}) pxe_node = Saltstack_pxe_nodes.query.filter_by( pxeipaddr=key_ip).first() if str(key_ip) == str(pxe_node): db.session.delete(pxe_node) db.session.commit() flash('Requested key ' + key_ip + ' has been removed!', 'success') return redirect(request.url) elif 'salt_keys_unaccepted_accept' in request.form: if not request.form['salt_keys_unaccepted_accept'] or request.form[ 'key_ip'] == '': flash('Please fill all the fields before sending a request!', 'danger') return redirect(request.url) else: key_ip = request.form['key_ip'] wheel.cmd('key.accept', [key_ip]) flash('Requested key ' + key_ip + ' has been accepted!', 'success') return redirect(request.url) elif 'salt_keys_unaccepted_delete' in request.form: if not request.form['salt_keys_unaccepted_delete'] or request.form[ 'key_ip'] == '': flash('Please fill all the fields before sending a request!', 'danger') return redirect(request.url) else: key_ip = request.form['key_ip'] wheel.cmd_async({'fun': 'key.delete', 'match': key_ip}) pxe_node = Saltstack_pxe_nodes.query.filter_by( pxeipaddr=key_ip).first() if str(key_ip) == str(pxe_node): db.session.delete(pxe_node) db.session.commit() flash('Requested key ' + key_ip + ' has been removed!', 'success') return redirect(request.url) elif 'salt_keys_accepted_delete' in request.form: if not request.form['salt_keys_accepted_delete'] or request.form[ 'key_ip'] == '': flash('Please fill all the fields before sending a request!', 'danger') return redirect(request.url) else: key_ip = request.form['key_ip'] wheel.cmd_async({'fun': 'key.delete', 'match': key_ip}) pxe_node = Saltstack_pxe_nodes.query.filter_by( pxeipaddr=key_ip).first() if str(key_ip) == str(pxe_node): db.session.delete(pxe_node) db.session.commit() flash('Requested key ' + key_ip + ' has been removed!', 'success') return redirect(request.url) elif 'salt_keys_audit_save' in request.form: if not request.form['salt_keys_audit_save'] or request.form[ 'key_ip'] == '': flash('Please fill all the fields before sending a request!', 'danger') return redirect(request.url) else: key_ip = request.form['key_ip'] pxe_node_check = Saltstack_pxe_nodes.query.filter_by( pxeipaddr=key_ip).first() if str(key_ip) == str(pxe_node_check): flash( 'Candidate ' + key_ip + ' has already been audited !', 'danger') return redirect(request.url) else: pxe_int_name = local.cmd(key_ip, 'network.ifacestartswith', [key_ip]) pxe_mac_addr = local.cmd(key_ip, 'network.hwaddr', [pxe_int_name[key_ip][0]]) pxe_node = Saltstack_pxe_nodes(key_ip, pxe_int_name[key_ip][0], pxe_mac_addr[key_ip]) db.session.add(pxe_node) db.session.commit() # print pxe_int_name[key_ip][0], pxe_mac_addr[key_ip] flash( 'Requested key ' + key_ip + ' has been audited! INT: ' + pxe_int_name[key_ip][0] + ' MAC: ' + pxe_mac_addr[key_ip] + ' ', 'success') return redirect(request.url) else: flash('Malformed form submitted !', 'danger') return redirect(request.url)
def salt_keys_rejected(): ret_rej = wheel.cmd('key.list', ['rejected']) return ret_rej
def salt_keys_denied(): ret_denied = wheel.cmd('key.list', ['denied']) return ret_denied
def execute(tgt, function=None, tgt_type='glob', roster=None, preview_target=False, target_details=False, timeout=60, with_grains=True, with_pillar=True, preload_grains=True, preload_pillar=True, default_grains=None, default_pillar=None, args=(), batch_size=10, sync=False, events=True, cache_grains=False, cache_pillar=False, use_cached_grains=True, use_cached_pillar=True, use_existing_proxy=False, **kwargs): ''' Invoke a Salt function on the list of devices matched by the Roster subsystem. tgt The target expression, e.g., ``*`` for all devices, or ``host1,host2`` for a list, etc. The ``tgt_list`` argument must be used accordingly, depending on the type of this expression. function The name of the Salt function to invoke. tgt_type: ``glob`` The type of the ``tgt`` expression. Choose between: ``glob`` (default), ``list``, ``pcre``, ``rage``, or ``nodegroup``. roster: ``None`` The name of the Roster to generate the targets. Alternatively, you can specify the name of the Roster by configuring the ``proxy_roster`` option into the Master config. preview_target: ``False`` Return the list of Roster targets matched by the ``tgt`` and ``tgt_type`` arguments. preload_grains: ``True`` Whether to preload the Grains before establishing the connection with the remote network device. default_grains: Dictionary of the default Grains to make available within the functions loaded. with_grains: ``True`` Whether to load the Grains modules and collect Grains data and make it available inside the Execution Functions. The Grains will be loaded after opening the connection with the remote network device. default_pillar: Dictionary of the default Pillar data to make it available within the functions loaded. with_pillar: ``True`` Whether to load the Pillar modules and compile Pillar data and make it available inside the Execution Functions. arg The list of arguments to send to the Salt function. kwargs Key-value arguments to send to the Salt function. batch_size: ``10`` The size of each batch to execute. sync: ``False`` Whether to return the results synchronously (or return them as soon as the device replies). events: ``True`` Whether should push events on the Salt bus, similar to when executing equivalent through the ``salt`` command. use_cached_pillar: ``True`` Use cached Pillars whenever possible. If unable to gather cached data, it falls back to compiling the Pillar. use_cached_grains: ``True`` Use cached Grains whenever possible. If unable to gather cached data, it falls back to collecting Grains. cache_pillar: ``False`` Cache the compiled Pillar data before returning. .. warning:: This option may be dangerous when targeting a device that already has a Proxy Minion associated, however recommended otherwise. cache_grains: ``False`` Cache the collected Grains before returning. .. warning:: This option may be dangerous when targeting a device that already has a Proxy Minion associated, however recommended otherwise. use_existing_proxy: ``False`` Use the existing Proxy Minions when they are available (say on an already running Master). CLI Example: .. code-block:: bash salt-run proxy.execute_roster edge* test.ping salt-run proxy.execute_roster junos-edges test.ping tgt_type=nodegroup ''' targets = [] roster = roster or __opts__.get('proxy_roster', __opts__.get('roster')) if not roster or roster == 'None': log.info( 'No Roster specified. Please use the ``roster`` argument, or set the ``proxy_roster`` option in the ' 'Master configuration.') targets = [] if use_existing_proxy: # When targeting exiting Proxies, we're going to look and match the # accepted keys log.debug( 'Requested to match the target based on the existing Minions') wheel = salt.wheel.WheelClient(__opts__) if tgt_type == 'list': # accepted_minions = wheel.cmd( # 'key.list', ['accepted'], print_event=False # ).get('minions', []) # log.debug('This Master has the following Minions accepted:') # log.debug(accepted_minions) # targets = [accepted for accepted in accepted_minions if accepted in tgt] # TODO: temporarily deactivated the above, as I thought it might # make more sense to try to execute best efforts on any of the # Minions listed, and later it will be checked if it's possible # to execute on an existing Minion or withing this Runner. # TBD if that's the right decision, re-evaluate while it's still # in beta release. targets = tgt[:] elif tgt_type == 'glob': targets = wheel.cmd('key.name_match', [tgt], print_event=False).get('minions', []) else: # Try a fuzzy match based on the exact target the user requested # only when not attempting to match an existing Proxy. If you do # want however, it won't be of much use, as the command is going to # be spread out to non-existing minions, so better turn off that # feature. log.debug('Trying a fuzzy match on the target') if tgt_type == 'list': targets = tgt[:] elif tgt_type == 'glob' and tgt != '*': targets = [tgt] else: log.debug('Computing the target using the %s Roster', roster) roster_modules = salt.loader.roster(__opts__, runner=__salt__) if '.targets' not in roster: roster = '{mod}.targets'.format(mod=roster) rtargets = roster_modules[roster](tgt, tgt_type=tgt_type) targets = list(rtargets.keys()) log.debug('The target expression "%s" (%s) matched the following:', str(tgt), tgt_type) log.debug(targets) if not targets: return 'No devices matched your target. Please review your tgt / tgt_type arguments, or the Roster data source' if preview_target: return targets elif not function: return 'Please specify a Salt function to execute.' jid = kwargs.get('__pub_jid') if not jid: if salt.version.__version_info__ >= (2018, 3, 0): jid = salt.utils.jid.gen_jid(__opts__) else: jid = salt.utils.jid.gen_jid() if events: __salt__['event.send'](jid, {'minions': targets}) return execute_devices(targets, function, tgt=tgt, tgt_type=tgt_type, with_grains=with_grains, preload_grains=preload_grains, with_pillar=with_pillar, preload_pillar=preload_pillar, default_grains=default_grains, default_pillar=default_pillar, args=args, batch_size=batch_size, sync=sync, events=events, cache_grains=cache_grains, cache_pillar=cache_pillar, use_cached_grains=use_cached_grains, use_cached_pillar=use_cached_pillar, use_existing_proxy=use_existing_proxy, **kwargs)
def keys_acc(): ret = wheel.cmd('key.list', ['accepted']) # wheel.cmd('key.list_all') return ret['minions']
def keys_denied(): ret = wheel.cmd('key.list', ['denied']) # wheel.cmd('key.list_all') return ret['minions_denied']
def keys_all(): ret = wheel.cmd('key.list_all') # wheel.cmd('key.list_all') return ret
def salt_keys_accepted(): ret_acc = wheel.cmd('key.list', ['accepted']) # return ret_acc['minions'] return ret_acc
def keys_unacc(): ret = wheel.cmd('key.list', ['unaccepted']) # wheel.cmd('key.list_all') return ret['minions_pre']
def testing(): ret = {} dupa = wheel.cmd('key.list', ['all']) return ret