Пример #1
0
    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.')
Пример #4
0
    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.")
Пример #5
0
    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
Пример #6
0
    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
Пример #7
0
 def raise_if_plus_a(definitely_not_underscore, mode):
     if mode == '+a':
         raise AnsibleAuthenticationFailure()
     return {'rc': 0, 'stdout': '', 'stderr': ''}