Inspecting Keystone Routes

What Policy is enforced when you call a Keystone API? Right now, there is no definitive way to say. However, with some programmatic help, we might be able to figure it out from the source code. Lets start by getting a complete list of the Keystone routes.

In the WSGI framework that Keystone uses, a Route is the object that used to match the URL. For example, when I try to look at the user with UserId abcd1234, I submit a GET request to the URL https://hostname:port/v3/users/abcd1234. The route path is the pattern /users/{user_id}. The WSGI framework handles the parts of the URL prior to that, and eventually needs to pull out a Python function to execute for the route. Here is how we can generate a list of the route paths in Keystone

from keystone.server import wsgi
app = wsgi.initialize_admin_application()
composing = app['/v3'].application.application.application.application.application.application._app.application.application.application.application
for route in composing._router.mapper.matchlist:
    print(route.routepath)

I’ll put the output at the end of this post.

That long chain of .application properties is due to the way that the pipeline is built using the paste file. In keystone/etc/keystone-paste.ini we see:

[pipeline:api_v3]
# The last item in this pipeline must be service_v3 or an equivalent
# application. It cannot be a filter.
pipeline = healthcheck cors sizelimit http_proxy_to_wsgi osprofiler url_normalize request_id build_auth_context token_auth json_body ec2_extension_v3 s3_extension service_v3

Each of those pipeline elements are python classes specified earlier in the file, that honor the middleware contract. Most of these can be traced back to the keystone.common.wsgi.Middleware base class, which implements this as __call__ method.

    @webob.dec.wsgify(RequestClass=request_mod.Request)
    @middleware_exceptions
    def __call__(self, request):
        response = self.process_request(request)
        if response:
            return response
        response = request.get_response(self.application)
        return self.process_response(request, response)

