コード例 #1
0
 def _acquire_service_token(self,
                            username,
                            password,
                            service_target=None,
                            service_policy=None):
     """Retrieve service token"""
     logger = self.logger(self._acquire_service_token.__name__)
     payload = self._prepare_request_from_template(
         'SAML.xml', {
             'auth_url': self.__sts_profile.authorityUrl,
             'username': username,
             'password': password,
             'message_id': str(uuid.uuid4()),
             'created': self.__sts_profile.created,
             'expires': self.__sts_profile.expires,
             'issuer': self.__sts_profile.federationTokenIssuer
         })
     logger.debug_secrets('options: %s', payload)
     response = requests.post(
         self.__sts_profile.security_token_service_url,
         data=payload,
         headers={'Content-Type': 'application/x-www-form-urlencoded'})
     token = self._process_service_token_response(response)
     logger.debug_secrets('security token: %s', token)
     return token
コード例 #2
0
    def get_authentication_cookie(self):
        """Generate Auth Cookie"""
        logger = self.logger(self.get_authentication_cookie.__name__)

        logger.debug_secrets("self.FedAuth: %s\nself.rtFa: %s", self.FedAuth,
                             self.rtFa)
        return 'FedAuth=' + self.FedAuth + '; rtFa=' + self.rtFa
コード例 #3
0
    def acquire_service_token(self, options):
        """Retrieve service token"""
        logger = self.logger(self.acquire_service_token.__name__)
        logger.debug_secrets('options: %s', options)

        request_body = self.prepare_security_token_request({
            'username':
            options['username'],
            'password':
            options['password'],
            'endpoint':
            self.url
        })

        sts_url = 'https://' + options['sts']['host'] + options['sts']['path']
        response = requests.post(
            sts_url,
            data=request_body,
            headers={'Content-Type': 'application/x-www-form-urlencoded'})
        token = self.process_service_token_response(response)
        logger.debug_secrets('token: %s', token)
        if token:
            self.token = token
            return True
        return False
コード例 #4
0
 def get_authentication_cookie(self):
     """Build auth cookie"""
     logger = self.logger(self.get_authentication_cookie.__name__)
     logger.debug_secrets(self._auth_cookies)
     return "; ".join([
         "=".join([key, str(val)])
         for key, val in self._auth_cookies.items()
     ])
コード例 #5
0
    def acquire_service_token_from_adfs(self, adfs_url, username, password):
        logger = self.logger(self.acquire_service_token_from_adfs.__name__)
        payload = self._prepare_request_from_template(
            'FederatedSAML.xml', {
                'auth_url': adfs_url,
                'username': username,
                'password': password,
                'message_id': str(uuid.uuid4()),
                'created': self.__sts_profile.created,
                'expires': self.__sts_profile.expires,
                'issuer': self.__sts_profile.federationTokenIssuer
            })
        response = requests.post(
            adfs_url,
            data=payload,
            headers={'Content-Type': 'application/soap+xml; charset=utf-8'})
        try:
            xml = ElementTree.fromstring(response.content)
            # 1.find assertion
            assertion_node = xml.find(
                '{0}Body/{1}RequestSecurityTokenResponse/{1}RequestedSecurityToken/{2}Assertion'
                .format(self.__ns_prefixes['s'], self.__ns_prefixes['wst'],
                        self.__ns_prefixes['saml']))
            if assertion_node is None:
                self.error = 'Cannot get security assertion for user {0} from {1}'.format(
                    self.__username, adfs_url)
                logger.error(self.error)
                return None
            # 2. prepare & submit token request
            self.__sts_profile.signInPage = '_vti_bin/idcrl.svc'
            self.__sts_profile.securityTokenServicePath = 'rst2.srf'
            template = self._prepare_request_from_template(
                'RST2.xml', {
                    'auth_url':
                    self.__sts_profile.authorityUrl,
                    'serviceTokenUrl':
                    self.__sts_profile.security_token_service_url
                })
            template_xml = ElementTree.fromstring(template)
            security_node = template_xml.find('{0}Header/{1}Security'.format(
                self.__ns_prefixes['s'], self.__ns_prefixes['wsse']))

            security_node.insert(1, assertion_node)
            payload = ElementTree.tostring(template_xml).decode()
            # 3. get token
            response = requests.post(
                self.__sts_profile.security_token_service_url,
                data=payload,
                headers={'Content-Type': 'application/soap+xml'})
            token = self._process_service_token_response(response)
            logger.debug_secrets('security token: %s', token)
            return token
        except ElementTree.ParseError as e:
            self.error = 'An error occurred while parsing the server response: {}'.format(
                e)
            logger.error(self.error)
            return None
