The multicluster-keycloak-operator is focused on providing a managed Single Sign-On (SSO) solution for a fleet of OpenShift clusters managed by Open Cluster Management.
The operator makes use of Keycloak to create a Github-backed identity provider.
- For each
AuthorizationDomain
, aKeycloakRealm
will be created to provide an identity provider for the hub and managed clusters. - For every ManagedCluster under management, a
KeycloakClient
will be created with a generatedclientId
andclientSecret
. - From there, a
ManifestWork
will be created that injects theclientSecret
into aSecret
on theManagedCluster
and updates theOAuth
cluster
configuration to respect theKeycloakRealm
identity provider hosted on the Hub cluster.
Currently, a work-in-progress.
- Deploy RHACM from the Operator Catalog on OpenShift Container Platform 4.7+.
- Create an empty
MulticlusterHub
to deploy the product API and web console.
If you already have RHACM deployed, you can configure the RH Single Sign-On Operator with the following Policy:
apiVersion: v1
kind: Namespace
metadata:
name: open-cluster-management-policies
---
apiVersion: apps.open-cluster-management.io/v1
kind: Channel
metadata:
name: example-policies-latest
namespace: open-cluster-management-policies
spec:
type: GitHub
pathname: https://github.com/mdelder/open-cluster-management-examples.git
---
apiVersion: apps.open-cluster-management.io/v1
kind: Subscription
metadata:
annotations:
apps.open-cluster-management.io/github-path: policies
name: example-policies
namespace: open-cluster-management-policies
labels:
app: example-policies
spec:
channel: open-cluster-management-policies/example-policies-latest
placement:
local: true
packageOverrides:
- packageName: kustomization
packageOverrides:
- value:
generatorOptions:
disableNameSuffixHash: true
resources:
- dev-clusters-placementrule.yaml
- production-clusters-placementrule.yaml
- policy-group-demo-admins.yaml
- policy-rhsso-operator.yaml
Otherwise you can manually deploy the RHSSO operator. If you are running on OpenShift 4.7, you must patch additional Roles/Bindings in place to work around a current bug on RHSSO 7.4.6.
- Install the Red Hat Single Sign-On Operator from the OpenShift Operator Catalog.
apiVersion: operators.coreos.com/v1alpha1
kind: Subscription
metadata:
labels:
operators.coreos.com/rhsso-operator.keycloak: ""
name: rhsso-operator
namespace: keycloak
spec:
channel: alpha
installPlanApproval: Automatic
name: rhsso-operator
source: redhat-operators
sourceNamespace: openshift-marketplace
startingCSV: rhsso-operator.7.4.4
- Configure a running instance of Keycloak, the service that is managed by the Red Hat SSO Operator.
apiVersion: keycloak.org/v1alpha1
kind: Keycloak
metadata:
name: keycloak-sso
labels:
app: sso
namespace: keycloak
spec:
externalAccess:
enabled: true
instances: 1
- Patch the permissions to allow the RHSSO operator the ability to update the
Route
on OpenShift Container Platform 4.7:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: rhsso-operator-route-editor
namespace: keycloak
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: route-editor
subjects:
- kind: ServiceAccount
name: rhsso-operator
namespace: keycloak
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: route-editor
rules:
- apiGroups:
- route.openshift.io
resources:
- routes/custom-host
verbs:
- create
- update
- list
- get
- patch
export KUBECONFIG=./path/to/your/kubeconfig
make install
make deploy
At this point, you can configure the AuthorizationDomain
object that will reference your GitHub OAuthApp and inject configuration to each ManagedCluster to use the Red Hat Single Sign-On (SSO) operator that you configured above.
- Register an OAuth App on GitHub (see the GitHub docs).
- Use any value for the
homepageURL
. - Use
https://keycloak-keycloak.apps.<clusterName>.<baseDomain>/auth/realms/sso-ad/broker/github/endpoint
for theOAuthCallbackURL
. The Route will be served by the instance of Keycloak deployed in step 3. The segment "sso-ad" is MUST be used as the name of theAuthorizationDomain
created below. So if you create anAuthorizationDomain
of a different name, then replace "sso-ad" in this URL with the name that you used for theAuthorizationDomain
. - Retrieve the
clientID
andclientSecret
.
- Use any value for the
- Create a Secret in the Namespace
keycloak
to store the GitHub OAuthclientID
andclientSecret
.
apiVersion: v1
kind: Secret
stringData:
clientId: ...
clientSecret: ...
metadata:
name: github-oauth-credentials
namespace: keycloak
type: Opaque
- Create an
AuthorizationDomain
. The Multicluster Keycloak Operator (in this project) will reconcile theAuthorizationDomain
CR and create the necessaryKeycloak
resources to allow anyManagedCluster
to use the runningKeycloak
service on the Hub as an OAuth2 Identity Provider. In addition, everyManagedCluster
will pick up a newManifestWork
that configures its localOAuth
cluster
CR.
apiVersion: keycloak.open-cluster-management.io/v1alpha1
kind: AuthorizationDomain
metadata:
name: sso-ad
namespace: keycloak
spec:
identityProviders:
- type: github
secretRef: github-oauth-credentials
# These fields are optional and are now discovered if not provided
# issuerURL: "https://keycloak-keycloak.apps.<clusterName>.<baseDomain>/auth/realms/sso-ad"
# issuerCertificate:
# configMapRef: ca-config-map
NOTE: This project remains a work in progress and the various objects that are created may need to be removed manually if you delete the AuthorizationDomain
. Be sure to have access to the TLS certificates or an alternative way to login to your cluster in case a problem occurs.
The following two policies will allow you to precreate a Group backed by email addresses that will be retrieve from GitHub to create the relevant Identity
and User
object after a user accesses a ManagedCluster
console.
apiVersion: policy.open-cluster-management.io/v1
kind: Policy
metadata:
name: policy-group-demo-admins
namespace: open-cluster-management-policies
annotations:
policy.open-cluster-management.io/standards: NIST-CSF
policy.open-cluster-management.io/categories: PR.AC Identity Management Authentication and Access Control
policy.open-cluster-management.io/controls: PR.AC-4 Access Control
spec:
remediationAction: enforce
disabled: false
policy-templates:
- objectDefinition:
apiVersion: policy.open-cluster-management.io/v1
kind: ConfigurationPolicy
metadata:
name: demo-admins-group-config-policy
spec:
severity: high
object-templates:
- complianceType: mustonlyhave
objectDefinition:
apiVersion: user.openshift.io/v1
kind: Group
metadata:
name: demo-admins
users:
- UPDATE THIS LIST WITH EMAIL ADDRESSES OF YOUR GITHUB USERS
- objectDefinition:
apiVersion: policy.open-cluster-management.io/v1
kind: ConfigurationPolicy
metadata:
name: demo-admins-clusterrolebinding-config-policy
spec:
severity: high
object-templates:
- complianceType: mustonlyhave # role definition should exact match
objectDefinition:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: demo-admins
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: demo-admins
---
apiVersion: policy.open-cluster-management.io/v1
kind: PlacementBinding
metadata:
name: binding-policy-group-demo-admins
namespace: open-cluster-management-policies
placementRef:
name: placement-policy-group-demo-admins
kind: PlacementRule
apiGroup: apps.open-cluster-management.io
subjects:
- name: policy-group-demo-admins
kind: Policy
apiGroup: policy.open-cluster-management.io
---
apiVersion: apps.open-cluster-management.io/v1
kind: PlacementRule
metadata:
name: placement-policy-group-demo-admins
namespace: open-cluster-management-policies
spec:
clusterConditions:
- status: "True"
type: ManagedClusterConditionAvailable
clusterSelector:
matchExpressions: []
The following policy will remove the default kubeadmin
credential from all ManagedClusters
.
apiVersion: policy.open-cluster-management.io/v1
kind: Policy
metadata:
name: no-kubeadmin-config-policy
namespace: open-cluster-management-policies
annotations:
policy.open-cluster-management.io/standards: NIST-CSF
policy.open-cluster-management.io/categories: PR.AC Identity Management Authentication and Access Control
policy.open-cluster-management.io/controls: PR.AC-4 Access Control
spec:
remediationAction: enforce
disabled: false
policy-templates:
- objectDefinition:
apiVersion: policy.open-cluster-management.io/v1
kind: ConfigurationPolicy
metadata:
name: no-kubeadmin-config-policy
spec:
severity: high
object-templates:
- complianceType: mustnothave
objectDefinition:
apiVersion: v1
kind: Secret
metadata:
name: kubeadmin
namespace: kube-system
type: Opaque
---
apiVersion: policy.open-cluster-management.io/v1
kind: PlacementBinding
metadata:
name: binding-no-kubeadmin-config-policy
namespace: open-cluster-management-policies
placementRef:
name: placement-no-kubeadmin-config-policy
kind: PlacementRule
apiGroup: apps.open-cluster-management.io
subjects:
- name: no-kubeadmin-config-policy
kind: Policy
apiGroup: policy.open-cluster-management.io
---
apiVersion: apps.open-cluster-management.io/v1
kind: PlacementRule
metadata:
name: placement-no-kubeadmin-config-policy
namespace: open-cluster-management-policies
spec:
clusterConditions:
- status: "True"
type: ManagedClusterConditionAvailable
clusterSelector:
matchExpressions: []
The initial project was created following the Operator SDK Tutorial for Golang.
operator-sdk init operator-sdk init --domain=open-cluster-management.io
operator-sdk create api --group=keycloak --version=v1alpha1 --kind=AuthorizationDomain
go mod vendor
make generate
make manifests
Contributions are welcome and encouraged via Pull Requests.
make generate
make manifests
make install
make run