The odd middleware out is AuthContextMiddleware which extends from from keystonemiddleware.auth_token.BaseAuthProtocol. See if you can spot the difference:

    @webob.dec.wsgify(RequestClass=_request._AuthTokenRequest)
    def __call__(self, req):
        """Handle incoming request."""
        response = self.process_request(req)
        if response:c
            return response
        response = req.get_response(self._app)
        return self.process_response(response

Yep: self._app.

Here is the output from the above code, executed in the python interpreter. This does not have the Verbs in it yet, but a little more poking should show where they are stored:

>>> for route in composing._router.mapper.matchlist:
...     print(route.routepath)
... 
/auth/tokens
/auth/tokens
/auth/tokens
/auth/tokens
/auth/tokens/OS-PKI/revoked
/auth/catalog
/auth/projects
/auth/domains
/auth/system
/users/{user_id}/projects
/roles/{prior_role_id}/implies
/roles/{prior_role_id}/implies/{implied_role_id}
/roles/{prior_role_id}/implies/{implied_role_id}
/roles/{prior_role_id}/implies/{implied_role_id}
/roles/{prior_role_id}/implies/{implied_role_id}
/role_inferences
/projects/{project_id}/users/{user_id}/roles/{role_id}
/projects/{project_id}/users/{user_id}/roles/{role_id}
/projects/{project_id}/users/{user_id}/roles/{role_id}
/projects/{project_id}/groups/{group_id}/roles/{role_id}
/projects/{project_id}/groups/{group_id}/roles/{role_id}
/projects/{project_id}/groups/{group_id}/roles/{role_id}
/projects/{project_id}/users/{user_id}/roles
/projects/{project_id}/groups/{group_id}/roles
/domains/{domain_id}/users/{user_id}/roles/{role_id}
/domains/{domain_id}/users/{user_id}/roles/{role_id}
/domains/{domain_id}/users/{user_id}/roles/{role_id}
/domains/{domain_id}/groups/{group_id}/roles/{role_id}
/domains/{domain_id}/groups/{group_id}/roles/{role_id}
/domains/{domain_id}/groups/{group_id}/roles/{role_id}
/domains/{domain_id}/users/{user_id}/roles
/domains/{domain_id}/groups/{group_id}/roles
/system/users/{user_id}/roles
/system/users/{user_id}/roles/{role_id}
/system/users/{user_id}/roles/{role_id}
/system/users/{user_id}/roles/{role_id}
/system/groups/{group_id}/roles
/system/groups/{group_id}/roles/{role_id}
/system/groups/{group_id}/roles/{role_id}
/system/groups/{group_id}/roles/{role_id}
/role_assignments
/OS-INHERIT/domains/{domain_id}/users/{user_id}/roles/{role_id}/inherited_to_projects
/OS-INHERIT/domains/{domain_id}/users/{user_id}/roles/{role_id}/inherited_to_projects
/OS-INHERIT/domains/{domain_id}/users/{user_id}/roles/{role_id}/inherited_to_projects
/OS-INHERIT/domains/{domain_id}/groups/{group_id}/roles/{role_id}/inherited_to_projects
/OS-INHERIT/domains/{domain_id}/groups/{group_id}/roles/{role_id}/inherited_to_projects
/OS-INHERIT/domains/{domain_id}/groups/{group_id}/roles/{role_id}/inherited_to_projects
/OS-INHERIT/domains/{domain_id}/groups/{group_id}/roles/inherited_to_projects
/OS-INHERIT/domains/{domain_id}/users/{user_id}/roles/inherited_to_projects
/OS-INHERIT/projects/{project_id}/users/{user_id}/roles/{role_id}/inherited_to_projects
/OS-INHERIT/projects/{project_id}/users/{user_id}/roles/{role_id}/inherited_to_projects
/OS-INHERIT/projects/{project_id}/users/{user_id}/roles/{role_id}/inherited_to_projects
/OS-INHERIT/projects/{project_id}/groups/{group_id}/roles/{role_id}/inherited_to_projects
/OS-INHERIT/projects/{project_id}/groups/{group_id}/roles/{role_id}/inherited_to_projects
/OS-INHERIT/projects/{project_id}/groups/{group_id}/roles/{role_id}/inherited_to_projects
/regions/{region_id}
/OS-EP-FILTER/endpoints/{endpoint_id}/projects
/OS-EP-FILTER/projects/{project_id}/endpoints/{endpoint_id}
/OS-EP-FILTER/projects/{project_id}/endpoints/{endpoint_id}
/OS-EP-FILTER/projects/{project_id}/endpoints/{endpoint_id}
/OS-EP-FILTER/projects/{project_id}/endpoints
/OS-EP-FILTER/projects/{project_id}/endpoint_groups
/OS-EP-FILTER/endpoint_groups
/OS-EP-FILTER/endpoint_groups
/OS-EP-FILTER/endpoint_groups/{endpoint_group_id}
/OS-EP-FILTER/endpoint_groups/{endpoint_group_id}
/OS-EP-FILTER/endpoint_groups/{endpoint_group_id}
/OS-EP-FILTER/endpoint_groups/{endpoint_group_id}/projects/{project_id}
/OS-EP-FILTER/endpoint_groups/{endpoint_group_id}/projects/{project_id}
/OS-EP-FILTER/endpoint_groups/{endpoint_group_id}/projects/{project_id}
/OS-EP-FILTER/endpoint_groups/{endpoint_group_id}/projects
/OS-EP-FILTER/endpoint_groups/{endpoint_group_id}/endpoints
/users/{user_id}/password
/groups/{group_id}/users
/groups/{group_id}/users/{user_id}
/groups/{group_id}/users/{user_id}
/groups/{group_id}/users/{user_id}
/users/{user_id}/groups
/users/{user_id}/application_credentials
/users/{user_id}/application_credentials
/users/{user_id}/application_credentials/{application_credential_id}
/users/{user_id}/application_credentials/{application_credential_id}
/registered_limits
/registered_limits
/registered_limits
/registered_limits/{registered_limit_id}
/registered_limits/{registered_limit_id}
/limits
/limits
/limits
/limits/{limit_id}
/limits/{limit_id}
/domains/{domain_id}/config
/domains/{domain_id}/config
/domains/{domain_id}/config
/domains/{domain_id}/config
/domains/{domain_id}/config/{group}
/domains/{domain_id}/config/{group}
/domains/{domain_id}/config/{group}
/domains/{domain_id}/config/{group}/{option}
/domains/{domain_id}/config/{group}/{option}
/domains/{domain_id}/config/{group}/{option}
/domains/config/default
/domains/config/{group}/default
/domains/config/{group}/{option}/default
/projects/{project_id}/tags
/projects/{project_id}/tags
/projects/{project_id}/tags
/projects/{project_id}/tags/{value}
/projects/{project_id}/tags/{value}
/projects/{project_id}/tags/{value}
/OS-REVOKE/events
/OS-FEDERATION/identity_providers/{idp_id}
/OS-FEDERATION/identity_providers/{idp_id}
/OS-FEDERATION/identity_providers/{idp_id}
/OS-FEDERATION/identity_providers/{idp_id}
/OS-FEDERATION/identity_providers
/OS-FEDERATION/identity_providers/{idp_id}/protocols/{protocol_id}
/OS-FEDERATION/identity_providers/{idp_id}/protocols/{protocol_id}
/OS-FEDERATION/identity_providers/{idp_id}/protocols/{protocol_id}
/OS-FEDERATION/identity_providers/{idp_id}/protocols/{protocol_id}
/OS-FEDERATION/identity_providers/{idp_id}/protocols
/OS-FEDERATION/mappings/{mapping_id}
/OS-FEDERATION/mappings/{mapping_id}
/OS-FEDERATION/mappings/{mapping_id}
/OS-FEDERATION/mappings/{mapping_id}
/OS-FEDERATION/mappings
/OS-FEDERATION/service_providers/{sp_id}
/OS-FEDERATION/service_providers/{sp_id}
/OS-FEDERATION/service_providers/{sp_id}
/OS-FEDERATION/service_providers/{sp_id}
/OS-FEDERATION/service_providers
/OS-FEDERATION/domains
/OS-FEDERATION/projects
/OS-FEDERATION/identity_providers/{idp_id}/protocols/{protocol_id}/auth
/auth/OS-FEDERATION/saml2
/auth/OS-FEDERATION/saml2/ecp
/auth/OS-FEDERATION/websso/{protocol_id}
/auth/OS-FEDERATION/identity_providers/{idp_id}/protocols/{protocol_id}/websso
/OS-FEDERATION/saml2/metadata
/OS-OAUTH1/consumers
/OS-OAUTH1/consumers
/OS-OAUTH1/consumers/{consumer_id}
/OS-OAUTH1/consumers/{consumer_id}
/OS-OAUTH1/consumers/{consumer_id}
/users/{user_id}/OS-OAUTH1/access_tokens
/users/{user_id}/OS-OAUTH1/access_tokens/{access_token_id}
/users/{user_id}/OS-OAUTH1/access_tokens/{access_token_id}
/users/{user_id}/OS-OAUTH1/access_tokens/{access_token_id}/roles
/users/{user_id}/OS-OAUTH1/access_tokens/{access_token_id}/roles/{role_id}
/OS-OAUTH1/request_token
/OS-OAUTH1/access_token
/OS-OAUTH1/authorize/{request_token_id}
/endpoints/{endpoint_id}/OS-ENDPOINT-POLICY/policy
/policies/{policy_id}/OS-ENDPOINT-POLICY/endpoints
/policies/{policy_id}/OS-ENDPOINT-POLICY/endpoints/{endpoint_id}
/policies/{policy_id}/OS-ENDPOINT-POLICY/endpoints/{endpoint_id}
/policies/{policy_id}/OS-ENDPOINT-POLICY/endpoints/{endpoint_id}
/policies/{policy_id}/OS-ENDPOINT-POLICY/services/{service_id}
/policies/{policy_id}/OS-ENDPOINT-POLICY/services/{service_id}
/policies/{policy_id}/OS-ENDPOINT-POLICY/services/{service_id}
/policies/{policy_id}/OS-ENDPOINT-POLICY/services/{service_id}/regions/{region_id}
/policies/{policy_id}/OS-ENDPOINT-POLICY/services/{service_id}/regions/{region_id}
/policies/{policy_id}/OS-ENDPOINT-POLICY/services/{service_id}/regions/{region_id}
/OS-SIMPLE-CERT/ca
/OS-SIMPLE-CERT/certificates
/OS-TRUST/trusts
/OS-TRUST/trusts
/OS-TRUST/trusts/{trust_id}
/OS-TRUST/trusts/{trust_id}
/OS-TRUST/trusts/{trust_id}/roles
/OS-TRUST/trusts/{trust_id}/roles/{role_id}
/roles
/roles
/roles/{role_id}
/roles/{role_id}
/roles/{role_id}
/regions
/regions
/regions/{region_id}
/regions/{region_id}
/regions/{region_id}
/services
/services
/services/{service_id}
/services/{service_id}
/services/{service_id}
/endpoints
/endpoints
/endpoints/{endpoint_id}
/endpoints/{endpoint_id}
/endpoints/{endpoint_id}
/credentials
/credentials
/credentials/{credential_id}
/credentials/{credential_id}
/credentials/{credential_id}
/users
/users
/users/{user_id}
/users/{user_id}
/users/{user_id}
/groups
/groups
/groups/{group_id}
/groups/{group_id}
/groups/{group_id}
/policies
/policies
/policies/{policy_id}
/policies/{policy_id}
/policies/{policy_id}
/domains
/domains
/domains/{domain_id}
/domains/{domain_id}
/domains/{domain_id}
/projects
/projects
/projects/{project_id}
/projects/{project_id}
/projects/{project_id}
/

Leave a Reply

Your email address will not be published. Required fields are marked *