Пример #1
0
    async def test_cis2_user_restricted_scope_combination(
        self,
        product_1_scopes,
        product_2_scopes,
        expected_filtered_scopes,
        test_app_and_product,
        helper,
    ):
        test_product, test_product2, test_app = test_app_and_product

        await test_product.update_scopes(product_1_scopes)
        await test_product2.update_scopes(product_2_scopes)
        apigee_trace = ApigeeApiTraceDebug(proxy=config.SERVICE_NAME)

        callback_url = await test_app.get_callback_url()
        oauth = OauthHelper(test_app.client_id, test_app.client_secret,
                            callback_url)

        apigee_trace.add_trace_filter(header_name="Auto-Test-Header",
                                      header_value="flow-callback")
        await apigee_trace.start_trace()

        assert helper.check_endpoint(
            verb="POST",
            endpoint=f"{config.OAUTH_URL}/token",
            expected_status_code=200,
            expected_response=[
                "access_token",
                "expires_in",
                "refresh_count",
                "refresh_token",
                "refresh_token_expires_in",
                "sid",
                "token_type",
            ],
            data={
                "client_id": test_app.get_client_id(),
                "client_secret": test_app.get_client_secret(),
                "redirect_uri": callback_url,
                "grant_type": "authorization_code",
                "code": await oauth.get_authenticated_with_simulated_auth(),
            },
        )

        user_restricted_scopes = await apigee_trace.get_apigee_variable_from_trace(
            name="apigee.user_restricted_scopes")
        assert (
            user_restricted_scopes is not None
        ), "variable apigee.user_restricted_scopes not found in the trace"
        user_restricted_scopes = user_restricted_scopes.split(" ")
        assert expected_filtered_scopes.sort() == user_restricted_scopes.sort()
    async def test_access_token_fields_for_logging_when_using_token_exchange_cis2(self):
        # Given
        apigee_trace = ApigeeApiTraceDebug(proxy=f"hello-world-{ENVIRONMENT}")

        id_token_jwt = self.oauth.create_id_token_jwt()
        client_assertion_jwt = self.oauth.create_jwt(kid='test-1')
        resp = await self.oauth.get_token_response(grant_type='token_exchange', _jwt=client_assertion_jwt,
                                                   id_token_jwt=id_token_jwt)
        access_token = resp['body']['access_token']

        # When
        await apigee_trace.start_trace()
        requests.get(f"{HELLO_WORLD_API_URL}", headers={"Authorization": f"Bearer {access_token}"})

        # Then
        auth_type = await apigee_trace.get_apigee_variable_from_trace(name='accesstoken.auth_type')
        auth_grant_type = await apigee_trace.get_apigee_variable_from_trace(name='accesstoken.auth_grant_type')
        auth_provider = await apigee_trace.get_apigee_variable_from_trace(name='accesstoken.auth_provider')
        auth_level = await apigee_trace.get_apigee_variable_from_trace(name='accesstoken.auth_level')
        auth_user_id = await apigee_trace.get_apigee_variable_from_trace(name='accesstoken.auth_user_id')

        assert auth_type == 'user'
        assert auth_grant_type == 'token_exchange'
        assert auth_provider == 'nhs-cis2'
        assert auth_level == 'aal3'
        assert auth_user_id == '787807429511'
    async def test_access_token_fields_for_logging_when_using_client_credentials(self):
        # Given
        apigee_trace = ApigeeApiTraceDebug(proxy=f"hello-world-{ENVIRONMENT}")
        jwt_claims = {
            'kid': 'test-1',
            'claims': {
                "sub": self.oauth.client_id,
                "iss": self.oauth.client_id,
                "jti": str(uuid4()),
                "aud": f"{OAUTH_URL}/token",
                "exp": int(time()),
            }
        }
        jwt = self.oauth.create_jwt(**jwt_claims)
        resp = await self.oauth.get_token_response(grant_type='client_credentials', _jwt=jwt)
        access_token = resp['body']['access_token']

        # When
        await apigee_trace.start_trace()
        requests.get(f"{HELLO_WORLD_API_URL}", headers={"Authorization": f"Bearer {access_token}"})

        # Then
        auth_type = await apigee_trace.get_apigee_variable_from_trace(name='accesstoken.auth_type')
        auth_grant_type = await apigee_trace.get_apigee_variable_from_trace(name='accesstoken.auth_grant_type')
        auth_level = await apigee_trace.get_apigee_variable_from_trace(name='accesstoken.auth_level')
        auth_provider = await apigee_trace.get_apigee_variable_from_trace(name='accesstoken.auth_provider')
        auth_user_id = await apigee_trace.get_apigee_variable_from_trace(name='accesstoken.auth_user_id')

        assert auth_type == 'app'
        assert auth_grant_type == 'client_credentials'
        assert auth_level == 'level3'
        assert auth_provider == 'apim'
        assert auth_user_id == ''
