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.