コード例 #6
0
    def prepare_security_token_request(params):
        """Construct the request body to acquire security token from STS endpoint"""
        logger = SamlTokenProvider.logger(SamlTokenProvider.prepare_security_token_request.__name__)
        logger.debug_secrets('params: %s', params)

        f = open(os.path.join(os.path.dirname(__file__), 'SAML.xml'))
        data = f.read()
        for key in params:
            data = data.replace('[' + key + ']', params[key])
        return data
コード例 #7
0
 def _prepare_request_from_template(template_name, params):
     """Construct the request body to acquire security token from STS endpoint"""
     logger = SamlTokenProvider.logger()
     logger.debug_secrets('params: %s', params)
     f = open(os.path.join(os.path.dirname(__file__), template_name))
     try:
         data = f.read()
         for key in params:
             data = data.replace('{' + key + '}', str(params[key]))
         return data
     finally:
         f.close()
コード例 #8
0
    def authenticate_request(self, request):
        """

        :param request:
        """
        logger = self.logger(self.authenticate_request.__name__)
        self.ensure_authentication_cookie()
        logger.debug_secrets(self._cached_auth_cookies)
        cookie_header_value = "; ".join([
            "=".join([key, str(val)])
            for key, val in self._cached_auth_cookies.items()
        ])
        request.set_header('Cookie', cookie_header_value)
コード例 #9
0
    def acquire_service_token_from_adfs(self, adfs_url, username, password):
        logger = self.logger(self.acquire_service_token_from_adfs.__name__)

        now = datetime.now(tz=timezone.utc)
        created = now.astimezone(timezone.utc).isoformat('T')[:-9] + 'Z'
        expires = (now + timedelta(minutes=10)).astimezone(
            timezone.utc).isoformat('T')[:-9] + 'Z'

        payload = self._prepare_request_from_template(
            'FederatedSAML.xml', {
                'auth_url': adfs_url,
                'message_id': str(uuid.uuid4()),
                'username': username,
                'password': password,
                'created': created,
                'expires': expires,
                'issuer': self.__sts_profile.federationTokenIssuer
            })

        response = requests.post(
            adfs_url,
            data=payload,
            headers={'Content-Type': 'application/soap+xml; charset=utf-8'})
        dom = minidom.parseString(response.content.decode())
        assertion_node = dom.getElementsByTagNameNS(
            "urn:oasis:names:tc:SAML:1.0:assertion", 'Assertion')[0].toxml()

        try:
            self.tenant = urlparse(self.__sts_profile.authorityUrl).netloc

            payload = self._prepare_request_from_template(
                'RST2.xml', {
                    'auth_url': self.tenant,
                    'serviceTokenUrl':
                    self.__sts_profile.security_token_service_url,
                    'assertion_node': assertion_node
                })

            # 3. get token
            response = requests.post(
                self.__sts_profile.security_token_service_url,
                data=payload,
                headers={'Content-Type': 'application/soap+xml'})
            token = self._process_service_token_response(response)
            logger.debug_secrets('security token: %s', token)
            return token
        except ElementTree.ParseError as e:
            self.error = 'An error occurred while parsing the server response: {}'.format(
                e)
            logger.error(self.error)
            return None
