def test_watch_jwt_bundle_no_retry_on_grpc_error_no_call(mocker): grpc_error = grpc.RpcError jwt_bundles = { 'example.org': JWKS_1_EC_KEY, 'domain.prod': JWKS_2_EC_1_RSA_KEYS } WORKLOAD_API_CLIENT._spiffe_workload_api_stub.FetchJWTBundles = mocker.Mock( side_effect=[ grpc_error, delayed_responses( [workload_pb2.JWTBundlesResponse(bundles=jwt_bundles)]), ]) expected_error = FetchJwtBundleError( 'Cannot process response from Workload API.') event = threading.Event() response_holder = ResponseHolder() WORKLOAD_API_CLIENT.watch_jwt_bundles( on_success=lambda r: handle_success(r, response_holder, event), on_error=lambda e: handle_error(e, response_holder, event), ) event.wait(3) # add timeout to prevent test from hanging assert not response_holder.success assert response_holder.error assert_error(response_holder.error, expected_error)
def test_fetch_x509_svid_corrupted_response(mocker): WORKLOAD_API_CLIENT._spiffe_workload_api_stub.FetchX509SVID = mocker.Mock( return_value=iter( [ workload_pb2.X509SVIDResponse( svids=[ workload_pb2.X509SVID( spiffe_id='spiffe://example.org/service', x509_svid=_CORRUPTED, x509_svid_key=_KEY1, ), workload_pb2.X509SVID( spiffe_id='spiffe://example.org/service2', x509_svid=_CHAIN2, x509_svid_key=_KEY2, ), ] ) ] ) ) with (pytest.raises(FetchX509SvidError)) as exception: WORKLOAD_API_CLIENT.fetch_x509_svid() assert ( str(exception.value) == 'Error fetching X.509 SVID: Error parsing certificate: Unable to parse DER X.509 certificate.' )
def test_fetch_x509_context_corrupted_svid(mocker): federated_bundles = dict() federated_bundles['domain.test'] = _FEDERATED_BUNDLE WORKLOAD_API_CLIENT._spiffe_workload_api_stub.FetchX509SVID = mocker.Mock( return_value=iter( [ workload_pb2.X509SVIDResponse( svids=[ workload_pb2.X509SVID( spiffe_id='spiffe://example.org/service', x509_svid=_CHAIN1, x509_svid_key=_CORRUPTED, bundle=_BUNDLE, ), workload_pb2.X509SVID( spiffe_id='spiffe://example.org/service2', x509_svid=_CHAIN2, x509_svid_key=_KEY2, bundle=_BUNDLE, ), ], federated_bundles=federated_bundles, ) ] ) ) with (pytest.raises(FetchX509SvidError)) as exception: WORKLOAD_API_CLIENT.fetch_x509_context() assert 'Error fetching X.509 SVID: Error parsing private key' in str( exception.value )
def test_fetch_jwt_svid_no_token_returned(mocker): WORKLOAD_API_CLIENT._spiffe_workload_api_stub.FetchJWTSVID = mocker.Mock( return_value=iter([workload_pb2.JWTSVIDResponse(svids=[])])) with pytest.raises(FetchJwtSvidError) as exception: WORKLOAD_API_CLIENT.fetch_jwt_svid(audiences=DEFAULT_AUDIENCE) assert str(exception.value).startswith('Error fetching JWT SVID')
def test_fetch_x509_context_corrupted_federated_bundle(mocker): federated_bundles = dict() federated_bundles['domain.test'] = _CORRUPTED WORKLOAD_API_CLIENT._spiffe_workload_api_stub.FetchX509SVID = mocker.Mock( return_value=iter( [ workload_pb2.X509SVIDResponse( svids=[ workload_pb2.X509SVID( spiffe_id='spiffe://example.org/service', x509_svid=_CHAIN1, x509_svid_key=_KEY1, bundle=_BUNDLE, ), workload_pb2.X509SVID( spiffe_id='spiffe://example.org/service2', x509_svid=_CHAIN2, x509_svid_key=_KEY2, bundle=_BUNDLE, ), ], federated_bundles=federated_bundles, ) ] ) ) with (pytest.raises(FetchX509BundleError)) as exception: WORKLOAD_API_CLIENT.fetch_x509_context() assert ( str(exception.value) == 'Error fetching X.509 Bundles: Unable to parse DER X.509 certificate.' )
def test_watch_x509_context_raise_unretryable_grpc_error(mocker): grpc_error = grpc.RpcError() grpc_error.code = lambda: grpc.StatusCode.INVALID_ARGUMENT mock_error_iter = mocker.MagicMock() mock_error_iter.__iter__.side_effect = grpc_error WORKLOAD_API_CLIENT._spiffe_workload_api_stub.FetchX509SVID = mocker.Mock( return_value=mock_error_iter) done = threading.Event() expected_error = FetchX509SvidError('StatusCode.INVALID_ARGUMENT') response_holder = ResponseHolder() WORKLOAD_API_CLIENT.watch_x509_context( lambda r: handle_success(r, response_holder, done), lambda e: handle_error(e, response_holder, done), True, ) done.wait(5) # add timeout to prevent test from hanging assert not response_holder.success assert str(response_holder.error) == str(expected_error)
def test_fetch_x509_svid_raise_exception(mocker): WORKLOAD_API_CLIENT._spiffe_workload_api_stub.FetchX509SVID = mocker.Mock( side_effect=Exception('mocked error')) with (pytest.raises(FetchX509SvidError)) as exception: WORKLOAD_API_CLIENT.fetch_x509_svid() assert str(exception.value) == 'Error fetching X.509 SVID: mocked error.'
def test_fetch_jwt_svid_fetch_error(mocker): WORKLOAD_API_CLIENT._spiffe_workload_api_stub.FetchJWTSVID = mocker.Mock( side_effect=Exception('Mocked Error')) with pytest.raises(FetchJwtSvidError) as exception: WORKLOAD_API_CLIENT.fetch_jwt_svid(audiences=DEFAULT_AUDIENCE) assert str(exception.value) == 'Error fetching JWT SVID: Mocked Error.'
def test_fetch_jwt_bundles_raise_error(mocker): WORKLOAD_API_CLIENT._spiffe_workload_api_stub.FetchJWTBundles = mocker.Mock( side_effect=Exception('Mocked error')) with pytest.raises(FetchJwtBundleError) as exc_info: WORKLOAD_API_CLIENT.fetch_jwt_bundles() assert str(exc_info.value) == 'Error fetching JWT Bundle: Mocked error.'
def test_fetch_x509_svid_raise_grpc_error_call(mocker): WORKLOAD_API_CLIENT._spiffe_workload_api_stub.FetchX509SVID = mocker.Mock( side_effect=FakeCall()) with (pytest.raises(FetchX509SvidError)) as exception: WORKLOAD_API_CLIENT.fetch_x509_svid() assert (str(exception.value) == 'Error fetching X.509 SVID: Error details from Workload API.')
def test_fetch_x509_svid_invalid_response(mocker): WORKLOAD_API_CLIENT._spiffe_workload_api_stub.FetchX509SVID = mocker.Mock( return_value=iter([])) with (pytest.raises(FetchX509SvidError)) as exception: WORKLOAD_API_CLIENT.fetch_x509_svid() assert (str(exception.value) == 'Error fetching X.509 SVID: X.509 SVID response is invalid.')
def test_fetch_jwt_bundles_raise_grpc_call(mocker): WORKLOAD_API_CLIENT._spiffe_workload_api_stub.FetchJWTBundles = mocker.Mock( side_effect=FakeCall()) with pytest.raises(FetchJwtBundleError) as exc_info: WORKLOAD_API_CLIENT.fetch_jwt_bundles() assert (str(exc_info.value) == 'Error fetching JWT Bundle: Error details from Workload API.')
def test_validate_jwt_svid_invalid_input(test_input_token, test_input_audience, expected): with pytest.raises(ArgumentError) as exception: WORKLOAD_API_CLIENT.validate_jwt_svid( token=test_input_token, audience=test_input_audience, ) assert str(exception.value) == expected
def test_fetch_x509_context_empty_response(mocker): WORKLOAD_API_CLIENT._spiffe_workload_api_stub.FetchX509SVID = mocker.Mock( return_value=iter([workload_pb2.X509SVIDResponse(svids=[])])) with (pytest.raises(FetchX509SvidError)) as exception: WORKLOAD_API_CLIENT.fetch_x509_context() assert (str(exception.value) == 'Error fetching X.509 SVID: X.509 SVID response is empty.')
def test_fetch_x509_bundles_empty_response(mocker): WORKLOAD_API_CLIENT._spiffe_workload_api_stub.FetchX509Bundles = mocker.Mock( return_value=iter([workload_pb2.X509BundlesResponse(bundles=[])])) with (pytest.raises(FetchX509BundleError)) as exception: WORKLOAD_API_CLIENT.fetch_x509_bundles() assert (str(exception.value) == 'Error fetching X.509 Bundles: X.509 Bundles response is empty.')
def test_fetch_jwt_svid_wrong_token(mocker): jwt_svid = create_jwt(spiffe_id='') WORKLOAD_API_CLIENT._spiffe_workload_api_stub.FetchJWTSVID = mocker.Mock( return_value=workload_pb2.JWTSVIDResponse( svids=[workload_pb2.JWTSVID(svid=jwt_svid, )])) with pytest.raises(FetchJwtSvidError) as exception: WORKLOAD_API_CLIENT.fetch_jwt_svid(audiences=DEFAULT_AUDIENCE) assert (str(exception.value) == 'Error fetching JWT SVID: Missing required claim: sub.')
def test_fetch_jwt_bundles_empty_response(mocker): WORKLOAD_API_CLIENT._spiffe_workload_api_stub.FetchJWTBundles = mocker.Mock( return_value=iter([ workload_pb2.JWTBundlesResponse(bundles={}, ), ])) with pytest.raises(FetchJwtBundleError) as exc_info: WORKLOAD_API_CLIENT.fetch_jwt_bundles() assert (str(exc_info.value) == 'Error fetching JWT Bundle: JWT Bundles response is empty.')
def test_watch_x509_context_success(mocker): federated_bundles = {'domain.test': FEDERATED_BUNDLE} WORKLOAD_API_CLIENT._spiffe_workload_api_stub.FetchX509SVID = mocker.Mock( return_value=iter([ workload_pb2.X509SVIDResponse( svids=[ workload_pb2.X509SVID( spiffe_id='spiffe://example.org/service', x509_svid=CHAIN1, x509_svid_key=KEY1, bundle=BUNDLE, ), workload_pb2.X509SVID( spiffe_id='spiffe://example.org/service2', x509_svid=CHAIN2, x509_svid_key=KEY2, bundle=BUNDLE, ), ], federated_bundles=federated_bundles, ) ])) done = threading.Event() response_holder = ResponseHolder() WORKLOAD_API_CLIENT.watch_x509_context( lambda r: handle_success(r, response_holder, done), lambda e: handle_error(e, response_holder, done), retry_connect=True, ) done.wait(5) # add timeout to prevent test from hanging assert not response_holder.error x509_context = response_holder.success svid1 = x509_context.default_svid() assert svid1.spiffe_id() == SpiffeId.parse('spiffe://example.org/service') assert len(svid1.cert_chain()) == 2 assert isinstance(svid1.leaf(), Certificate) assert isinstance(svid1.private_key(), ec.EllipticCurvePrivateKey) svid2 = x509_context.x509_svids()[1] assert svid2.spiffe_id() == SpiffeId.parse('spiffe://example.org/service2') assert len(svid2.cert_chain()) == 1 assert isinstance(svid2.leaf(), Certificate) assert isinstance(svid2.private_key(), ec.EllipticCurvePrivateKey) bundle_set = x509_context.x509_bundle_set() bundle = bundle_set.get_x509_bundle_for_trust_domain( TrustDomain.parse('example.org')) assert bundle assert len(bundle.x509_authorities()) == 1
def test_validate_jwt_svid_raise_error(mocker): jwt_svid = create_jwt() WORKLOAD_API_CLIENT._spiffe_workload_api_stub.ValidateJWTSVID = mocker.Mock( side_effect=Exception('Mocked error')) with pytest.raises(ValidateJwtSvidError) as exception: WORKLOAD_API_CLIENT.validate_jwt_svid(token=jwt_svid, audience='audience') assert str(exception.value) == 'JWT SVID is not valid: Mocked error.'
def test_fetch_jwt_bundles_raise_grpc_error(mocker): WORKLOAD_API_CLIENT._spiffe_workload_api_stub.FetchJWTBundles = mocker.Mock( side_effect=grpc.RpcError('Mocked gRPC error')) with pytest.raises(FetchJwtBundleError) as exc_info: WORKLOAD_API_CLIENT.fetch_jwt_bundles() assert ( str(exc_info.value) == 'Error fetching JWT Bundle: Could not process response from the Workload API.' )
def test_fetch_x509_bundles_raise_exception(mocker): WORKLOAD_API_CLIENT._spiffe_workload_api_stub.FetchX509Bundles = mocker.Mock( side_effect=Exception('mocked error') ) with (pytest.raises(FetchX509BundleError)) as exception: WORKLOAD_API_CLIENT.fetch_x509_bundles() assert ( str(exception.value) == 'Error fetching X.509 Bundles: X.509 Bundles response is invalid.' )
def test_fetch_x509_bundles_corrupted_federated_bundle(mocker): bundles = {'example.org': BUNDLE, 'domain.test': CORRUPTED} WORKLOAD_API_CLIENT._spiffe_workload_api_stub.FetchX509Bundles = mocker.Mock( return_value=iter( [workload_pb2.X509BundlesResponse(bundles=bundles, )])) with (pytest.raises(FetchX509BundleError)) as exception: WORKLOAD_API_CLIENT.fetch_x509_bundles() assert ( str(exception.value) == 'Error fetching X.509 Bundles: Error parsing X.509 bundle: Unable to parse DER X.509 certificate.' )
def test_fetch_x509_bundles_success(mocker): bundles = dict() bundles['example.org'] = _BUNDLE bundles['domain.test'] = _FEDERATED_BUNDLE WORKLOAD_API_CLIENT._spiffe_workload_api_stub.FetchX509Bundles = mocker.Mock( return_value=iter( [ workload_pb2.X509BundlesResponse( bundles=bundles, ) ] ) ) bundle_set = WORKLOAD_API_CLIENT.fetch_x509_bundles() bundle = bundle_set.get_x509_bundle_for_trust_domain(TrustDomain('example.org')) assert bundle assert len(bundle.x509_authorities()) == 1 federated_bundle = bundle_set.get_x509_bundle_for_trust_domain( TrustDomain('domain.test') ) assert federated_bundle assert len(federated_bundle.x509_authorities()) == 1
def test_fetch_x509_svid_success(mocker): WORKLOAD_API_CLIENT._spiffe_workload_api_stub.FetchX509SVID = mocker.Mock( return_value=iter( [ workload_pb2.X509SVIDResponse( svids=[ workload_pb2.X509SVID( spiffe_id='spiffe://example.org/service', x509_svid=_CHAIN1, x509_svid_key=_KEY1, ), workload_pb2.X509SVID( spiffe_id='spiffe://example.org/service2', x509_svid=_CHAIN2, x509_svid_key=_KEY2, ), ] ) ] ) ) svid = WORKLOAD_API_CLIENT.fetch_x509_svid() assert svid.spiffe_id() == SpiffeId.parse('spiffe://example.org/service') assert len(svid.cert_chain()) == 2 assert isinstance(svid.leaf(), Certificate) assert isinstance(svid.private_key(), ec.EllipticCurvePrivateKey)
def test_fetch_jwt_bundles_error_parsing_jwks(mocker): bundles = { 'example.org': JWKS_1_EC_KEY, 'domain.test': JWKS_MISSING_KEY_ID } WORKLOAD_API_CLIENT._spiffe_workload_api_stub.FetchJWTBundles = mocker.Mock( return_value=iter([ workload_pb2.JWTBundlesResponse(bundles=bundles, ), ])) with pytest.raises(FetchJwtBundleError) as exc_info: WORKLOAD_API_CLIENT.fetch_jwt_bundles() assert ( str(exc_info.value) == 'Error fetching JWT Bundle: Error parsing JWT bundle: Error adding authority from JWKS: keyID cannot be empty.' )
def test_fetch_x509_context_success(mocker): federated_bundles = dict() federated_bundles['domain.test'] = _FEDERATED_BUNDLE WORKLOAD_API_CLIENT._spiffe_workload_api_stub.FetchX509SVID = mocker.Mock( return_value=iter( [ workload_pb2.X509SVIDResponse( svids=[ workload_pb2.X509SVID( spiffe_id='spiffe://example.org/service', x509_svid=_CHAIN1, x509_svid_key=_KEY1, bundle=_BUNDLE, ), workload_pb2.X509SVID( spiffe_id='spiffe://example.org/service2', x509_svid=_CHAIN2, x509_svid_key=_KEY2, bundle=_BUNDLE, ), ], federated_bundles=federated_bundles, ) ] ) ) x509_context = WORKLOAD_API_CLIENT.fetch_x509_context() svids = x509_context.x509_svids() bundle_set = x509_context.x509_bundle_set() assert len(svids) == 2 svid1 = x509_context.default_svid() assert svid1.spiffe_id() == SpiffeId.parse('spiffe://example.org/service') assert len(svid1.cert_chain()) == 2 assert isinstance(svid1.leaf(), Certificate) assert isinstance(svid1.private_key(), ec.EllipticCurvePrivateKey) svid2 = x509_context.x509_svids()[1] assert svid2.spiffe_id() == SpiffeId.parse('spiffe://example.org/service2') assert len(svid2.cert_chain()) == 1 assert isinstance(svid2.leaf(), Certificate) assert isinstance(svid2.private_key(), ec.EllipticCurvePrivateKey) bundle = bundle_set.get_x509_bundle_for_trust_domain(TrustDomain('example.org')) assert bundle assert len(bundle.x509_authorities()) == 1 federated_bundle = bundle_set.get_x509_bundle_for_trust_domain( TrustDomain('domain.test') ) assert federated_bundle assert len(federated_bundle.x509_authorities()) == 1
def test_watch_jwt_bundle_success(mocker): jwt_bundles = { 'example.org': JWKS_1_EC_KEY, 'domain.prod': JWKS_2_EC_1_RSA_KEYS } jwt_bundles_2 = {'domain.dev': JWKS_1_EC_KEY} WORKLOAD_API_CLIENT._spiffe_workload_api_stub.FetchJWTBundles = mocker.Mock( return_value=delayed_responses([ workload_pb2.JWTBundlesResponse(bundles=jwt_bundles), workload_pb2.JWTBundlesResponse(bundles=jwt_bundles_2), ])) event = threading.Event() response_holder = ResponseHolder() WORKLOAD_API_CLIENT.watch_jwt_bundles( on_success=lambda r: handle_success(r, response_holder, event), on_error=lambda e: handle_error(e, response_holder, event), ) event.wait(3) # add timeout to prevent test from hanging assert not response_holder.error jwt_bundle_set = response_holder.success assert jwt_bundle_set jwt_bundle_1 = jwt_bundle_set.get(TrustDomain.parse('example.org')) assert jwt_bundle_1 assert len(jwt_bundle_1.jwt_authorities()) == 1 jwt_bundle_2 = jwt_bundle_set.get(TrustDomain.parse('domain.prod')) assert jwt_bundle_2 assert len(jwt_bundle_2.jwt_authorities()) == 3 # Wait to receive the second response from delayed_responses() time.sleep(1) assert not response_holder.error jwt_bundle_set = response_holder.success jwt_bundle = jwt_bundle_set.get(TrustDomain.parse('domain.dev')) assert jwt_bundle assert len(jwt_bundle.jwt_authorities()) == 1
def test_watch_jwt_bundle_no_retry_on_error(mocker): some_error = Exception('Some Error') WORKLOAD_API_CLIENT._spiffe_workload_api_stub.FetchJWTBundles = mocker.Mock( side_effect=some_error, ) expected_error = FetchJwtBundleError(str(some_error)) event = threading.Event() response_holder = ResponseHolder() WORKLOAD_API_CLIENT.watch_jwt_bundles( on_success=lambda r: handle_success(r, response_holder, event), on_error=lambda e: handle_error(e, response_holder, event), ) event.wait(3) # add timeout to prevent test from hanging assert not response_holder.success assert response_holder.error assert_error(response_holder.error, expected_error)
def test_watch_x509_context_raise_retryable_grpc_error_and_then_ok_response( mocker): mock_error_iter = mocker.MagicMock() mock_error_iter.__iter__.side_effect = ( yield_grpc_error_and_then_correct_x509_svid_response()) WORKLOAD_API_CLIENT._spiffe_workload_api_stub.FetchX509SVID = mocker.Mock( return_value=mock_error_iter) expected_error = FetchX509SvidError('StatusCode.DEADLINE_EXCEEDED') done = threading.Event() response_holder = ResponseHolder() WORKLOAD_API_CLIENT.watch_x509_context( lambda r: handle_success(r, response_holder, done), lambda e: assert_error(e, expected_error), True, ) done.wait(5) # add timeout to prevent test from hanging x509_context = response_holder.success svid1 = x509_context.default_svid() assert svid1.spiffe_id() == SpiffeId.parse('spiffe://example.org/service') assert len(svid1.cert_chain()) == 2 assert isinstance(svid1.leaf(), Certificate) assert isinstance(svid1.private_key(), ec.EllipticCurvePrivateKey) svid2 = x509_context.x509_svids()[1] assert svid2.spiffe_id() == SpiffeId.parse('spiffe://example.org/service2') assert len(svid2.cert_chain()) == 1 assert isinstance(svid2.leaf(), Certificate) assert isinstance(svid2.private_key(), ec.EllipticCurvePrivateKey) bundle_set = x509_context.x509_bundle_set() bundle = bundle_set.get_x509_bundle_for_trust_domain( TrustDomain.parse('example.org')) assert bundle assert len(bundle.x509_authorities()) == 1
def test_fetch_jwt_svid_aud(mocker): spiffe_id = 'spiffe://test.com/my_service' jwt_svid = create_jwt(spiffe_id=spiffe_id) WORKLOAD_API_CLIENT._spiffe_workload_api_stub.FetchJWTSVID = mocker.Mock( return_value=workload_pb2.JWTSVIDResponse( svids=[workload_pb2.JWTSVID(svid=jwt_svid, )])) svid = WORKLOAD_API_CLIENT.fetch_jwt_svid(audiences=DEFAULT_AUDIENCE) utc_time = timegm(datetime.datetime.utcnow().utctimetuple()) assert svid.spiffe_id == SpiffeId.parse(spiffe_id) assert svid.token == jwt_svid assert svid.claims['aud'] == DEFAULT_AUDIENCE assert int(svid.expiry) > utc_time