From d8cb5a3e9339a67aab13c2af31bfbff39b14fbc6 Mon Sep 17 00:00:00 2001 From: Guang Yee Date: Tue, 24 May 2016 17:24:47 -0700 Subject: [PATCH] Make sure audit can handle API requests which does not require a token Some service APIs such as Swift list public containers does not require a token. Therefore, there will be no identity or service catalog information available. In these cases, audit should fill in the default (i.e. taxonomy.UNKNOWN) for both initiator and target instead of raising an exception. Change-Id: I3f3c12d5e8c0fa176fb7f0218c368971e0a9d0b5 Closes-Bug: 1583699 --- keystonemiddleware/audit.py | 25 +++++++----- .../tests/unit/test_audit_middleware.py | 40 +++++++++++++++++++ .../notes/bug-1583699-dba4fe6c057e2be5.yaml | 9 +++++ 3 files changed, 65 insertions(+), 9 deletions(-) create mode 100644 releasenotes/notes/bug-1583699-dba4fe6c057e2be5.yaml diff --git a/keystonemiddleware/audit.py b/keystonemiddleware/audit.py index 84de1530..a7247ee4 100644 --- a/keystonemiddleware/audit.py +++ b/keystonemiddleware/audit.py @@ -51,7 +51,7 @@ from six.moves import configparser from six.moves.urllib import parse as urlparse import webob.dec -from keystonemiddleware.i18n import _LE, _LI +from keystonemiddleware.i18n import _LE, _LI, _LW _LOG = None @@ -286,13 +286,19 @@ class OpenStackAuditApi(object): service_info = Service(type=taxonomy.UNKNOWN, name=taxonomy.UNKNOWN, id=taxonomy.UNKNOWN, admin_endp=None, private_endp=None, public_endp=None) + + catalog = {} try: catalog = ast.literal_eval( req.environ['HTTP_X_SERVICE_CATALOG']) except KeyError: - raise PycadfAuditApiConfigError( - 'Service catalog is missing. ' - 'Cannot discover target information') + _LOG.warning(_LW('Unable to discover target information because ' + 'service catalog is missing. Either the incoming ' + 'request does not contain an auth token or auth ' + 'token does not contain a service catalog. For ' + 'the latter, please make sure the ' + '"include_service_catalog" property in ' + 'auth_token middleware is set to "True"')) default_endpoint = None for endp in catalog: @@ -431,13 +437,14 @@ class AuditMiddleware(object): initiator = ClientResource( typeURI=taxonomy.ACCOUNT_USER, - id=req.environ['HTTP_X_USER_ID'], - name=req.environ['HTTP_X_USER_NAME'], + id=req.environ.get('HTTP_X_USER_ID', taxonomy.UNKNOWN), + name=req.environ.get('HTTP_X_USER_NAME', taxonomy.UNKNOWN), host=host.Host(address=req.client_addr, agent=req.user_agent), credential=KeystoneCredential( - token=req.environ['HTTP_X_AUTH_TOKEN'], - identity_status=req.environ['HTTP_X_IDENTITY_STATUS']), - project_id=req.environ['HTTP_X_PROJECT_ID']) + token=req.environ.get('HTTP_X_AUTH_TOKEN', ''), + identity_status=req.environ.get('HTTP_X_IDENTITY_STATUS', + taxonomy.UNKNOWN)), + project_id=req.environ.get('HTTP_X_PROJECT_ID', taxonomy.UNKNOWN)) target = self._cadf_audit.get_target_resource(req) event = factory.EventFactory().new_event( diff --git a/keystonemiddleware/tests/unit/test_audit_middleware.py b/keystonemiddleware/tests/unit/test_audit_middleware.py index 6a2410ea..110fb33a 100644 --- a/keystonemiddleware/tests/unit/test_audit_middleware.py +++ b/keystonemiddleware/tests/unit/test_audit_middleware.py @@ -703,3 +703,43 @@ class AuditApiLogicTest(BaseAuditMiddlewareTest): self.middleware._process_request(req) payload = req.environ['cadf_event'].as_dict() self.assertEqual((payload['target']['addresses'][0]['url']), "unknown") + + def test_no_auth_token(self): + # Test cases where API requests such as Swift list public containers + # which does not require an auth token. In these cases, CADF event + # should have the defaults (i.e taxonomy.UNKNOWN) instead of raising + # an exception. + env_headers = {'HTTP_X_IDENTITY_STATUS': 'Invalid', + 'REQUEST_METHOD': 'GET'} + req = webob.Request.blank('https://23.253.72.207/v1/' + + str(uuid.uuid4()), + environ=env_headers, + remote_addr='192.168.0.1') + req.context = {} + self.middleware._process_request(req) + payload = req.environ['cadf_event'].as_dict() + self.assertEqual(payload['action'], 'read') + self.assertEqual(payload['typeURI'], + 'http://schemas.dmtf.org/cloud/audit/1.0/event') + self.assertEqual(payload['outcome'], 'pending') + self.assertEqual(payload['eventType'], 'activity') + self.assertEqual(payload['target']['name'], taxonomy.UNKNOWN) + self.assertEqual(payload['target']['id'], taxonomy.UNKNOWN) + self.assertEqual(payload['target']['typeURI'], taxonomy.UNKNOWN) + self.assertNotIn('addresses', payload['target']) + self.assertEqual(payload['initiator']['id'], taxonomy.UNKNOWN) + self.assertEqual(payload['initiator']['name'], taxonomy.UNKNOWN) + self.assertEqual(payload['initiator']['project_id'], + taxonomy.UNKNOWN) + self.assertEqual(payload['initiator']['host']['address'], + '192.168.0.1') + self.assertEqual(payload['initiator']['typeURI'], + 'service/security/account/user') + self.assertNotEqual(payload['initiator']['credential']['token'], + None) + self.assertEqual(payload['initiator']['credential']['identity_status'], + 'Invalid') + self.assertNotIn('reason', payload) + self.assertNotIn('reporterchain', payload) + self.assertEqual(payload['observer']['id'], 'target') + self.assertEqual(req.path, payload['requestPath']) diff --git a/releasenotes/notes/bug-1583699-dba4fe6c057e2be5.yaml b/releasenotes/notes/bug-1583699-dba4fe6c057e2be5.yaml new file mode 100644 index 00000000..6b141fed --- /dev/null +++ b/releasenotes/notes/bug-1583699-dba4fe6c057e2be5.yaml @@ -0,0 +1,9 @@ +--- +fixes: + - > + [`bug 1583699 `_] + Some service APIs (such as Swift list public containers) do not require + a token. Therefore, there will be no identity or service catalog + information available. In these cases, audit now fills in the default + (i.e. taxonomy.UNKNOWN) for both initiator and target instead of raising + an exception.