コード例 #10
0
    def _acquire_service_token_from_adfs(self, adfs_url):
        logger = self.logger(self._acquire_service_token_from_adfs.__name__)

        payload = self._prepare_request_from_template(
            'FederatedSAML.xml', {
                'auth_url': adfs_url,
                'message_id': str(uuid.uuid4()),
                'username': self._username,
                'password': self._password,
                'created': self._sts_profile.created,
                'expires': self._sts_profile.expires,
                'issuer': self._sts_profile.tokenIssuer
            })

        response = requests.post(
            adfs_url,
            data=payload,
            headers={'Content-Type': 'application/soap+xml; charset=utf-8'})
        dom = minidom.parseString(response.content.decode())
        assertion_node = dom.getElementsByTagNameNS(
            "urn:oasis:names:tc:SAML:1.0:assertion", 'Assertion')[0].toxml()

        try:
            payload = self._prepare_request_from_template(
                'RST2.xml', {
                    'auth_url': self._sts_profile.tenant,
                    'serviceTokenUrl':
                    self._sts_profile.security_token_service_url,
                    'assertion_node': assertion_node
                })

            # 3. get security token
            response = requests.post(
                self._sts_profile.security_token_service_url,
                data=payload,
                headers={'Content-Type': 'application/soap+xml'})
            token = self._process_service_token_response(response)
            logger.debug_secrets('security token: %s', token)
            return token
        except ElementTree.ParseError as e:
            self.error = 'An error occurred while parsing the server response: {}'.format(
                e)
            logger.error(self.error)
            return None
コード例 #11
0
    def process_service_token_response(self, response):
        logger = self.logger(self.process_service_token_response.__name__)
        logger.debug_secrets('response: %s\nresponse.content: %s', response,
                             response.content)

        xml = ElementTree.fromstring(response.content)
        ns_prefixes = {
            'S':
            '{http://www.w3.org/2003/05/soap-envelope}',
            'psf':
            '{http://schemas.microsoft.com/Passport/SoapServices/SOAPFault}',
            'wst':
            '{http://schemas.xmlsoap.org/ws/2005/02/trust}',
            'wsse':
            '{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}'
        }
        logger.debug_secrets("ns_prefixes: %s", ns_prefixes)

        # check for errors
        if xml.find('{0}Body/{0}Fault'.format(ns_prefixes['S'])) is not None:
            error = xml.find(
                '{0}Body/{0}Fault/{0}Detail/{1}error/{1}internalerror/{1}text'.
                format(ns_prefixes['S'], ns_prefixes['psf']))
            self.error = 'An error occurred while retrieving token: {0}'.format(
                error.text)
            logger.error(self.error)
            return None

        # extract token
        token = xml.find(
            '{0}Body/{1}RequestSecurityTokenResponse/{1}RequestedSecurityToken/{2}BinarySecurityToken'
            .format(ns_prefixes['S'], ns_prefixes['wst'], ns_prefixes['wsse']))
        logger.debug_secrets("token: %s", token)
        return token.text
コード例 #12
0
    def _get_authentication_cookie(self, security_token, federated=False):
        """Retrieve auth cookie from STS

        :type federated: bool
        :type security_token: str
        """
        logger = self.logger(self._get_authentication_cookie.__name__)

        session = requests.session()
        logger.debug_secrets("session: %s\nsession.post(%s, data=%s)", session,
                             self._sts_profile.signin_page_url, security_token)
        if not federated:
            session.post(
                self._sts_profile.signin_page_url,
                data=security_token,
                headers={'Content-Type': 'application/x-www-form-urlencoded'})
        else:
            idcrl_endpoint = "https://{}/_vti_bin/idcrl.svc/".format(
                self._sts_profile.tenant)
            session.get(idcrl_endpoint,
                        headers={
                            'User-Agent': 'Office365 Python Client',
                            'X-IDCRL_ACCEPTED': 't',
                            'Authorization':
                            'BPOSIDCRL {0}'.format(security_token)
                        })
        logger.debug_secrets("session.cookies: %s", session.cookies)
        cookies = requests.utils.dict_from_cookiejar(session.cookies)
        logger.debug_secrets("cookies: %s", cookies)
        if not is_valid_auth_cookies(cookies):
            self.error = "An error occurred while retrieving auth cookies from {0}".format(
                self._sts_profile.signin_page_url)
            logger.error(self.error)
            raise ValueError(self.error)
        return cookies
