Add JSON schema and validation for implied role

Change-Id: I6bdd351a177b6c36e3f205da3c81fea218bd9039
This commit is contained in:
0weng 2024-12-11 14:47:02 -08:00
parent 0a690d47b2
commit 488167f8d7
3 changed files with 119 additions and 0 deletions

View File

@ -15,6 +15,8 @@
import flask_restful import flask_restful
from keystone.api._shared import implied_roles as shared from keystone.api._shared import implied_roles as shared
from keystone.api import validation
from keystone.assignment import schema
from keystone.common import provider_api from keystone.common import provider_api
from keystone.common import rbac_enforcer from keystone.common import rbac_enforcer
from keystone.server import flask as ks_flask from keystone.server import flask as ks_flask
@ -24,6 +26,10 @@ PROVIDERS = provider_api.ProviderAPIs
class RoleInferencesResource(flask_restful.Resource): class RoleInferencesResource(flask_restful.Resource):
@validation.request_body_schema(None)
@validation.response_body_schema(
schema.role_inferences_index_response_body
)
def get(self): def get(self):
"""List role inference rules. """List role inference rules.

View File

@ -218,6 +218,8 @@ def _build_enforcement_target_ref():
class RoleImplicationListResource(flask_restful.Resource): class RoleImplicationListResource(flask_restful.Resource):
@validation.request_body_schema(None)
@validation.response_body_schema(schema.role_inference_show_response_body)
def get(self, prior_role_id): def get(self, prior_role_id):
"""List Implied Roles. """List Implied Roles.
@ -243,6 +245,8 @@ class RoleImplicationListResource(flask_restful.Resource):
class RoleImplicationResource(flask_restful.Resource): class RoleImplicationResource(flask_restful.Resource):
@validation.request_body_schema(None)
@validation.response_body_schema(None)
def head(self, prior_role_id, implied_role_id=None): def head(self, prior_role_id, implied_role_id=None):
# TODO(morgan): deprecate "check_implied_role" policy, as a user must # TODO(morgan): deprecate "check_implied_role" policy, as a user must
# have both check_implied_role and get_implied_role to use the head # have both check_implied_role and get_implied_role to use the head
@ -261,6 +265,8 @@ class RoleImplicationResource(flask_restful.Resource):
# here is incorrect. It is maintained as is for API contract reasons. # here is incorrect. It is maintained as is for API contract reasons.
return None, http.client.NO_CONTENT return None, http.client.NO_CONTENT
@validation.request_body_schema(None)
@validation.response_body_schema(schema.implied_role_show_response_body)
def get(self, prior_role_id, implied_role_id): def get(self, prior_role_id, implied_role_id):
"""Get implied role. """Get implied role.
@ -287,6 +293,8 @@ class RoleImplicationResource(flask_restful.Resource):
} }
return response_json return response_json
@validation.request_body_schema(None)
@validation.response_body_schema(schema.implied_role_show_response_body)
def put(self, prior_role_id, implied_role_id): def put(self, prior_role_id, implied_role_id):
"""Create implied role. """Create implied role.
@ -300,6 +308,8 @@ class RoleImplicationResource(flask_restful.Resource):
response_json = self._get_implied_role(prior_role_id, implied_role_id) response_json = self._get_implied_role(prior_role_id, implied_role_id)
return response_json, http.client.CREATED return response_json, http.client.CREATED
@validation.request_body_schema(None)
@validation.response_body_schema(None)
def delete(self, prior_role_id, implied_role_id): def delete(self, prior_role_id, implied_role_id):
"""Delete implied role. """Delete implied role.

View File

@ -120,3 +120,106 @@ role_update_request_body = {
"required": ["role"], "required": ["role"],
"additionalProperties": False, "additionalProperties": False,
} }
# Individual properties of a returned prior/implied role
_implied_role_properties: dict[str, Any] = {
"id": {
"type": "string",
"format": "uuid",
"description": "The role ID.",
"readOnly": True,
},
"links": response_types.resource_links,
"name": parameter_types.name,
}
# Common schema of prior role
prior_role_schema: dict[str, Any] = {
"type": "object",
"description": "A prior role object.",
"properties": _implied_role_properties,
"additionalProperties": False,
}
# Common schema of implied role
implied_role_schema: dict[str, Any] = {
"type": "object",
"description": "An implied role object.",
"properties": _implied_role_properties,
"additionalProperties": False,
}
# Response body of API operations returning a single implied role
# `GET /v3/roles/{prior_role_id}/implies/{implies_role_id}`
# and `PUT /v3/roles/{prior_role_id}/implies/{implies_role_id}`
implied_role_show_response_body: dict[str, Any] = {
"type": "object",
"properties": {
"role_inference": {
"type": "object",
"description": (
"Role inference object that contains "
"prior_role object and implies object."
),
"properties": {
"prior_role": prior_role_schema,
"implies": implied_role_schema,
},
"additionalProperties": False,
},
"links": response_types.links,
},
"additionalProperties": False,
}
# Response body of the `GET /v3/roles/{prior_role_id}/implies` API operation
# returning a single role inference
role_inference_show_response_body: dict[str, Any] = {
"type": "object",
"properties": {
"role_inference": {
"type": "object",
"description": "A role inference object.",
"properties": {
"prior_role": prior_role_schema,
"implies": {
"type": "array",
"items": implied_role_schema,
"description": "A list of implied role objects.",
},
},
"additionalProperties": False,
},
"links": response_types.links,
},
"additionalProperties": False,
}
# Response body of the `GET /v3/role_inferences` API operation
# returning a list of role inferences
role_inferences_index_response_body: dict[str, Any] = {
"type": "object",
"properties": {
"role_inferences": {
"type": "array",
"description": "A list of role inference objects.",
"items": {
"type": "object",
"properties": {
# NOTE(0weng): The example in the docs incorrectly
# includes the `description` field in the output.
"prior_role": prior_role_schema,
"implies": {
"type": "array",
"items": implied_role_schema,
"description": "A list of implied role objects.",
},
},
"additionalProperties": False,
},
"additionalProperties": False,
},
"links": response_types.links,
},
"additionalProperties": False,
}