Exemple #1
0
    def change_password(self, username, new_password, old_password, otp=None):
        """
        Set the password of a user. (Does not expire)

        :param username: User login (username)
        :type username: str
        :param new_password: New password for the user
        :type new_password: str
        :param old_password: Users old password
        :type old_password: str
        :param otp: User's OTP token if they have one
        :type otp: str or None
        """

        password_url = 'https://{0}/ipa/session/change_password'.format(
            self.current_host)
        headers = {
            'Content-Type': 'application/x-www-form-urlencoded',
            'Accept': 'text/plain',
        }

        data = {
            'user': username,
            'new_password': new_password,
            'old_password': old_password,
        }
        if otp:
            data['otp'] = otp

        response = self._session.post(password_url,
                                      headers=headers,
                                      data=data,
                                      verify=self._verify_ssl)

        if not response.ok:
            raise FreeIPAError(message=response.text,
                               code=response.status_code)

        pwchange_result = response.headers.get('X-IPA-Pwchange-Result', None)
        if pwchange_result != 'ok':
            if pwchange_result == 'invalid-password':
                raise PWChangeInvalidPassword(message=response.text,
                                              code=response.status_code)
            elif pwchange_result == 'policy-error':
                policy_error = response.headers.get(
                    'X-IPA-Pwchange-Policy-Error', None)
                raise PWChangePolicyError(
                    message=response.text,
                    code=response.status_code,
                    policy_error=policy_error,
                )
            else:
                raise FreeIPAError(message=response.text,
                                   code=response.status_code)
        return response
Exemple #2
0
 def dns_discovered(self):
     if isinstance(self._dns_discovery, str):
         _domain = self._dns_discovery
     elif self._dns_discovery:
         _domain = socket.getfqdn()
     else:
         raise FreeIPAError('neither host specified, not dns_discovery enabled')
     while True:
         try:
             return srvlookup.lookup('ldap', 'tcp', _domain)
         except srvlookup.SRVQueryFailure:
             try:
                 _domain = _domain.split('.', 1)[1]
             except IndexError:
                 raise FreeIPAError('could not find any IPA Server using DNS lookup')
Exemple #3
0
    def login_kerberos(self):
        """
        Login to FreeIPA server using existing Kerberos credentials.

        In order to use this method, the package ```requests_kerberos`` <https://pypi.org/project/requests-kerberos/>`_
        must be installed. There must already be a Kerberos Ticket-Granting Ticket (TGT) cached in a Kerberos credential
        cache. Whether a TGT is available can be easily determined by running the klist command. If no TGT is available,
        then it first must be obtained by running the kinit command, or pointing the ``$KRB5CCNAME`` environment
        variable to a credential cache with a valid TGT.

        :raises Unauthorized: raised if credentials are invalid.
        :raises ImportError: raised if the ``requests_kerberos`` module is unavailable.
        """
        if self._host:
            self._current_host = self._host
            return self._login_kerberos(self._host)
        else:
            for host in self.dns_discovered:
                try:
                    self._current_host = host.hostname
                    return self._login_kerberos(host.hostname)
                except requests.exceptions.ConnectionError as err:
                    self.log.warning(
                        "Could not connect discovered host: {0}".format(err))
            raise FreeIPAError("Could not connect to any host")
Exemple #4
0
    def _change_password(self, username, new_password, old_password, otp=None):
        """
        private function, use change_password instead
        """
        password_url = 'https://{0}/ipa/session/change_password'.format(
            self.current_host)
        headers = {
            'Content-Type': 'application/x-www-form-urlencoded',
            'Accept': 'text/plain',
        }

        data = {
            'user': username,
            'new_password': new_password,
            'old_password': old_password,
        }
        if otp:
            data['otp'] = otp

        response = self._session.post(password_url,
                                      headers=headers,
                                      data=data,
                                      verify=self._verify_ssl)

        if not response.ok:
            raise FreeIPAError(message=response.text,
                               code=response.status_code)

        pwchange_result = response.headers.get('X-IPA-Pwchange-Result', None)
        if pwchange_result != 'ok':
            if pwchange_result == 'invalid-password':
                raise PWChangeInvalidPassword(message=response.text,
                                              code=response.status_code)
            elif pwchange_result == 'policy-error':
                policy_error = response.headers.get(
                    'X-IPA-Pwchange-Policy-Error', None)
                raise PWChangePolicyError(
                    message=response.text,
                    code=response.status_code,
                    policy_error=policy_error,
                )
            else:
                raise FreeIPAError(message=response.text,
                                   code=response.status_code)
        return response
Exemple #5
0
    def _request(self, method, args=None, params=None):
        """
        Make an HTTP request to FreeIPA JSON RPC server.

        :param method: RPC method name is required
        :type method: str
        :param args: optional positional argument or list of arguments
        :type args: list or string
        :param params: optional named parameters
        :type params: dict
        :return: parsed response from the request
        :rtype: dict
        :raises FreeIPAError: if the response code is not OK
        """
        session_url = 'https://{0}/ipa/session/json'.format(self.current_host)
        headers = {
            'Referer': 'https://{0}/ipa'.format(self.current_host),
            'Content-Type': 'application/json',
            'Accept': 'application/json',
        }

        if not args:
            args = []
        elif not isinstance(args, list):
            args = [args]

        if not params:
            params = {}

        if self._version:
            params.setdefault('version', self._version)

        data = {'method': method, 'params': [args, params]}

        self.log.debug(
            'Making {method} request to {url} with arguments {args} and params {params}'
            .format(method=method, url=session_url, args=args, params=params))

        response = self._session.post(session_url,
                                      headers=headers,
                                      data=json.dumps(data),
                                      verify=self._verify_ssl)

        if response.status_code == 401:
            raise Unauthorized()

        if not response.ok:
            raise FreeIPAError(message=response.text,
                               code=response.status_code)

        result = response.json()
        error = result['error']
        if error:
            parse_error(error)
        else:
            return result['result']
Exemple #6
0
    def login(self, username, password):
        """
        Login to FreeIPA server using username and password.

        :param username: user to connect
        :type username: str
        :param password: password of the user
        :type password: str
        :raises Unauthorized: raised if credentials are invalid.
        """
        if self._host:
            self._current_host = self._host
            return self._login(self._host, username, password)
        else:
            for host in self.dns_discovered:
                try:
                    self._current_host = host.hostname
                    return self._login(host.hostname, username, password)
                except requests.exceptions.ConnectionError as err:
                    self.log.warning(
                        "Could not connect discovered host: {0}".format(err))
            raise FreeIPAError("Could not connect to any host")
Exemple #7
0
    def _wrap_in_dns_discovery(self, function, *args, **kwargs):
        """
        Wrap a function in DNS discovery.

        :param function: the function to wrap
        :type function: callable
        :param args: the function's arguments
        :type args: list
        :param kwargs: the function's keyword arguments
        :type kwargs: dict
        """
        if self._host:
            self._current_host = self._host
            return function(*args, **kwargs)
        else:
            for host in self.dns_discovered:
                try:
                    self._current_host = host.hostname
                    return function(*args, **kwargs)
                except requests.exceptions.ConnectionError as err:
                    self.log.warning(
                        "Could not connect discovered host: {0}".format(err))
            raise FreeIPAError("Could not connect to any host")