Fix Secure RBAC policies for Secrets
This patch fixes policy issues for deployments that have not yet opted into the Secure RBAC defaults by making sure that the new policies are only evaluated when enforce_new_defaults = True. This prevents policy side-effects where some users with roles used in the new policy defaults are able to access APIs that they were not allowed to access with the legacy deprecated policies. This patch also deprecates the old policies using DeprecatedRule objects from olso_policy to ensure that the enforce_new_defaults option works as expected. Story: 2010235 Depends-On: I16ed904eeb27ab7110a7e4e56ef7ea89c8c3c2ab Change-Id: I224c50a8bf9f540f8f643339a4beeaff36ca6509
This commit is contained in:
parent
ff7fef6211
commit
cd9b0ba9f0
@ -18,9 +18,12 @@ from webob import exc
|
||||
|
||||
from barbican import api
|
||||
from barbican.common import accept
|
||||
from barbican.common import config
|
||||
from barbican.common import utils
|
||||
from barbican import i18n as u
|
||||
|
||||
|
||||
CONF = config.CONF
|
||||
LOG = utils.getLogger(__name__)
|
||||
|
||||
|
||||
@ -55,14 +58,17 @@ def _do_enforce_rbac(inst, req, action_name, ctx, **kwargs):
|
||||
action_name = 'secret:decrypt' # Override to perform special rules
|
||||
|
||||
target_name, target_data = inst.get_acl_tuple(req, **kwargs)
|
||||
policy_dict = {}
|
||||
policy_dict = {
|
||||
"enforce_new_defaults": CONF.oslo_policy.enforce_new_defaults
|
||||
}
|
||||
if target_name and target_data:
|
||||
policy_dict['target'] = {target_name: target_data}
|
||||
|
||||
policy_dict.update(kwargs)
|
||||
# Enforce access controls.
|
||||
if ctx.policy_enforcer:
|
||||
ctx.policy_enforcer.authorize(action_name, flatten(policy_dict),
|
||||
target = flatten(policy_dict)
|
||||
ctx.policy_enforcer.authorize(action_name, target,
|
||||
ctx, do_raise=True)
|
||||
|
||||
|
||||
|
@ -75,9 +75,21 @@ rules = [
|
||||
name='container_non_private_read',
|
||||
check_str="rule:all_users and rule:container_project_match and not " +
|
||||
"rule:container_private_read"),
|
||||
policy.RuleDefault(
|
||||
name='secret_project_reader',
|
||||
check_str='role:reader and rule:secret_project_match'),
|
||||
policy.RuleDefault(
|
||||
name='secret_project_member',
|
||||
check_str='role:member and rule:secret_project_match'),
|
||||
policy.RuleDefault(
|
||||
name='secret_project_admin',
|
||||
check_str="rule:admin and rule:secret_project_match"),
|
||||
check_str='rule:admin and rule:secret_project_match'),
|
||||
policy.RuleDefault(
|
||||
name='secret_owner',
|
||||
check_str='user_id:%(target.secret.creator_id)s'),
|
||||
policy.RuleDefault(
|
||||
name='secret_is_not_private',
|
||||
check_str='True:%(target.secret.read_project_access)s'),
|
||||
policy.RuleDefault(
|
||||
name='secret_project_creator',
|
||||
check_str="rule:creator and rule:secret_project_match and " +
|
||||
|
@ -10,25 +10,68 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_log import versionutils
|
||||
from oslo_policy import policy
|
||||
|
||||
|
||||
_READER = "role:reader"
|
||||
_MEMBER = "role:member"
|
||||
_ADMIN = "role:admin"
|
||||
_PROJECT_MEMBER = f"{_MEMBER} and project_id:%(target.secret.project_id)s"
|
||||
_PROJECT_ADMIN = f"{_ADMIN} and project_id:%(target.secret.project_id)s"
|
||||
_SECRET_CREATOR = "user_id:%(target.secret.creator_id)s"
|
||||
_SECRET_IS_NOT_PRIVATE = "True:%(target.secret.read_project_access)s"
|
||||
_LEGACY_POLICY_DEPRECATION = (
|
||||
'The default policy for the Key Manager API has been updated '
|
||||
'to use scopes and default roles.'
|
||||
)
|
||||
|
||||
deprecated_secret_decrypt = policy.DeprecatedRule(
|
||||
name='secret:decrypt',
|
||||
check_str='rule:secret_decrypt_non_private_read or ' +
|
||||
'rule:secret_project_creator or ' +
|
||||
'rule:secret_project_admin or rule:secret_acl_read',
|
||||
deprecated_reason=_LEGACY_POLICY_DEPRECATION,
|
||||
deprecated_since=versionutils.deprecated.ZED
|
||||
)
|
||||
deprecated_secret_get = policy.DeprecatedRule(
|
||||
name='secret:get',
|
||||
check_str='rule:secret_non_private_read or ' +
|
||||
'rule:secret_project_creator or ' +
|
||||
'rule:secret_project_admin or rule:secret_acl_read',
|
||||
deprecated_reason=_LEGACY_POLICY_DEPRECATION,
|
||||
deprecated_since=versionutils.deprecated.ZED
|
||||
)
|
||||
deprecated_secret_put = policy.DeprecatedRule(
|
||||
name='secret:put',
|
||||
check_str='rule:admin_or_creator and rule:secret_project_match',
|
||||
deprecated_reason=_LEGACY_POLICY_DEPRECATION,
|
||||
deprecated_since=versionutils.deprecated.ZED
|
||||
)
|
||||
deprecated_secret_delete = policy.DeprecatedRule(
|
||||
name='secret:delete',
|
||||
check_str='rule:secret_project_admin or ' +
|
||||
'rule:secret_project_creator or ' +
|
||||
'(rule:secret_project_creator_role and ' +
|
||||
'not rule:secret_private_read)',
|
||||
deprecated_reason=_LEGACY_POLICY_DEPRECATION,
|
||||
deprecated_since=versionutils.deprecated.ZED
|
||||
)
|
||||
deprecated_secrets_post = policy.DeprecatedRule(
|
||||
name='secrets:post',
|
||||
check_str='rule:admin_or_creator',
|
||||
deprecated_reason=_LEGACY_POLICY_DEPRECATION,
|
||||
deprecated_since=versionutils.deprecated.ZED
|
||||
)
|
||||
deprecated_secrets_get = policy.DeprecatedRule(
|
||||
name='secrets:get',
|
||||
check_str='rule:all_but_audit',
|
||||
deprecated_reason=_LEGACY_POLICY_DEPRECATION,
|
||||
deprecated_since=versionutils.deprecated.ZED
|
||||
)
|
||||
|
||||
rules = [
|
||||
policy.DocumentedRuleDefault(
|
||||
name='secret:decrypt',
|
||||
check_str='rule:secret_decrypt_non_private_read or ' +
|
||||
'rule:secret_project_creator or ' +
|
||||
'rule:secret_project_admin or rule:secret_acl_read or ' +
|
||||
f"({_PROJECT_MEMBER} and ({_SECRET_CREATOR} or " +
|
||||
f"{_SECRET_IS_NOT_PRIVATE})) or {_PROJECT_ADMIN}",
|
||||
check_str=(
|
||||
"True:%(enforce_new_defaults)s and "
|
||||
"(rule:secret_project_admin or "
|
||||
"(rule:secret_project_member and rule:secret_owner) or "
|
||||
"(rule:secret_project_member and rule:secret_is_not_private) or "
|
||||
"rule:secret_acl_read)"),
|
||||
scope_types=['project'],
|
||||
description='Retrieve a secrets payload.',
|
||||
operations=[
|
||||
@ -36,15 +79,17 @@ rules = [
|
||||
'path': '/v1/secrets/{uuid}/payload',
|
||||
'method': 'GET'
|
||||
}
|
||||
]
|
||||
],
|
||||
deprecated_rule=deprecated_secret_decrypt
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name='secret:get',
|
||||
check_str='rule:secret_non_private_read or ' +
|
||||
'rule:secret_project_creator or ' +
|
||||
'rule:secret_project_admin or rule:secret_acl_read or ' +
|
||||
f"({_PROJECT_MEMBER} and ({_SECRET_CREATOR} or " +
|
||||
f"{_SECRET_IS_NOT_PRIVATE})) or {_PROJECT_ADMIN}",
|
||||
check_str=(
|
||||
"True:%(enforce_new_defaults)s and "
|
||||
"(rule:secret_project_admin or "
|
||||
"(rule:secret_project_member and rule:secret_owner) or "
|
||||
"(rule:secret_project_member and rule:secret_is_not_private) or "
|
||||
"rule:secret_acl_read)"),
|
||||
scope_types=['project'],
|
||||
description='Retrieves a secrets metadata.',
|
||||
operations=[
|
||||
@ -52,13 +97,16 @@ rules = [
|
||||
'path': '/v1/secrets/{secret-id}',
|
||||
'method': 'GET'
|
||||
}
|
||||
]
|
||||
],
|
||||
deprecated_rule=deprecated_secret_get
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name='secret:put',
|
||||
check_str='rule:admin_or_creator and rule:secret_project_match or ' +
|
||||
f"({_PROJECT_MEMBER} and ({_SECRET_CREATOR} or " +
|
||||
f"{_SECRET_IS_NOT_PRIVATE})) or {_PROJECT_ADMIN}",
|
||||
check_str=(
|
||||
"True:%(enforce_new_defaults)s and "
|
||||
"(rule:secret_project_admin or "
|
||||
"(rule:secret_project_member and rule:secret_owner) or "
|
||||
"(rule:secret_project_member and rule:secret_is_not_private))"),
|
||||
scope_types=['project'],
|
||||
description='Add the payload to an existing metadata-only secret.',
|
||||
operations=[
|
||||
@ -66,16 +114,16 @@ rules = [
|
||||
'path': '/v1/secrets/{secret-id}',
|
||||
'method': 'PUT'
|
||||
}
|
||||
]
|
||||
],
|
||||
deprecated_rule=deprecated_secret_put
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name='secret:delete',
|
||||
check_str='rule:secret_project_admin or ' +
|
||||
'rule:secret_project_creator or ' +
|
||||
'(rule:secret_project_creator_role and ' +
|
||||
'not rule:secret_private_read) or ' +
|
||||
f"({_PROJECT_MEMBER} and ({_SECRET_CREATOR} or " +
|
||||
f"{_SECRET_IS_NOT_PRIVATE})) or {_PROJECT_ADMIN}",
|
||||
check_str=(
|
||||
"True:%(enforce_new_defaults)s and "
|
||||
"(rule:secret_project_admin or "
|
||||
"(rule:secret_project_member and rule:secret_owner) or "
|
||||
"(rule:secret_project_member and rule:secret_is_not_private))"),
|
||||
scope_types=['project'],
|
||||
description='Delete a secret by uuid.',
|
||||
operations=[
|
||||
@ -83,11 +131,12 @@ rules = [
|
||||
'path': '/v1/secrets/{secret-id}',
|
||||
'method': 'DELETE'
|
||||
}
|
||||
]
|
||||
],
|
||||
deprecated_rule=deprecated_secret_delete
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name='secrets:post',
|
||||
check_str=f'rule:admin_or_creator or {_MEMBER}',
|
||||
check_str=f'True:%(enforce_new_defaults)s and role:member',
|
||||
scope_types=['project'],
|
||||
description='Creates a Secret entity.',
|
||||
operations=[
|
||||
@ -95,11 +144,12 @@ rules = [
|
||||
'path': '/v1/secrets',
|
||||
'method': 'POST'
|
||||
}
|
||||
]
|
||||
],
|
||||
deprecated_rule=deprecated_secrets_post
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name='secrets:get',
|
||||
check_str=f'rule:all_but_audit or {_MEMBER}',
|
||||
check_str=f'True:%(enforce_new_defaults)s and role:member',
|
||||
scope_types=['project'],
|
||||
description='Lists a projects secrets.',
|
||||
operations=[
|
||||
@ -107,7 +157,8 @@ rules = [
|
||||
'path': '/v1/secrets',
|
||||
'method': 'GET'
|
||||
}
|
||||
]
|
||||
],
|
||||
deprecated_rule=deprecated_secrets_get
|
||||
)
|
||||
]
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user