Пример #4
0
    async def test_nhs_login_user_restricted_scope_combination(
        self,
        product_1_scopes,
        product_2_scopes,
        expected_filtered_scopes,
        test_app_and_product,
        helper,
        auth_code_nhs_login,
    ):
        test_product, test_product2, test_app = test_app_and_product

        await test_product.update_scopes(product_1_scopes)
        await test_product2.update_scopes(product_2_scopes)
        apigee_trace = ApigeeApiTraceDebug(proxy=config.SERVICE_NAME)

        callback_url = await test_app.get_callback_url()

        state = await auth_code_nhs_login.get_state(self.oauth, test_app)

        auth_code = await auth_code_nhs_login.make_auth_request(
            self.oauth, state)

        await apigee_trace.start_trace()
        await auth_code_nhs_login.make_callback_request(
            self.oauth, state, auth_code)

        user_restricted_scopes = await apigee_trace.get_apigee_variable_from_trace(
            name="apigee.user_restricted_scopes")
        assert (
            user_restricted_scopes is not None
        ), "variable apigee.user_restricted_scopes not found in the trace"
        user_restricted_scopes = user_restricted_scopes.split(" ")
        assert expected_filtered_scopes.sort() == user_restricted_scopes.sort()
Пример #5
0
    async def test_valid_application_restricted_scope_combination(
        self,
        product_1_scopes,
        product_2_scopes,
        expected_filtered_scopes,
        test_app_and_product,
    ):
        test_product, test_product2, test_app = test_app_and_product
        apigee_trace = ApigeeApiTraceDebug(proxy=config.SERVICE_NAME)

        await test_product.update_scopes(product_1_scopes)
        await test_product2.update_scopes(product_2_scopes)

        jwt = self.oauth.create_jwt(kid="test-1", client_id=test_app.client_id)
        await apigee_trace.start_trace()
        resp = await self.oauth.get_token_response(
            grant_type="client_credentials", _jwt=jwt)

        application_scope = await apigee_trace.get_apigee_variable_from_trace(
            name="apigee.application_restricted_scopes")
        assert (
            application_scope is not None
        ), "variable apigee.user_restricted_scopes not found in the trace"
        application_scope = application_scope.split(" ")

        assert list(resp["body"].keys()) == [
            "access_token",
            "expires_in",
            "token_type",
            "issued_at",
        ]
        assert resp["status_code"] == 200
        assert application_scope.sort() == expected_filtered_scopes.sort()
    async def test_splunk_fields_for_authorize_endpoint_for_cis2(self):
        debug = ApigeeApiTraceDebug(proxy=config.SERVICE_NAME)

        await debug.start_trace()
        await self.oauth.hit_oauth_endpoint(
            method="GET",
            endpoint="authorize",
            params={
                "client_id": self.oauth.client_id,
                "redirect_uri": self.oauth.redirect_uri,
                "response_type": "code",
                "state": random.getrandbits(32),
            },
        )

        payload = await self._get_payload_from_splunk(debug)

        # Then
        auth = payload["auth"]

        auth_meta = auth["meta"]
        assert auth_meta["auth_type"] == "user"
        assert auth_meta["grant_type"] == "authorization_code"
        assert auth_meta[
            "level"] == ""  # level is unknown when hitting /authorize
        assert auth_meta["provider"] == "nhs-cis2"

        auth_user = auth["user"]
        assert auth_user[
            "user_id"] == ""  # user_id is unknown when hitting /authorize
Пример #7
0
async def test_apigee_stop_trace_without_starting_trace():
    api = ApigeeApiTraceDebug(proxy="personal-demographics-pr-538")
    with pytest.raises(RuntimeError) as exec_info:
        await api.stop_trace()
        assert str(
            exec_info.value
        ) == 'You must run start_trace() before you can run stop_trace()'
Пример #8
0
async def test_apigee_trace_timeout():
    api = ApigeeApiTraceDebug(proxy="personal-demographics-pr-538", timeout=2)
    resp = await api.start_trace()
    assert resp['status_code'] == 201

    with pytest.raises(TimeoutError) as exec_info:
        sleep(2)  # Wait for session to timeout
        await api.get_trace_data()
        assert str(
            exec_info.value
        ) == "Your session has timed out, please rerun the start_trace() method again"