コード例 #13
0
    def _process_service_token_response(self, response):
        logger = self.logger(self._process_service_token_response.__name__)
        logger.debug_secrets('response: %s\nresponse.content: %s', response,
                             response.content)

        try:
            xml = ElementTree.fromstring(response.content)
        except ElementTree.ParseError as e:
            self.error = 'An error occurred while parsing the server response: {}'.format(
                e)
            logger.error(self.error)
            return None

        # check for errors
        if xml.find('{0}Body/{0}Fault'.format(
                self.__ns_prefixes['s'])) is not None:
            error = xml.find(
                '{0}Body/{0}Fault/{0}Detail/{1}error/{1}internalerror/{1}text'.
                format(self.__ns_prefixes['s'], self.__ns_prefixes['psf']))
            if error is None:
                self.error = 'An error occurred while retrieving token from XML response.'
            else:
                self.error = 'An error occurred while retrieving token from XML response: {0}'.format(
                    error.text)
            logger.error(self.error)
            return None

        # extract token
        token = xml.find(
            '{0}Body/{1}RequestSecurityTokenResponse/{1}RequestedSecurityToken/{2}BinarySecurityToken'
            .format(self.__ns_prefixes['s'], self.__ns_prefixes['wst'],
                    self.__ns_prefixes['wsse']))
        if token is None:
            self.error = 'Cannot get binary security token for from {0}'.format(
                self.__sts_profile.security_token_service_url)
            logger.error(self.error)
            return None
        logger.debug_secrets("token: %s", token)
        return token.text
コード例 #14
0
    def acquire_authentication_cookie(self, options):
        """Retrieve SPO auth cookie"""
        logger = self.logger(self.acquire_authentication_cookie.__name__)

        url = options['endpoint']

        session = requests.session()
        logger.debug_secrets("session: %s\nsession.post(%s, data=%s)", session, url, self.token)
        session.post(url, data=self.token, headers={'Content-Type': 'application/x-www-form-urlencoded'})
        logger.debug_secrets("session.cookies: %s", session.cookies)
        cookies = requests.utils.dict_from_cookiejar(session.cookies)
        logger.debug_secrets("cookies: %s", cookies)
        if 'FedAuth' in cookies and 'rtFa' in cookies:
            self.FedAuth = cookies['FedAuth']
            self.rtFa = cookies['rtFa']
            return True
        self.error = "An error occurred while retrieving auth cookies"
        logger.error(self.error)
        return False
コード例 #15
0
 def _acquire_authentication_cookie(self, security_token, federated=False):
     """Retrieve auth cookie from STS"""
     logger = self.logger(self._acquire_authentication_cookie.__name__)
     session = requests.session()
     logger.debug_secrets("session: %s\nsession.post(%s, data=%s)", session,
                          self.__sts_profile.signin_page_url,
                          security_token)
     if not federated:
         self._auth_cookies['FedAuth'] = None
         self._auth_cookies['rtFa'] = None
         session.post(
             self.__sts_profile.signin_page_url,
             data=security_token,
             headers={'Content-Type': 'application/x-www-form-urlencoded'})
     else:
         self._auth_cookies['SPOIDCRL'] = None
         session.head(self.__sts_profile.signin_page_url,
                      headers={
                          'User-Agent':
                          'Office365 Python Client',
                          'X-IDCRL_ACCEPTED':
                          't',
                          'Authorization':
                          'BPOSIDCRL {0}'.format(security_token),
                          'Content-Type':
                          'application/x-www-form-urlencoded'
                      })
     logger.debug_secrets("session.cookies: %s", session.cookies)
     cookies = requests.utils.dict_from_cookiejar(session.cookies)
     logger.debug_secrets("cookies: %s", cookies)
     if not cookies:
         self.error = "An error occurred while retrieving auth cookies from {0}".format(
             self.__sts_profile.signin_page_url)
         logger.error(self.error)
         return False
     for name in self._auth_cookies.keys():
         self._auth_cookies[name] = cookies[name]
     return True