def test_delegation_token(self): peer_ident = model.Identity.from_bytes('user:[email protected]') class Handler(handler.AuthenticatingHandler): @classmethod def get_auth_methods(cls, conf): return [lambda _request: peer_ident] @api.public def get(self): self.response.write( json.dumps({ 'peer_id': api.get_peer_identity().to_bytes(), 'cur_id': api.get_current_identity().to_bytes(), })) app = self.make_test_app('/request', Handler) def call(headers=None): return json.loads(app.get('/request', headers=headers).body) # No delegation. self.assertEqual( { u'cur_id': u'user:[email protected]', u'peer_id': u'user:[email protected]' }, call()) # TODO(vadimsh): Mint token via some high-level function call. subtoken = delegation_pb2.Subtoken( delegated_identity='user:[email protected]', audience=['*'], services=['*'], creation_time=int(utils.time_time()), validity_duration=3600) tok = delegation.serialize_token(delegation.seal_token(subtoken)) # With valid delegation token. self.assertEqual( { u'cur_id': u'user:[email protected]', u'peer_id': u'user:[email protected]' }, call({'X-Delegation-Token-V1': tok})) # With invalid delegation token. r = app.get('/request', headers={'X-Delegation-Token-V1': tok + 'blah'}, expect_errors=True) self.assertEqual(403, r.status_int) # Transient error. def mocked_check(*_args): raise delegation.TransientError('Blah') self.mock(delegation, 'check_bearer_delegation_token', mocked_check) r = app.get('/request', headers={'X-Delegation-Token-V1': tok}, expect_errors=True) self.assertEqual(500, r.status_int)
def test_works(self): api.reset_local_state() # to clear request-cached AuthDB # Subtoken proto. tok = fake_subtoken_proto('user:[email protected]', audience=['user:[email protected]']) # Sign, serialize. blob = delegation.serialize_token(delegation.seal_token(tok)) # Deserialize, check sig, validate. make_id = model.Identity.from_bytes ident = delegation.check_bearer_delegation_token( blob, make_id('user:[email protected]')) self.assertEqual(make_id('user:[email protected]'), ident)
def test_delegation_token(self): peer_ident = model.Identity.from_bytes('user:[email protected]') class Handler(handler.AuthenticatingHandler): @classmethod def get_auth_methods(cls, conf): return [lambda _request: peer_ident] @api.public def get(self): self.response.write(json.dumps({ 'peer_id': api.get_peer_identity().to_bytes(), 'cur_id': api.get_current_identity().to_bytes(), })) app = self.make_test_app('/request', Handler) def call(headers=None): return json.loads(app.get('/request', headers=headers).body) # No delegation. self.assertEqual( {u'cur_id': u'user:[email protected]', u'peer_id': u'user:[email protected]'}, call()) # TODO(vadimsh): Mint token via some high-level function call. subtokens = delegation_pb2.SubtokenList(subtokens=[ delegation_pb2.Subtoken( issuer_id='user:[email protected]', creation_time=int(utils.time_time()), validity_duration=3600), ]) tok = delegation.serialize_token(delegation.seal_token(subtokens)) # With valid delegation token. self.assertEqual( {u'cur_id': u'user:[email protected]', u'peer_id': u'user:[email protected]'}, call({'X-Delegation-Token-V1': tok})) # With invalid delegation token. r = app.get( '/request', headers={'X-Delegation-Token-V1': tok + 'blah'}, expect_errors=True) self.assertEqual(403, r.status_int) # Transient error. def mocked_check(*_args): raise delegation.TransientError('Blah') self.mock(delegation, 'check_delegation_token', mocked_check) r = app.get( '/request', headers={'X-Delegation-Token-V1': tok}, expect_errors=True) self.assertEqual(500, r.status_int)
def post(self): # Forbid usage of delegation tokens for this particular call. Using # delegation when creating delegation tokens is too deep. Redelegation will # be done as separate explicit API call that accept existing delegation # token via request body, not via headers. if auth.get_current_identity() != auth.get_peer_identity(): raise auth.AuthorizationError( 'This API call must not be used with active delegation token') # Convert request body to proto (with validation). Verify IP format. try: body = self.parse_body() subtoken = subtoken_from_jsonish(body) intent = body.get('intent') or '' if not isinstance(intent, basestring): raise TypeError('"intent" must be string') except (TypeError, ValueError) as exc: self.abort_with_error(400, text=str(exc)) # Fill in defaults. assert not subtoken.requestor_identity user_id = auth.get_current_identity().to_bytes() subtoken.requestor_identity = user_id if not subtoken.delegated_identity: subtoken.delegated_identity = user_id subtoken.creation_time = int(utils.time_time()) if not subtoken.validity_duration: subtoken.validity_duration = DEF_VALIDITY_DURATION_SEC if '*' in subtoken.services: subtoken.services[:] = get_default_allowed_services(user_id) # Check ACL (raises auth.AuthorizationError on errors). rule = check_can_create_token(user_id, subtoken) # Register the token in the datastore, generate its ID. subtoken.subtoken_id = register_subtoken(subtoken, rule, intent, auth.get_peer_ip()) # Create and sign the token. try: token = delegation.serialize_token(delegation.seal_token(subtoken)) except delegation.BadTokenError as exc: # This happens if resulting token is too large. self.abort_with_error(400, text=str(exc)) self.send_response(response={ 'delegation_token': token, 'subtoken_id': str(subtoken.subtoken_id), 'validity_duration': subtoken.validity_duration, }, http_code=201)
def test_works(self): # Subtoken list proto. toks = delegation_pb2.SubtokenList(subtokens=[ fake_subtoken_proto( 'user:[email protected]', audience=['user:[email protected]']), fake_subtoken_proto( 'user:[email protected]', audience=['user:[email protected]']), ]) # Sign, serialize. blob = delegation.serialize_token(delegation.seal_token(toks)) # Deserialize, check sig, validate. make_id = model.Identity.from_bytes ident = delegation.check_delegation_token(blob, make_id('user:[email protected]')) self.assertEqual(make_id('user:[email protected]'), ident)
def test_works(self): # Subtoken list proto. toks = delegation_pb2.SubtokenList(subtokens=[ fake_subtoken_proto('user:[email protected]', audience=['user:[email protected]']), fake_subtoken_proto('user:[email protected]', audience=['user:[email protected]']), ]) # Sign, serialize. blob = delegation.serialize_token(delegation.seal_token(toks)) # Deserialize, check sig, validate. make_id = model.Identity.from_bytes ident = delegation.check_delegation_token(blob, make_id('user:[email protected]')) self.assertEqual(make_id('user:[email protected]'), ident)
def post(self): # Forbid usage of delegation tokens for this particular call. Using # delegation when creating delegation tokens is too deep. Redelegation will # be done as separate explicit API call that accept existing delegation # token via request body, not via headers. if auth.get_current_identity() != auth.get_peer_identity(): raise auth.AuthorizationError( 'This API call must not be used with active delegation token') # Convert request body to proto (with validation). try: subtoken = subtoken_from_jsonish(self.parse_body()) except (TypeError, ValueError) as exc: self.abort_with_error(400, text=str(exc)) # Fill in defaults. assert not subtoken.impersonator_id user_id = auth.get_current_identity().to_bytes() if not subtoken.issuer_id: subtoken.issuer_id = user_id if subtoken.issuer_id != user_id: subtoken.impersonator_id = user_id subtoken.creation_time = int(utils.time_time()) if not subtoken.validity_duration: subtoken.validity_duration = DEF_VALIDITY_DURATION_SEC if not subtoken.services or '*' in subtoken.services: subtoken.services[:] = get_default_allowed_services(user_id) # Check ACL (raises auth.AuthorizationError on errors). check_can_create_token(user_id, subtoken) # Create and sign the token. try: token = delegation.serialize_token( delegation.seal_token( delegation_pb2.SubtokenList(subtokens=[subtoken]))) except delegation.BadTokenError as exc: # This happens if resulting token is too large. self.abort_with_error(400, text=str(exc)) self.send_response( response={ 'delegation_token': token, 'validity_duration': subtoken.validity_duration, }, http_code=201)
def post(self): # Forbid usage of delegation tokens for this particular call. Using # delegation when creating delegation tokens is too deep. Redelegation will # be done as separate explicit API call that accept existing delegation # token via request body, not via headers. if auth.get_current_identity() != auth.get_peer_identity(): raise auth.AuthorizationError( 'This API call must not be used with active delegation token') # Convert request body to proto (with validation). try: subtoken = subtoken_from_jsonish(self.parse_body()) except (TypeError, ValueError) as exc: self.abort_with_error(400, text=str(exc)) # Fill in defaults. assert not subtoken.impersonator_id user_id = auth.get_current_identity().to_bytes() if not subtoken.issuer_id: subtoken.issuer_id = user_id if subtoken.issuer_id != user_id: subtoken.impersonator_id = user_id subtoken.creation_time = int(utils.time_time()) if not subtoken.validity_duration: subtoken.validity_duration = DEF_VALIDITY_DURATION_SEC if not subtoken.services or '*' in subtoken.services: subtoken.services[:] = get_default_allowed_services(user_id) # Check ACL (raises auth.AuthorizationError on errors). check_can_create_token(user_id, subtoken) # Create and sign the token. try: token = delegation.serialize_token( delegation.seal_token( delegation_pb2.SubtokenList(subtokens=[subtoken]))) except delegation.BadTokenError as exc: # This happens if resulting token is too large. self.abort_with_error(400, text=str(exc)) self.send_response(response={ 'delegation_token': token, 'validity_duration': subtoken.validity_duration, }, http_code=201)
def test_delegation_token(self): def call(tok=None): headers = {'X-Delegation-Token-V1': tok} if tok else None self.call('127.0.0.1', '*****@*****.**', headers) return { 'cur_id': api.get_current_identity().to_bytes(), 'peer_id': api.get_current_identity().to_bytes(), } # No delegation. self.assertEqual( { 'cur_id': 'user:[email protected]', 'peer_id': 'user:[email protected]' }, call()) # TODO(vadimsh): Mint token via some high-level function call. subtokens = delegation_pb2.SubtokenList(subtokens=[ delegation_pb2.Subtoken(issuer_id='user:[email protected]', creation_time=int(utils.time_time()), validity_duration=3600), ]) tok = delegation.serialize_token(delegation.seal_token(subtokens)) # Valid delegation token. self.assertEqual( { 'cur_id': 'user:[email protected]', 'peer_id': 'user:[email protected]' }, call(tok)) # Invalid delegation token. with self.assertRaises(api.AuthorizationError): call(tok + 'blah') # Transient error. def mocked_check(*_args): raise delegation.TransientError('Blah') self.mock(delegation, 'check_delegation_token', mocked_check) with self.assertRaises(endpoints.InternalServerErrorException): call(tok)
def test_delegation_token(self): def call(tok=None): headers = {'X-Delegation-Token-V1': tok} if tok else None self.call('127.0.0.1', '*****@*****.**', headers) return { 'cur_id': api.get_current_identity().to_bytes(), 'peer_id': api.get_current_identity().to_bytes(), } # No delegation. self.assertEqual( {'cur_id': 'user:[email protected]', 'peer_id': 'user:[email protected]'}, call()) # TODO(vadimsh): Mint token via some high-level function call. subtokens = delegation_pb2.SubtokenList(subtokens=[ delegation_pb2.Subtoken( issuer_id='user:[email protected]', creation_time=int(utils.time_time()), validity_duration=3600), ]) tok = delegation.serialize_token(delegation.seal_token(subtokens)) # Valid delegation token. self.assertEqual( {'cur_id': 'user:[email protected]', 'peer_id': 'user:[email protected]'}, call(tok)) # Invalid delegation token. with self.assertRaises(api.AuthorizationError): call(tok + 'blah') # Transient error. def mocked_check(*_args): raise delegation.TransientError('Blah') self.mock(delegation, 'check_delegation_token', mocked_check) with self.assertRaises(endpoints.InternalServerErrorException): call(tok)
def test_unknown_signer_id(self): checker = delegation.SignatureChecker() # empty, no trusted signers self.mock(delegation, 'get_signature_checker', lambda: checker) with self.assertRaises(delegation.BadTokenError): delegation.unseal_token( delegation.seal_token(fake_subtoken_list_proto()))
def test_round_trip(self): toks = fake_subtoken_list_proto() self.assertEqual(toks, delegation.unseal_token(delegation.seal_token(toks)))
def test_unknown_signing_key_id(self): msg = delegation.seal_token(fake_subtoken_list_proto()) msg.signing_key_id = 'blah' with self.assertRaises(delegation.BadTokenError): delegation.unseal_token(msg)
def test_bad_signature(self): msg = delegation.seal_token(fake_subtoken_list_proto()) msg.pkcs1_sha256_sig = msg.pkcs1_sha256_sig[:-1] + 'A' with self.assertRaises(delegation.BadTokenError): delegation.unseal_token(msg)
def test_bad_signer_id(self): msg = delegation.seal_token(fake_subtoken_list_proto()) msg.signer_id = 'not an identity' with self.assertRaises(delegation.BadTokenError): delegation.unseal_token(msg)
def test_unknown_signer_id(self): checker = delegation.SignatureChecker() # empty, no trusted signers self.mock(delegation, 'get_signature_checker', lambda: checker) with self.assertRaises(delegation.BadTokenError): delegation.unseal_token(delegation.seal_token(fake_subtoken_list_proto()))
def test_unknown_signing_key_id(self): msg = delegation.seal_token(fake_subtoken_proto()) msg.signing_key_id = 'blah' with self.assertRaises(delegation.BadTokenError): delegation.unseal_token(msg)
def test_bad_signature(self): msg = delegation.seal_token(fake_subtoken_proto()) msg.pkcs1_sha256_sig = msg.pkcs1_sha256_sig[:-1] + 'A' with self.assertRaises(delegation.BadTokenError): delegation.unseal_token(msg)
def test_unknown_signer_id(self): # Empty dict, no trusted signers. self.mock(delegation, 'get_trusted_signers', lambda: {}) with self.assertRaises(delegation.BadTokenError): delegation.unseal_token( delegation.seal_token(fake_subtoken_proto()))
def test_bad_signer_id(self): msg = delegation.seal_token(fake_subtoken_proto()) msg.signer_id = 'not an identity' with self.assertRaises(delegation.BadTokenError): delegation.unseal_token(msg)
def test_round_trip(self): tok = fake_subtoken_proto() self.assertEqual(tok, delegation.unseal_token(delegation.seal_token(tok)))