def login(self, username, password): login_path = LOGIN_URL data = { "dsCredentials": { "password": to_text(password), "userName": to_text(username), } } code, auth_token = self.send_request("POST", login_path, data=data) try: if code >= 400 and isinstance(auth_token, dict): raise AnsibleAuthenticationFailure( message="{0} Failed to acquire login token.".format( auth_token["error"].get("message") ) ) # This is still sent as an HTTP header, so we can set our connection's _auth # variable manually. If the token is returned to the device in another way, # you will have to keep track of it another way and make sure that it is sent # with the rest of the request from send_request() self.connection._auth = {"Cookie": "sID={0}".format(auth_token)} # Have to carry this around because variuous Trend Micro Deepsecurity REST # API endpoints want the sID as a querystring parameter instead of honoring # the session Cookie self._auth_token = auth_token except KeyError: raise AnsibleAuthenticationFailure( message="Failed to acquire login token." )
def fail_exit(module, e): if e.reason == "Unauthorized": raise AnsibleAuthenticationFailure(to_native(e.reason)) elif e.body is not None: err = json.loads(str(e.body)) raise AnsibleError(err["message"]) else: return module.exit_json(failed=True, msg=to_native(e.reason))
def login(self): _, repsonse_json = self.send_request( self.login_url, 'POST', data=urlencode(self._credentials), headers={ 'Accept': 'application/json', 'Content-Type': 'application/x-www-form-urlencoded' } ) try: self._uidaruba = repsonse_json['_global_result']['UIDARUBA'] except KeyError: raise AnsibleAuthenticationFailure('Failed to acquire UIDARUBA token from login response.')
def login(self, username, password): login_path = "/sepm/api/v1/identity/authenticate" data = {"username": username, "password": password} response, response_data = self.send_request("POST", login_path, data=to_bytes( json.dumps(data))) try: self.connection._auth = { "Authorization": "Bearer {0}".format(response_data["token"]) } except KeyError: raise AnsibleAuthenticationFailure( message="Failed to acquire login token.")
def _connect_uncached(self): ''' activates the connection object ''' if paramiko is None: raise AnsibleError("paramiko is not installed: %s" % to_native(PARAMIKO_IMPORT_ERR)) port = self._play_context.port or 22 display.vvv("ESTABLISH PARAMIKO SSH CONNECTION FOR USER: %s on PORT %s TO %s" % (self._play_context.remote_user, port, self._play_context.remote_addr), host=self._play_context.remote_addr) ssh = paramiko.SSHClient() # override paramiko's default logger name if self._log_channel is not None: ssh.set_log_channel(self._log_channel) self.keyfile = os.path.expanduser("~/.ssh/known_hosts") if self.get_option('host_key_checking'): for ssh_known_hosts in ("/etc/ssh/ssh_known_hosts", "/etc/openssh/ssh_known_hosts"): try: # TODO: check if we need to look at several possible locations, possible for loop ssh.load_system_host_keys(ssh_known_hosts) break except IOError: pass # file was not found, but not required to function ssh.load_system_host_keys() ssh_connect_kwargs = self._parse_proxy_command(port) ssh.set_missing_host_key_policy(MyAddPolicy(self._new_stdin, self)) conn_password = self.get_option('password') or self._play_context.password allow_agent = True if conn_password is not None: allow_agent = False try: key_filename = None if self._play_context.private_key_file: key_filename = os.path.expanduser(self._play_context.private_key_file) # paramiko 2.2 introduced auth_timeout parameter if LooseVersion(paramiko.__version__) >= LooseVersion('2.2.0'): ssh_connect_kwargs['auth_timeout'] = self._play_context.timeout # paramiko 1.15 introduced banner timeout parameter if LooseVersion(paramiko.__version__) >= LooseVersion('1.15.0'): ssh_connect_kwargs['banner_timeout'] = self.get_option('banner_timeout') ssh.connect( self._play_context.remote_addr.lower(), username=self._play_context.remote_user, allow_agent=allow_agent, look_for_keys=self.get_option('look_for_keys'), key_filename=key_filename, password=conn_password, timeout=self._play_context.timeout, port=port, **ssh_connect_kwargs ) except paramiko.ssh_exception.BadHostKeyException as e: raise AnsibleConnectionFailure('host key mismatch for %s' % e.hostname) except paramiko.ssh_exception.AuthenticationException as e: msg = 'Failed to authenticate: {0}'.format(to_text(e)) raise AnsibleAuthenticationFailure(msg) except Exception as e: msg = to_text(e) if u"PID check failed" in msg: raise AnsibleError("paramiko version issue, please upgrade paramiko on the machine running ansible") elif u"Private key file is encrypted" in msg: msg = 'ssh %s@%s:%s : %s\nTo connect as a different user, use -u <username>.' % ( self._play_context.remote_user, self._play_context.remote_addr, port, msg) raise AnsibleConnectionFailure(msg) else: raise AnsibleConnectionFailure(msg) return ssh
def run(self, tmp=None, task_vars=None): if task_vars is None: task_vars = dict() # uncomment to enable request debugging #try: # import http.client as http_client #except ImportError: # # Python 2 # import httplib as http_client # http_client.HTTPConnection.debuglevel = 1 ## #import logging #logLevel = logging.DEBUG #logging.basicConfig() #logging.getLogger().setLevel(logLevel) #requests_log = logging.getLogger("requests.packages.urllib3") #requests_log.setLevel(logLevel) #requests_log.propagate = True result = super(ActionModule, self).run(tmp, task_vars) self._task_vars = task_vars changed = False no_log = self._play_context.no_log if not no_log: display.v("args: %s" % (self._task.args)) check_mode = task_vars['ansible_check_mode'] display.v("check_mode: %s" % (check_mode)) try: # Get the tasmota host tasmota_host = self._get_arg_or_var('tasmota_host', task_vars['ansible_host']) command = self._get_arg_or_var('command') incoming_value = self._get_arg_or_var('value', None, False) if incoming_value is None: # early return when incoming_value is not provided result["changed"] = False result["skipped"] = True return result except Exception as err: display.v("got an exception: %s" % (err)) display.v("got an exception: " + err.message) return self._fail_result( result, "error during retrieving parameter '%s'" % (err.message)) if not no_log: display.v("incoming_value %s" % (incoming_value)) auth_params = {} try: user = self._get_arg_or_var("tasmota_user") password = self._get_arg_or_var('tasmota_password') auth_params = {'user': user, 'password': password} display.v("authentication parameters: %s" % (auth_params)) except: pass # Enable retries due to reboot of the devices session = requests.Session() session.mount("http://%s" % (tasmota_host), HTTPAdapter(Retry(total=5, backoff_factor=1.0))) endpoint_uri = "http://%s/cm" % (tasmota_host) status_params = copy.deepcopy(auth_params) status_params.update({'cmnd': command}) # execute command status_response = requests.get(url=endpoint_uri, params=status_params) # get response data data = status_response.json() display.v("data: %s, response code: %s" % (data, status_response.status_code)) warnings = [] resp_warn = data.get("WARNING") if resp_warn: # Prior to v8.2.3 authorization error has 200 ok status if status_response.status_code == 401 or resp_warn == "Need user=<username>&password=<password>": raise AnsibleAuthenticationFailure( "Missing/Invalid credentials") warnings.append(resp_warn) if status_response.status_code != 200: raise AnsibleRuntimeError("Unexpected response code: %s" % (status_response.status_code)) existing_value = unicode(data.get(command)) if (command.startswith('Rule')): display.vv("rule found!") existing_once = data.get("Once") existing_rules = data.get("Rules") existing_rule = data.get(command) existing_stop_on_error = data.get("StopOnError") if incoming_value in ["0", "1", "2"]: display.vv("disable, enable, toggle rule found") existing_value = self._translateResultStr(existing_value) elif incoming_value in ["4", "5"]: display.vv("disable, enable oneshot") existing_value = self._translateResultStr( existing_once, "4", "5") elif incoming_value.startswith("on"): display.vv("rule value found") existing_value = existing_rules elif (command.startswith('SetOption')): existing_value = self._translateResultStr(existing_value) elif (command.startswith('PowerRetain')): existing_value = self._translateResultStr(existing_value) elif (command == 'Module'): modules_ids = data.get(command).keys() existing_value = next(iter(modules_ids)) elif (command.startswith('Gpio')): gpios = data.get(command.upper()).keys() existing_value = next(iter(gpios)) elif (command == 'Template'): existing_value = data elif (command.startswith('Timers')): existing_value = self._translateResultStr(data.get('Timers')) elif (re.findall('Timer\d', command)): existing_value = data.get(command) elif (command == 'TimeStd' or command == 'TimeDst'): display.vv("TimeStd/TimeDst found!") existing_data = data.get(command) existing_day = existing_data.get("Day") existing_hemisphere = existing_data.get("Hemisphere") existing_hour = existing_data.get("Hour") existing_month = existing_data.get("Month") existing_offset = existing_data.get("Offset") existing_week = existing_data.get("Week") existing_value = "%s,%s,%s,%s,%s,%s" % ( existing_hemisphere, existing_week, existing_month, existing_day, existing_hour, existing_offset) elif (command == 'TuyaMCU'): # Return only relevant subset of fn/dp ids, ignoring the rest try: fn_id, dp_id = (int(x) for x in incoming_value.split(',')) except Exception as e: raise AnsibleOptionsError( "Invalid value '%s' for TuyaMCU: %s" % (incoming_value, e)) try: def our_entry(x): return fn_id == x['fnId'] or dp_id == x['dpId'] relevant_entries = list(filter(our_entry, data['TuyaMCU'])) relevant_entries = [ "%s,%s" % (x['fnId'], x['dpId']) for x in relevant_entries ] except KeyError as e: raise AnsibleRuntimeError("Invalid response: %s, error: %s" % (data, e)) if dp_id != 0: if len(relevant_entries) == 1: existing_value = relevant_entries[0] else: existing_value = relevant_entries else: if not relevant_entries: # Missing entries equals to disabled entry existing_value = incoming_value else: existing_value = relevant_entries elif (command == 'DimmerRange'): try: existing_value = "%s,%s" % (data[command]['Min'], data[command]['Max']) except Exception as e: raise AnsibleRuntimeError( "Invalid response payload: %s, error: %s" % (data, e)) display.v( "[%s] command: %s,\n\t existing_value: '%s',\n\t incoming_value: '%s'" % (tasmota_host, command, existing_value, incoming_value if not no_log else "")) display.v("[%s] existing_uri: %s" % (tasmota_host, endpoint_uri)) if existing_value != incoming_value: changed = True if not check_mode: change_params = copy.deepcopy(auth_params) # encode json if required if isinstance(incoming_value, dict): change_params.update({ 'cmnd': ("%s %s" % (command, json.dumps(incoming_value))) }) else: change_params.update( {'cmnd': ("%s %s" % (command, incoming_value))}) change_response = requests.get(url=endpoint_uri, params=change_params) if status_response.status_code != 200: raise AnsibleRuntimeError("Unexpected response code: %s" % (status_response.status_code)) if warnings: display.warning(warnings) result["warning"] = warnings result["changed"] = changed result["command"] = command result["tasmota_host"] = tasmota_host result["raw_data"] = data result["endpoint_uri"] = endpoint_uri result["incoming_value"] = incoming_value result["existing_value"] = existing_value return result
def raise_if_plus_a(definitely_not_underscore, mode): if mode == '+a': raise AnsibleAuthenticationFailure() return {'rc': 0, 'stdout': '', 'stderr': ''}