Migrate from RBAC v1 to RBAC v2
This is a guide for the first phase of migration of existing Insights applications from RBACv1 to Kessel. In this initial phase, the goal is to start using Kessel for authorization enforcement while keeping parity with the current behaviors. Further âworkspacificationâ (i.e. making assets other than hosts workspace-aware) is out of scope for the initial phase and this guide.
Questions? Please raise them in #mgmt-fabric-insights-integrations
Identify the patterns
Section titled âIdentify the patternsâWe start the migration process by identifying the patterns used by our application. The patterns should be identified individually for each asset type managed by the application. Different asset types may fall under different patterns and hence an application may use a combination of patterns. For example, an application may use a combination of:
- permission protecting access to an org-wide setting
- permission protecting access to inventory group aware assets (e.g. host vulnerabilities)
The following patterns are supported:
For the initial migration of RBACv1 applications to Kessel, the following simplified decision tree can be used to identify the appropriate pattern:
- Is the asset related to a host (vulnerability, advisory, compliance report, etc.) and the service already workspace-aware? Use Native, workspace-level list
- Can the resource be conceptualized as an âassetâ (customer manages CRUD; we can imagine it as being placed in a Workspace)? â> Use Default workspace
- Is the resource âthe organizationâ as a whole (e.g. managing an organization-wide setting) and the operation is âasset-centricâ (we could imagine it being Workspace level in the future)? â> Use Root workspace
- Is the resource âthe organizationâ as a whole (e.g. managing an organization-wide setting) and the operation is not âasset-centricâ (would never belong at a Workspace level)? â> Use Organization-level
See the Pattern Summary section in KSL-016: Migrating host and organization level permissions for more information about the patterns.
The patterns identified for each application are tracked in Management Fabric Integrations
Model the permissions
Section titled âModel the permissionsâAfterwards, we need to convert permission definitions from the legacy RBACv1 format to permission definitions expressed using the ksl language.
These permission definitions are stored in .ksl
files in the rbac-config repository.
The @rbac.add_v1_based_permission()
extension simplifies the process of converting the legacy RBACv1 permission definitions to Kessel permissions by incorporating support for wildcard permissions.
The following rules apply to the @rbac.add_v1_based_permission()
extension:
- The
app
parameter should be the name of the application. - The
resource
parameter should be the singular name of the resource type. - The
verb
parameter should be the the verb. - The
v2_perm
parameter should be the name of the compound permission in Kessel. Note that the last segment of the v2 permission name will differ from the verb of the v1 permission. The following naming convention should be used:read
->view
write
->edit
Example of a permission definition using the @rbac.add_v1_based_permission()
extension:
version 0.1namespace config_manager
import rbac
@rbac.add_v1_based_permission(app:'config_manager', resource:'profile', verb:'read', v2_perm:'config_manager_profile_view');@rbac.add_v1_based_permission(app:'config_manager', resource:'profile', verb:'write', v2_perm:'config_manager_profile_edit');
Permissions that apply to host-centric assets
Section titled âPermissions that apply to host-centric assetsâCertain RBACv1 permissions apply to host-centric assets. These permissions are typically used to protect access to host-specific data, such as host vulnerabilities, advisories, etc.
In RBACv1, these permissions are evaluated in conjunction with the inventory:host:read
permission, which can be restricted to specific workspaces (inventory groups) using attribute filters.
In Kessel, this logic can be implemented natively by combining the compound permission with the inventory:host:read
permission.
The rbac.add_contingent_permission()
extension simplifies this process.
@rbac.add_v1_based_permission(app:'patch', resource:'system', verb:'read', v2_perm:'patch_system_view_assigned');@rbac.add_contingent_permission(first: 'inventory_host_view', second: 'patch_system_view_assigned', contingent: 'patch_system_view');
which is equivalent to (metalanguage used for illustration purposes):
patch_system_view_assigned = patch_system_read OR patch_system_all OR patch_system_all_read OR patch_system_all_all OR all_all_allpatch_system_view = inventory_host_view AND patch_system_view_assigned
Notice that the _assigned
suffix is used for the compound permission, which distinguishes it from the contingent permission that incorporates the inventory permission and which should be used for access checks.
Full example:
version 0.1namespace patch
import rbacimport hbi
@rbac.add_v1_based_permission(app:'patch', resource:'system', verb:'read', v2_perm:'patch_system_view_assigned');@rbac.add_contingent_permission(first: 'inventory_host_view', second: 'patch_system_view_assigned', contingent: 'patch_system_view');@hbi.expose_host_permission(v2_perm: 'patch_system_view', host_perm: 'patch_system_view');
@rbac.add_v1_based_permission(app:'patch', resource:'system', verb:'write', v2_perm:'patch_system_edit_assigned');@rbac.add_contingent_permission(first: 'inventory_host_view', second: 'patch_system_edit_assigned', contingent: 'patch_system_edit');@hbi.expose_host_permission(v2_perm: 'patch_system_edit', host_perm: 'patch_system_edit');
Checking in the permission definitions
Section titled âChecking in the permission definitionsâOnce the .ksl
file(s) are ready, they need to be added to the rbac-config repository by opening a PR.
Note that a separate config exists for each environment (stage, prod), allowing the change to be tested in stage before being released to prod.
There is no need to include the modified zed schema in the PR as an automated job will transpile the new/modified ksl files into a zed schema.
Role definitions
Section titled âRole definitionsâNote that the way these permissions are associated with a role remains the same, i.e. via role files.
In some cases a completely new permission may be defined in the process of onboarding to Kessel. In that case, consider defining this permission in RHEL persona-based roles (e.g. RHEL Viewer) in addition to application-specific roles (e.g. Advisor Viewer). See RHCLOUD-35891 for additional details.
Implement the changes in the application code
Section titled âImplement the changes in the application codeâThe implementation part typically consists of the following steps:
- Import the Kessel client library
- Implement the authorization check in the application code
- Add tests
- Add configuration options for the Kessel client
Importing the client library
Section titled âImporting the client libraryâKessel client libraries are available for these languages:
Implement the authorization check in the application code
Section titled âImplement the authorization check in the application codeâThe authorization check is typically implemented at the middleware layer. The actual implementation differs based on the selected pattern(s).
Root/Default workspace pattern
Section titled âRoot/Default workspace patternâThe implementation of root workspace pattern and default workspace pattern starts with a lookup of the default/root workspace id for the given organization.
The workspace ID can be obtained from the RBAC service via a REST call:
GET /v2/workspaces?type=rootGET /v2/workspaces?type=default
The default/root workspace for a given organization is guaranteed to never change and is therefore easily cacheable. However, in the future the need to look up the default/root workspace ID will be resolved transparently on the Kessel side. There is therefore no need to implement the caching code in the application code at this time.
With the workspace id resolved, the authorization check call can be made to Kessel. The actual method called depends on the nature of the operation.
Use CheckForUpdate for performing authorization check for
- any write operations
- highly-sensitive read operations (e.g. access to read credentials for connecting to a customerâs cluster)
In all other cases, use Check.
The parameters provided for the Check/CheckForUpdate request for the Root/Default workspace pattern should be structured as follows:
object := &kesselv2.ResourceReference{ ResourceType: "workspace", ResourceId: defaultOrRootWorkspaceID, Reporter: &kesselv2.ReporterReference{ Type: "rbac", },}
relation = // the permission to check for
subject := &kesselv2.SubjectReference{ Resource: &kesselv2.ResourceReference{ ResourceType: "principal", ResourceId: fmt.Sprintf("redhat/%s", principalID), Reporter: &kesselv2.ReporterReference{ Type: "rbac", }, },}
Default workspace pattern implementations and PoCs:
See Default workspace for additional information.
Native, workspace-level list
Section titled âNative, workspace-level listâThe Native, workspace-level list pattern is typically implemented by resolving the ids of all the workspaces for which the given principal possesses the given permission and then using these workspace ids to filter the assets in application database query.
The workspace ids are obtained using the StreamedListObjects method and its parameters should be defined as follows:
objectType := &kesselv2.RepresentationType{ ResourceType: "workspace", ReporterType: "rbac",},
relation = // the permission to check for
subject := &kesselv2.SubjectReference{ Resource: &kesselv2.ResourceReference{ ResourceType: "principal", ResourceId: fmt.Sprintf("redhat/%s", principalID), Reporter: &kesselv2.ReporterReference{ Type: "rbac", }, },}
Native, workspace-level list pattern implementations and PoCs:
See Native, workspace-level list for additional information.
Adding tests
Section titled âAdding testsâTBD
Example of a testcase for Kessel integration
Add configuration options for the Kessel client
Section titled âAdd configuration options for the Kessel clientâThe application should add the following configuration options for Kessel:
KESSEL_ENABLED
KESSEL_URL
KESSEL_AUTH_ENABLED
KESSEL_AUTH_CLIENT_ID
KESSEL_AUTH_CLIENT_SECRET
KESSEL_AUTH_OIDC_ISSUER
KESSEL_INSECURE
The ClowdApp template should also be updated accordingly to enable environment-specific configuration. See Config Managerâs configuration for an example.
Validate the changes in the ephemeral environment
Section titled âValidate the changes in the ephemeral environmentâThe following section describes how to deploy Kessel and related services in an ephemeral environment and use them to validate the changes made to an integrating application.
Deploying Kessel and related services
Section titled âDeploying Kessel and related servicesâinsights-service-deployer should be used to deploy Kessel and other related services in an ephemeral environment. Follow the instructions in the README to reserve a namespace and set up the environment variables and then run the following command to deploy Kessel and related services and seed them with sample data:
./deploy.sh deploy_with_hbi_demo
Enabling authentication
Section titled âEnabling authenticationâApplications using Kessel for access control need to authenticate with Kessel and RBAC in stage/prod environments. The following steps enable authentication with Kessel so that it can be validated in the ephemeral environment.
-
Navigate to Identity & Access Management in Stage to create a new service account and obtain the client ID and client secret. This is a service account that our application will use to authenticate with Kessel and RBAC.
-
Start a new shell and store the client ID and client secret as environment variables:
Terminal window CLIENT_ID=<client_id>CLIENT_SECRET=<client_secret> -
Next, we need to determine the subject (
sub
claim) for the service account:Terminal window SUB=$(curl -s https://sso.stage.redhat.com/auth/realms/redhat-external/protocol/openid-connect/token -d grant_type=client_credentials -d client_id=${CLIENT_ID} -d client_secret=${CLIENT_SECRET} | jq -r '.access_token' | awk -F. '{print $2}' | base64 --decode 2>/dev/null | jq -r '.sub') -
Now, weâll update the configuration of the RBAC service to enable authentication. With the RBAC service running in the ephemeral environment (see steps above), run the following command to grant unlimited access to the service account created in the first step:
Terminal window oc create secret generic system-users --dry-run=client -o yaml --from-literal="system-users.json={\"$SUB\": {\"admin\": true,\"is_service_account\": true,\"allow_any_org\": true}}" | kubectl apply -f - -
Next, reconfigure the RBAC service to validate access tokens using Stage SSO:
Terminal window oc get clowdapp rbac -o json | \jq '(.spec.deployments[] | select(.name=="service") | .podSpec.env[] | select(.name=="IT_BYPASS_TOKEN_VALIDATION") | .value) = "False" |(.spec.deployments[] | select(.name=="service") | .podSpec.env[] | select(.name=="IT_SERVICE_HOST") | .value) = "sso.stage.redhat.com"' | \oc apply -f - -
Furthermore, we also need to update the Kessel Inventory service configuration to enable authentication. Run
oc edit cm inventory-api-config
to edit the kessel-inventory configuration ConfigMap and in the editor update the authn section like this:authn:oidc:authn-server-url: https://sso.stage.redhat.com/auth/realms/redhat-externalclient-id: fooskip-client-id-check: trueinsecure-client: false -
Finally, restart the Kessel service:
Terminal window oc delete pod -l pod=kessel-inventory-api
Forwarding ports for local development
Section titled âForwarding ports for local developmentâWith Kessel running in the ephemeral environment, you can forward the ports to enable the application running locally to connect to RBAC and Kessel.
- Use
oc port-forward svc/rbac-service 8000:8000
to forward port 8000 to the RBAC service - Use
oc port-forward svc/kessel-inventory-api 9091:9000
to forward port 9091 to the Kessel Inventory service
With port forwarding running, you can now configure your application to use the local Kessel and RBAC ports and start it.
For example, for Config Manager, the command to configure and run the application looks like this:
go run main.go --log-level trace --kessel-enabled=true --kessel-url=localhost:9091 --kessel-auth-enabled=true --kessel-auth-client-id=${CLIENT_ID} --kessel-auth-client-secret=${CLIENT_SECRET} --kessel-auth-oidc-issuer=https://sso.stage.redhat.com/auth/realms/redhat-external --rbac-url=http://localhost:8000 http-api
Deploy the changes
Section titled âDeploy the changesâFollow Using Kessel in production to set up your service to use Kessel in stage and prod.