diff --git a/Standards/scs-03XX-v1-standard-roles.md b/Standards/scs-03XX-v1-standard-roles.md new file mode 100644 index 000000000..2a112a871 --- /dev/null +++ b/Standards/scs-03XX-v1-standard-roles.md @@ -0,0 +1,211 @@ +--- +title: SCS Standard Roles +type: Standard +status: Draft +track: IAM +--- + +## Introduction + +SCS aims to provide a standardized role model for Role-Based Access Control (RBAC) across all supported OpenStack API services. +The goal of this standard is to define IaaS roles for SCS clouds with sensible and consistent permission sets. +It is closely guided by the OpenStack defaults to achieve compatibility and interoperability. + +:::note + +The standard described below is only applicable to OpenStack releases 2024.2 or later. + +::: + +## Terminology + +The following special terms are used throughout this standard document: + +| Term | Meaning | +|---|---| +| API | Application Programming Interface, often referring to the REST API interfaces provided by OpenStack and related services | +| CSP | Cloud Service Provider, provider managing the OpenStack infrastructure | +| IaaS | Infrastructure-as-a-Service | +| IAM | Identity and Access Management | +| RBAC | Role-Based Access Control[^1] established by OpenStack Keystone | + +[^1]: [OpenStack Documentation: Role-Based Access Control Overview](https://static.opendev.org/docs/patrole/latest/rbac-overview.html) + +## Motivation + +The permission settings of OpenStack RBAC roles are preconfigured in the OpenStack API implementations and can optionally be adjusted in service-specific deployment configuration files (usually the respective "`policy.yaml`") individually. +In contrast to many of OpenStack's IAM and IaaS resources however, these settings cannot be changed via its API at runtime, only via configuration files. +Changing these settings can also have a wide range of implications and requires careful testing and maintenance. +For these reasons it is important to have a secure and sensible default configuration in SCS clouds that is both intuitive and flexible enough to cover all necessary use cases of permission models desired by CSPs and customers. + +## Design Considerations + +One key aspect of the design considerations for this standard is to be as close to the native (upstream) OpenStack role model and role definitions as possible to not introduce unnecessary complexity or divergence from OpenStack. +Meanwhile the standardized roles and permission sets should cover all scenarios and use cases that SCS deems necessary. + +Due to the high level of modularity and the large amount of available services for OpenStack clouds, this standard cannot address all possible manifestations of OpenStack clouds. +This standard will therefore only cover IaaS APIs and services that are classified as either mandatory or supported by the SCS project. + +### Core Roles + +The following overview will list the roles which are considered core roles by this standard and explain their purposes as well as target scopes. +Roles marked as "internal" are roles only meant to be assigned to technical user accounts intended for internal use by OpenStack services. + +Core Roles: + +| Role | Primary Target(s) | Purpose | +|---|---|---| +| reader | customer | read-only access to resources in the scope of authentication (e.g. project) | +| member | customer | read and write access to resources in the scope of authentication (e.g. project) | +| manager | customer | identity self-service capability within a domain, to assign/revoke roles between users, groups and projects | +| admin | CSP | cloud-level global administrative access to all resources (cross-domain, cross-project) | +| service | internal | internal technical user role for service communication | + +### Scope Enforcement Compatibility + +The API policy library used by OpenStack (oslo.policy) introduced two new [configuration options](https://docs.openstack.org/oslo.policy/latest/configuration/#oslo-policy) during the ongoing RBAC rework of OpenStack[^2]: + +- `enforce_scope` +- `enforce_new_defaults` + +Using those new defaults and scope-enforcing options [will currently break](https://governance.openstack.org/tc/goals/selected/consistent-and-secure-rbac.html#the-issues-we-are-facing-with-scope-concept) orchestration tooling such as **OpenStack Heat** and Tacker. +This must be considered when making decisions in this standard. +Careful evaluation of benefits as well as implications of adopting these changes is necessary. +The new options are not adopted equally across all OpenStack services yet in context of the ongoing rework. + +Some service-specific role sets currently found in OpenStack services can only be eliminated and streamlined with the general roles (reader, member etc.) when those new options are enabled. + +[^2]: [OpenStack Technical Committee Governance Documents: Consistent and Secure Default RBAC](https://governance.openstack.org/tc/goals/selected/consistent-and-secure-rbac.html) + +#### Core Role Set + +Independently from any service-specific roles, the set of core roles is fundamentally affected by the scope enforcement options as well. + +The proper distinction between reader, member and manager roles is only fully implemented in all services when the `enforce_scope` and `enforce_new_defaults` oslo.policy options are used. +Otherwise the OpenStack APIs will oftentimes fall back to their earlier policy implementations which do not fully differentiate between reader, member and manager. + +This results in more elevated permissions for users possessing the reader role than its role description suggests. +If this standard cannot mandate or expect the use of the aforementioned oslo.policy options due to their current compatibility issues as stated above, the usefulness of the reader role would be limited and unexpected behavior would be introduced when using it. +In such case, the standard should omit the reader role in its current state. + +#### Barbican Role Set + +The Key Manager component Barbican [established a set of dedicated roles](https://docs.openstack.org/barbican/2024.1/admin/access_control.html#default-policy): + +- key-manager:service-admin +- creator +- observer +- audit + +This set of roles is Barbican-specific and not used by any other API. +It became deprecated during the RBAC rework of OpenStack[^2]. + +Due to its deprecation it is possible to enable Barbican's use of the already established reader, member and admin roles instead. +This however requires the olso.policy options `enforce_scope` and `enforce_new_default` to be enabled. + +#### Octavia Role Set + +The Load-Balancer-as-a-Service (LBaaS) component Octavia comes with a set of specific roles in its default API policy configuration: + +- load-balancer_observer +- load-balancer_global_observer +- load-balancer_member +- load-balancer_quota_admin +- load-balancer_admin + +This set of roles is Octavia-specific and not used by any other API. +However, Octavia also [officially supports alternative policy configurations](https://docs.openstack.org/octavia/2024.1/configuration/policy.html#openstack-default-roles-policy-override-file) that use the already established reader, member and admin roles instead. + +Using the alternative configurations would streamline Octavia's policies with the rest of the services and reduce complexity as well as ambiguity in the global role model of this standard. + +However, both of the alternative policy files that omit the Octavia-specific roles currently state "The [oslo_policy] `enforce_scope` and `enforce_new_defaults` must be `True`.". +This would require the new defaults and scope-enforcing options. + +### Inclusion of the "manager" role + +The current RBAC rework in upstream OpenStack[^2] describes a "project-manager" persona utilizing a new "manager" role on project scope to perform more privileged operations than "member" (see "Phase 3" of the document). +This role is intended to be used across various OpenStack services. +As of the OpenStack release 2024.1 this role is not implemented in any of the core services yet, only in Ironic with `enforce_new_defaults` enabled[^3]. + +On the other hand, the SCS project is making use of this role to implement a Domain Manager persona (see the [SCS Domain Manager standard under "Related Documents"](#scs-domain-manager-standard)). +This persona will be available as a native upstream feature in Keystone starting with the 2024.2 release of OpenStack. + +As a result, the "manager" role has no effect outside of the Keystone Identity API until phase 3 of the RBAC rework is implemented upstream but can be used for identity-related functionality in Keystone. + +[^3]: [Implementation of the "manager" role in Ironic for the 2024.1 release](https://github.com/openstack/ironic/blob/stable/2024.1/ironic/common/policy.py#L76-L82) + +## Standard + +### Roles + +This standard establishes the following default roles in SCS clouds. +The roles mentioned below MUST be present in the Identity API at all times. + +- reader +- member +- manager +- admin +- service + +### API configuration + +All API services MUST be configured to use the Secure RBAC role model by enabling `enforce_new_defaults` and `enforce_scope` of the oslo.policy library. + +If custom policy rules are added to an API by a CSP the `policy_file` option of the oslo.policy library SHOULD be explicitly set to the name of the policy override file and not rely on the corresponding default path. + +Example configuration entries: + +```ini +[oslo_policy] +enforce_new_defaults = True +enforce_scope = True +policy_file = policy.yaml +``` + +#### API Policies + +The following applies to all APIs that use RBAC policies: + +- Custom policy rules MUST NOT extend the privileges of the core roles mentioned in this standard beyond their default permissions. +- If roles with custom permission sets are required, new roles and corresponding policies MAY be added as long as their names differ from the core roles and they do not impact the core roles. + +The following applies only to the Octavia v2 LBaaS API: + +- The scoping-compatible variant of [OpenStack Default Roles Policy Override File](https://docs.openstack.org/octavia/2024.1/configuration/policy.html#openstack-default-roles-policy-override-file) MUST be used as a base to align the LBaaS API with the standardized reader, member and admin role set. + As of the 2024.1 release of Octavia, this template is provided as [keystone_default_roles_scoped-policy.yaml](https://github.com/openstack/octavia/blob/stable/2024.1/etc/policy/keystone_default_roles_scoped-policy.yaml). + +## Related Documents + +### SCS Mandatory and Supported IaaS Services + +**Description:** SCS standard that lists mandatory and supported OpenStack APIs for SCS clouds. +This list is decisive for the standard on roles as all applicable services need to be taken into consideration. + +**Link:** TBD + +### SCS Domain Manager standard + +**Description:** SCS standard that describes the Domain Manager role introduced by SCS and its configuration. + +**Link:** [SCS Standards: Domain Manager configuration for Keystone](https://docs.scs.community/standards/scs-0302-v1-domain-manager-role) + +### SCS Key Manager standard role adjustment + +**Description:** Implementation notes of the [SCS Key Manager standard](https://github.com/SovereignCloudStack/standards/blob/main/Standards/scs-0116-v1-key-manager-standard.md) that describe a policy adjustment to redirect the "creator" role to the "member" role for Key Manager setups not yet using the `enforce_new_defaults` option in order to enable generic project members to manage secrets and access encryption functionalities. + +**Link:** [SCS Standards: Key Manager Standard Implementation Notes](https://github.com/SovereignCloudStack/standards/blob/main/Standards/scs-0116-w1-key-manager-implementation-testing.md#policies) + +### Consistent and Secure Default RBAC + +**Description:** Upstream rework of the default role definitions and hierarchy across all OpenStack services. +Explains the reasoning for the `enforce_scope` and `enforce_new_defaults` options and the transition process. + +**Link:** [OpenStack Technical Committee Governance Documents: Consistent and Secure Default RBAC](https://governance.openstack.org/tc/goals/selected/consistent-and-secure-rbac.html) + +## Conformance Tests + +Conformance tests verify that the roles mandated by the standard exist and the Key Manager API adjustments are implemented. + +There is a test suite in [`standard-roles-check.py`](https://github.com/SovereignCloudStack/standards/blob/main/Tests/iam/iaas-roles/standard-roles-check.py). +The test suite connects to the OpenStack API, queries the role list and verifies the behavior of the Key Manager API. +Please consult the associated [README.md](https://github.com/SovereignCloudStack/standards/blob/main/Tests/iam/iaas-roles/README.md) for detailed setup and testing instructions. diff --git a/Tests/iam/iaas-roles/README.md b/Tests/iam/iaas-roles/README.md new file mode 100644 index 000000000..94570e569 --- /dev/null +++ b/Tests/iam/iaas-roles/README.md @@ -0,0 +1,92 @@ +# Standard Roles Test Suite + +## Test Environment Setup + +### API User Account + +The test suite strictly requires an OpenStack user that possesses the following access rights: + +1. the "`member`" role in the project referenced as authentication target +2. access permissions to the "`list_roles`" in the Identity API + +The second requirement (access to "`list_roles`") is usually not granted to users with the "`member`" role in default configurations and only works for user accounts also possessing the "`manager`" role in the domain. +So the test would require an user account possessing both the "`member`" role in a project as well as the "`manager`" role in the domain. + +Note that the "`manager`" role only works this way starting with OpenStack Keystone 2024.2. +If an older Keystone release is used, see the alternative instructions below. + +#### Alternative using a dedicated role + +One alternative way to address this is for older Keystone releases is to create a dedicated role in the cloud environment which only has access to the role list endpoint and assign it to the user account intended for testing (in addition to the "`member`" role). + +To achieve this, first the role has to be created and assigned: + +```sh +openstack role create scs-conformance-tester +openstack role add --user ... --project ... member +openstack role add --user ... --project ... scs-conformance-tester +``` + +Finally, the Keystone API policy definition for the role list endpoint has to be extended to allow this role. +The following is an example entry for `/etc/keystone/policy.yaml` of the Keystone service: + +```yaml +"identity:list_roles": "... or role:scs-conformance-tester" +``` + +("`...`" is a placeholder and must be replaced by the current content of the `"identity:list_roles"` rule!) + +The credentials of the resulting user must be specified in the "`clouds.yaml`" accordingly (see below). + +### Test Execution Environment + +To execute the test suite a valid cloud configuration for the OpenStack SDK in the shape of "`clouds.yaml`" is mandatory[^1]. +**The file is expected to be located in the current working directory where the test script is executed unless configured otherwise.** + +[^1]: [OpenStack Documentation: Configuring OpenStack SDK Applications](https://docs.openstack.org/openstacksdk/latest/user/config/configuration.html) + +The test execution environment can be located on any system outside of the cloud infrastructure that has OpenStack API access. +Make sure that the API access is configured properly in "`clouds.yaml`". + +It is recommended to use a Python virtual environment[^2]. +Next, install the OpenStack SDK required by the test suite: + +```bash +pip3 install openstacksdk +``` + +Within this environment execute the test suite. + +[^2]: [Python 3 Documentation: Virtual Environments and Packages](https://docs.python.org/3/tutorial/venv.html) + +## Test Execution + +The test suite is executed as follows: + +```bash +python3 standard-roles-check.py --os-cloud mycloud +``` + +As an alternative to "`--os-cloud`", the "`OS_CLOUD`" environment variable may be specified instead. +The parameter is used to look up the correct cloud configuration in "`clouds.yaml`". +For the example command above, this file should contain a `clouds.mycloud` section like this: + +```yaml +--- +clouds: + mycloud: + auth: + auth_url: ... + ... + ... +``` + +For any further options consult the output of "`python3 standard-roles-check.py --help`". + +### Script Behavior & Test Results + +The script will print all executed tests and their results to `stdout`. + +If all tests pass, the script will return with an exit code of `0`. + +If any test fails, the script will abort, print the failed test to `stdout` and return with a non-zero exit code. diff --git a/Tests/iam/iaas-roles/standard-roles-check.py b/Tests/iam/iaas-roles/standard-roles-check.py new file mode 100644 index 000000000..e0c98b337 --- /dev/null +++ b/Tests/iam/iaas-roles/standard-roles-check.py @@ -0,0 +1,92 @@ +import argparse +import getpass +import os +import typing + +import openstack + +CORE_ROLES = { + "reader", + "member", + "admin", + "service" +} + + +def connect(cloud_name: str, password: typing.Optional[str] = None + ) -> openstack.connection.Connection: + """Create a connection to an OpenStack cloud + + :param string cloud_name: + The name of the configuration to load from clouds.yaml. + + :param string password: + Optional password override for the connection. + + :returns: openstack.connnection.Connection + """ + + if password: + return openstack.connect( + cloud=cloud_name, + password=password + ) + else: + return openstack.connect( + cloud=cloud_name, + ) + + +def check_list_of_roles(conn: openstack.connection.Connection, + expected_roles: typing.Iterable[str]) -> None: + """ + Retrieves the list of roles from the Identity API and verifies that + it contains all role names specified in the given expected_roles list. + """ + actual_roles = [role.name for role in conn.identity.roles()] + for role in expected_roles: + assert role in actual_roles, ( + f"Expected role '{role}' was not found." + ) + print(f"Role '{role}' is present: PASS") + + +def main(): + parser = argparse.ArgumentParser( + description="SCS Standard Roles Conformance Checker") + parser.add_argument( + "--os-cloud", type=str, + help="Name of the cloud from clouds.yaml, alternative " + "to the OS_CLOUD environment variable" + ) + parser.add_argument( + "--ask", + help="Ask for password interactively instead of reading it from the " + "clouds.yaml", + action="store_true" + ) + parser.add_argument( + "--debug", action="store_true", + help="Enable OpenStack SDK debug logging" + ) + args = parser.parse_args() + openstack.enable_logging(debug=args.debug) + + # parse cloud name for lookup in clouds.yaml + cloud = os.environ.get("OS_CLOUD", None) + if args.os_cloud: + cloud = args.os_cloud + assert cloud, ( + "You need to have the OS_CLOUD environment variable set to your " + "cloud name or pass it via --os-cloud" + ) + conn = connect( + cloud, + password=getpass.getpass("Enter password: ") if args.ask else None + ) + + check_list_of_roles(conn, CORE_ROLES) + + +if __name__ == "__main__": + main()