Пример #9
0
async def _api():
    """ Setup and Teardown """

    api = ApigeeApiTraceDebug(proxy="personal-demographics-pr-538")

    print(f"\nStarting Trace on proxy {api.proxy}...")
    await api.start_trace()

    yield api
    # teardown
    try:
        print(f"\nStopping Trace on proxy {api.proxy}...")
        await api.stop_trace()
    except RuntimeError:
        # Session already stopped or has timed out
        pass
    async def test_access_token_fields_for_logging_when_using_authorization_code_cis2(self, helper):
        # Given
        apigee_trace = ApigeeApiTraceDebug(proxy=f"hello-world-{ENVIRONMENT}")

        # When
        await apigee_trace.start_trace()
        requests.get(f"{HELLO_WORLD_API_URL}", headers={"Authorization": f"Bearer {self.oauth.access_token}"})

        # Then
        auth_type = await apigee_trace.get_apigee_variable_from_trace(name='accesstoken.auth_type')
        auth_grant_type = await apigee_trace.get_apigee_variable_from_trace(name='accesstoken.auth_grant_type')
        auth_level = await apigee_trace.get_apigee_variable_from_trace(name='accesstoken.auth_level')
        auth_provider = await apigee_trace.get_apigee_variable_from_trace(name='accesstoken.auth_provider')
        auth_user_id = await apigee_trace.get_apigee_variable_from_trace(name='accesstoken.auth_user_id')

        assert auth_type == 'user'
        assert auth_grant_type == 'authorization_code'
        assert auth_level == 'aal3'
        assert auth_provider == 'nhs-cis2'
        assert auth_user_id == '787807429511'
    async def test_access_token_fields_for_logging_when_using_authorization_code_nhs_login(self, scope, helper):
        # Given
        apigee_trace = ApigeeApiTraceDebug(proxy=f"hello-world-{ENVIRONMENT}")

        # Make authorize request to retrieve state2
        response = await self.oauth.hit_oauth_endpoint(
            method="GET",
            endpoint="authorize",
            params={
                "client_id": self.oauth.client_id,
                "redirect_uri": self.oauth.redirect_uri,
                "response_type": "code",
                "state": "1234567890",
                "scope": "nhs-login"
            },
            allow_redirects=False,
        )

        state = helper.get_param_from_url(
            url=response["headers"]["Location"], param="state"
        )
        # Make simulated auth request to authenticate
        response = await self.oauth.hit_oauth_endpoint(
            base_uri=MOCK_IDP_BASE_URL,
            method="POST",
            endpoint="nhs_login_simulated_auth",
            params={
                "response_type": "code",
                "client_id": self.oauth.client_id,
                "redirect_uri": self.oauth.redirect_uri,
                "scope": "openid",
                "state": state,
            },
            headers={"Content-Type": "application/x-www-form-urlencoded"},
            data={
                "state": state,
                "auth_method": scope
            },
            allow_redirects=False,
        )

        # Make initial callback request
        auth_code = helper.get_param_from_url(
            url=response["headers"]["Location"], param="code"
        )

        response = await self.oauth.hit_oauth_endpoint(
            method="GET",
            endpoint="callback",
            params={"code": auth_code, "client_id": "some-client-id", "state": state},
            allow_redirects=False,
        )

        auth_code = helper.get_param_from_url(
            url=response["headers"]["Location"], param="code"
        )

        response = await self.oauth.hit_oauth_endpoint(
            method="POST",
            endpoint="token",
            data={
                "grant_type": "authorization_code",
                "state": state,
                "code": auth_code,
                "redirect_uri": self.oauth.redirect_uri,
                "client_id": self.oauth.client_id,
                "client_secret": self.oauth.client_secret
            },
            allow_redirects=False,
        )

        access_token = response['body']['access_token']
        # When
        await apigee_trace.start_trace()
        requests.get(f"{HELLO_WORLD_API_URL}", headers={"Authorization": f"Bearer {access_token}"})

        # Then
        auth_type = await apigee_trace.get_apigee_variable_from_trace(name='accesstoken.auth_type')
        auth_grant_type = await apigee_trace.get_apigee_variable_from_trace(name='accesstoken.auth_grant_type')
        auth_level = await apigee_trace.get_apigee_variable_from_trace(name='accesstoken.auth_level')
        auth_provider = await apigee_trace.get_apigee_variable_from_trace(name='accesstoken.auth_provider')
        auth_user_id = await apigee_trace.get_apigee_variable_from_trace(name='accesstoken.auth_user_id')

        assert auth_type == 'user'
        assert auth_grant_type == 'authorization_code'
        assert auth_level == scope.lower()
        assert auth_provider == 'apim-mock-nhs-login'
        assert auth_user_id == '9912003071'
    async def test_access_token_fields_for_logging_when_using_token_exchange_nhs_login(self, scope):
        # Given
        apigee_trace = ApigeeApiTraceDebug(proxy=f"hello-world-{ENVIRONMENT}")

        id_token_claims = {
            "aud": "tf_-APIM-1",
            "id_status": "verified",
            "token_use": "id",
            "auth_time": 1616600683,
            "iss": "https://internal-dev.api.service.nhs.uk",
            "vot": "P9.Cp.Cd",
            "exp": int(time()) + 600,
            "iat": int(time()) - 10,
            "vtm": "https://auth.sandpit.signin.nhs.uk/trustmark/auth.sandpit.signin.nhs.uk",
            "jti": str(uuid4()),
            "identity_proofing_level": scope,
            "nhs_number": "900000000001"
        }
        id_token_headers = {
            "sub": "49f470a1-cc52-49b7-beba-0f9cec937c46",
            "aud": "APIM-1",
            "kid": "nhs-login",
            "iss": "https://internal-dev.api.service.nhs.uk",
            "typ": "JWT",
            "exp": 1616604574,
            "iat": 1616600974,
            "alg": "RS512",
            "jti": str(uuid4()),
        }

        with open(ID_TOKEN_NHS_LOGIN_PRIVATE_KEY_ABSOLUTE_PATH, "r") as f:
            contents = f.read()

        client_assertion_jwt = self.oauth.create_jwt(kid="test-1")
        id_token_jwt = self.oauth.create_id_token_jwt(
            algorithm="RS512",
            claims=id_token_claims,
            headers=id_token_headers,
            signing_key=contents,
        )
        resp = await self.oauth.get_token_response(
            grant_type="token_exchange",
            _jwt=client_assertion_jwt,
            id_token_jwt=id_token_jwt,
        )
        access_token = resp['body']['access_token']

        # When
        await apigee_trace.start_trace()
        requests.get(f"{HELLO_WORLD_API_URL}", headers={"Authorization": f"Bearer {access_token}"})

        # Then
        auth_type = await apigee_trace.get_apigee_variable_from_trace(name='accesstoken.auth_type')
        auth_grant_type = await apigee_trace.get_apigee_variable_from_trace(name='accesstoken.auth_grant_type')
        auth_provider = await apigee_trace.get_apigee_variable_from_trace(name='accesstoken.auth_provider')
        auth_level = await apigee_trace.get_apigee_variable_from_trace(name='accesstoken.auth_level')
        auth_user_id = await apigee_trace.get_apigee_variable_from_trace(name='accesstoken.auth_user_id')

        assert auth_type == 'user'
        assert auth_grant_type == 'token_exchange'
        assert auth_provider == 'apim-mock-nhs-login'
        assert auth_level == scope.lower()
        assert auth_user_id == '900000000001'
Пример #13
0
async def apigee_start_trace(expected_filtered_scopes):
    apigee_trace = ApigeeApiTraceDebug(proxy=config.SERVICE_NAME)
    await apigee_trace.start_trace()
    return apigee_trace
    async def test_splunk_fields_for_callback_endpoint_for_cis2(self, helper):
        # Given
        response = await self.oauth.hit_oauth_endpoint(
            method="GET",
            endpoint="authorize",
            params={
                "client_id": self.oauth.client_id,
                "redirect_uri": self.oauth.redirect_uri,
                "response_type": "code",
                "state": "1234567890",
            },
            allow_redirects=False,
        )

        state = helper.get_param_from_url(url=response["headers"]["Location"],
                                          param="state")

        # Make simulated auth request to authenticate
        response = await self.oauth.hit_oauth_endpoint(
            base_uri=config.MOCK_IDP_BASE_URL,
            method="POST",
            endpoint="simulated_auth",
            params={
                "response_type": "code",
                "client_id": self.oauth.client_id,
                "redirect_uri": self.oauth.redirect_uri,
                "scope": "openid",
                "state": state,
            },
            headers={"Content-Type": "application/x-www-form-urlencoded"},
            data={"state": state},
            allow_redirects=False,
        )

        # Make initial callback request
        auth_code = helper.get_param_from_url(
            url=response["headers"]["Location"], param="code")

        # When
        debug = ApigeeApiTraceDebug(proxy=config.SERVICE_NAME)
        await debug.start_trace()
        await self.oauth.hit_oauth_endpoint(
            method="GET",
            endpoint="callback",
            params={
                "code": auth_code,
                "client_id": "some-client-id",
                "state": state
            },
            allow_redirects=False,
        )

        payload = await self._get_payload_from_splunk(debug)

        # Then
        auth = payload["auth"]

        auth_meta = auth["meta"]
        assert auth_meta["auth_type"] == "user"
        assert auth_meta["grant_type"] == "authorization_code"
        assert auth_meta["level"] == "aal3"
        assert auth_meta["provider"] == "nhs-cis2"

        auth_user = auth["user"]
        assert auth_user["user_id"] == "787807429511"
Пример #15
0
async def test_apigee_get_trace_data():
    api = ApigeeApiTraceDebug(proxy='apim-test')
    await api.start_trace()
    resp = await api.get_trace_data()
    assert resp == {}