⚠️ Please go to https://openunison.github.io/ to integrate your cluster with OpenUnison. This repo is no longer supported and will no longer get updated builds
⚠️
Orchestra is an automation portal for Kubernetes built on OpenUnison. Orchestra integrates a user's identity into Kubernetes enabling:
- SSO between the API server and your LDAP infrastructure
- SSO with the Kubernetes Dashboard
- Self service access to existing Namespaces
- Self service creation of new Namespaces
- Workflows for automating access approvals without getting system administrators involved
- Built in self service reporting
When a user accesses Kubernetes using Orchestra, they'll access both the self service portal and the dashboard through OpenUnison's reverse proxy (instead of directly via an ingress). OpenUnison will inject the user's identity into each request, allowing the dashboard to act on their behalf.
Orchestra stores all Kubernetes access information as a groups inside of a relational database, as opposed to a group in an external directory. OpenUnison will create the appropriate Roles and RoleBindings to allow for the access.
- Administration - Full cluster management access
- Administrators - All operations inside of a namespace
- Viewers - Can view contents of a namespace (except
Secret
s), but can not make changes
- System Approver - Able to approve access to roles specific to OpenUnison
- Auditor - Able to view audit reports, but not request projects or approve access
Prior to deploying OpenUnison you will need:
- Kubernetes 1.10 or higher
- The Nginx Ingress Controller deployed (https://kubernetes.github.io/ingress-nginx/deploy/)
- A MySQL or MariaDB Database
- Information from your OpenID Connect Identity Provider per "Create Environments File" in the next section. When registering OpenUnison with your identity provider, use the hostname and
/auth/oidc
as the redirect. For instance if OpenUnison will be running onk8sou.tremolo.lan.com
then the redirect_uri will behttps://k8sou.tremolo.lan/auth/oidc
- An SMTP server for sending notifications
- Deploy the dashboard to your cluster
- helm 3.0+
In order to integrate your identity provide make sure the following attributes are in the id_token
:
- sub
- given_name
- family_name
- name
These are then mapped into the user's object in OpenUnison for personalization.
helm repo add tremolo https://nexus.tremolo.io/repository/helm/
helm repo update
Create your namespace
kubectl create ns openunison
Deploy the operator
helm install openunison tremolo/openunison-operator --namespace openunison
Wait for the operator pod to be available
watch kubectl get pods -n openunison
Create a secret in the openunison
namespace:
apiVersion: v1
type: Opaque
metadata:
name: orchestra-secrets-source
namespace: openunison
data:
OIDC_CLIENT_SECRET: aW0gYSBzZWNyZXQ=
K8S_DB_SECRET: aW0gYSBzZWNyZXQ=
SMTP_PASSWORD: aW0gYSBzZWNyZXQ=
OU_JDBC_PASSWORD: aW0gYSBzZWNyZXQ=
unisonKeystorePassword: aW0gYSBzZWNyZXQ=
kind: Secret
Property | Description |
---|---|
OIDC_CLIENT_SECRET | The secret provided by your identity provider |
unisonKeystorePassword | The password for OpenUnison's keystore, should NOT contain an ampersand (& ) |
K8S_DB_SECRET | A random string of characters used to secure the SSO process with the dashboard. This should be long and random, with no ampersands (& ) |
OU_JDBC_PASSWORD | The password for accessing the database |
SMTP_PASSWORD | Password for accessing the SMTP server (may be blank) |
Copy values.yaml
(https://raw.githubusercontent.com/OpenUnison/helm-charts/master/openunison-k8s-oidc/values.yaml) and update as appropriate:
Property | Description |
---|---|
network.openunison_host | The host name for OpenUnison. This is what user's will put into their browser to login to Kubernetes |
network.dashboard_host | The host name for the dashboard. This is what users will put into the browser to access to the dashboard. NOTE: network.openunison_host and network.dashboard_host Both network.openunison_host and network.dashboard_host MUST point to OpenUnison |
network.api_server_host | The host name to use for the api server reverse proxy. This is what kubectl will interact with to access your cluster. NOTE: network.openunison_host and network.dashboard_host |
network.k8s_url | The URL for the Kubernetes API server |
network.session_inactivity_timeout_seconds | The number of seconds of inactivity before the session is terminated, also the length of the refresh token's session |
cert_template.ou | The OU attribute for the forward facing certificate |
cert_template.o | The O attribute for the forward facing certificate |
cert_template.l | The L attribute for the forward facing certificate |
cert_template.st | The ST attribute for the forward facing certificate |
cert_template.c | The C attribute for the forward facing certificate |
certs.use_k8s_cm | Tells the deployment system if you should use k8s' built in certificate manager. If your distribution doesn't support this (such as Canonical and Rancher), set this to false |
myvd_config_path | The path to the MyVD configuration file, unless being customized, use WEB-INF/myvd.conf |
dashboard.namespace | The namespace for the dashboard. For the 1.x dashboard this is kube-system , for the 2.x dashboard this is kubernetes-dashboard |
dashboard.cert_name | The name of the secret in the dashboard's namespace that stores the certificate for the dashboard |
dashboard.label | The label of the dashboard pod, this is used to delete the pod once new certificates are generated |
dashboard.service_name | The name of the service object for the dashboard |
k8s_cluster_name | The name of the cluster to use in the ./kube-config . Defaults to kubernetes |
image | The name of the image to use |
enable_impersonation | If true , OpenUnison will run in impersonation mode. Instead of OpenUnison being integrated with Kubernetes via OIDC, OpenUnison will be a reverse proxy and impersonate users. This is useful with cloud deployments where oidc is not an option |
monitoring.prometheus_service_account | The prometheus service account to authorize access to the /monitoring endpoint |
database.hibernate_dialect | Hibernate dialect for accessing the database. Unless customizing for a different database do not change |
database.quartz_dialect | Dialect used by the Quartz Scheduler. Unless customizing for a different database do not change |
database.driver | JDBC driver for accessing the database. Unless customizing for a different database do not change |
database.url | The URL for accessing the database |
database.user | The user for accessing the database |
database.validation | A query for validating database connections/ Unless customizing for a different database do not change |
smtp.host | Host for an email server to send notifications |
smtp.port | Port for an email server to send notifications |
smtp.user | Username for accessing the SMTP server (may be blank) |
smtp.from | The email address that messages from OpenUnison are addressed from |
smtp.tls | true or false, depending if SMTP should use start tls |
oidc.client_id | The client ID registered with your identity provider |
oidc.auth_url | Your identity provider's authorization url |
oidc.token_url | Your identity provider's token url |
oidc.domain | An email domain to limit access to |
oidc.user_in_idtoken | Set to true if the user's attributes (such as name and groups), is contained in the user's id_token . Set to false if a call to the identity provider's user info endpoint is required to load the full profile |
oidc.userinfo_url | If oidc.user_in_idtoken is false , the user_info endpoint for your identity provider |
oidc.claims.sub | If specified, the claim from the id_token to use for the sub attribute |
oidc.claims.email | If specified, the claim from the id_token to use for the mail attribute |
oidc.claims.givenName | If specified, the claim from the id_token to use for the givenName attribute |
oidc.claims.familyName | If specified, the claim from the id_token to use for the sn attribute |
oidc.claims.displayName | If specified, the claim from the id_token to use for the dipslayName attribute |
oidc.claims.groups | If specified, the claim from the id_token to use for the groups attribute |
oidc.scopes | The scopes to request, may change based on your identity provider |
Additionally, you can add your identity provider's TLS base64 encoded PEM certificate to your values under trusted_certs
for pem_b64
. This will allow OpenUnison to talk to your identity provider using TLS if it doesn't use a commercially signed certificate. NOTE - If you are using a public identity provider like Googl or Okta replace the trusted_certs
section with trusted_certs: []
.
Finally, run the helm chart:
helm install orchestra tremolo/openunison-k8s-oidc --namespace openunison -f /path/to/values.yaml
If you are using impersonation, you can skip this section. Run kubectl describe configmap api-server-config -n openunison
to get the SSO integration artifacts. The output will give you both the API server flags that need to be configured on your API servers. The certificate that needs to be trusted is in the ou-tls-certificate
secret in the openunison
namespace.
At this point you should be able to login to OpenUnison using the host specified in the OU_HOST
of your properties. Once you are logged in, logout. Users are created in the database "just-in-time", meaning that once you login the data representing your user is created inside of the database deployed for Orchestra.
The user you logged in as is currently unprivileged. In order for other users to login and begin requesting access to projects this first user must be enabled as an approver. Login to the MySQL database deployed for Orchestra and execute the following SQL:
insert into userGroups (userId,groupId) values (2,1);
This will add the administrator group to your user. Logout of Orchestra and log back in.
Once SSO is enabled in the next step, you'll need a cluster administrator to be able to perform cluster level operations:
- Login to Orchestra
- Click on "Request Access" in the title bar
- Click on "Kubernetes Administration"
- Click "Add To Cart" next to "Cluster Administrator"
- Next to "Check Out" in the title bar you'll see a red
1
, click on "Check Out" - For "Supply Reason", give a reason like "Initial user" and click "Submit Request"
- Since you are the only approver refresh OpenUnison, you will see a red
1
next to "Open Approvals". Click on "Open Approvals" - Click "Review" next to your email address
- Specify "Initial user" for the "Justification" and click "Approve"
- Click on "Confirm Approval"
At this point you will be provisioned to the k8s-cluster-administrators
group in the database that has a RoleBinding to the cluster-admin
Role. Logout of Orchestra and log back in. If you click on your email address in the upper left, you'll see that you have the Role k8s-cluster-administrators
.
OpenUnison can support more applications for SSO then just Kubernetes and the dashboard. You can add other clusters and applications that support OpenID Connect by adding some custom resources to your openunison
namespace.
The Trust
tells your OpenID Connect enabled application it can trust authentication requests from your OpenUnison. To start you'll need:
- Callback URL - This URL is where OpenUnison redirects the user after authenticating.
- Client Secret - Web applications, like GitLab, will need a secret that is shared between the two systems. Applications with CLI components, like ArgoCD, don't need a client secret.
- Client ID - This is how you identify your application to OpenUnison.
OpenUnison will provide the following claims for your application to consume:
Claim | Description |
---|---|
sub | Unique identifier as supplied from authentication |
name | Combination of first name and last name |
preferred_username | A username supplied from authentication |
The user's email address | |
groups | The list of groups provided by the authentication source |
Once you have everything you need to get started, create the Trust
object.
If you're application is using a client secret, a Secret
needs to be created to hold it. This can either be a new Secret
or it can be a new one. Which ever Secret
you add it to, keep a note of the name of the Secret
and the key in the data
section used to store it.
If your application doesn't have a client secret, skip this step.
Create a Trust
object in the openunison
namespace. Here's one for GitLab you can use as an example:
apiVersion: openunison.tremolo.io/v1
kind: Trust
metadata:
name: gitlab
namespace: openunison
spec:
accessTokenSkewMillis: 120000
accessTokenTimeToLive: 60000
authChainName: LoginService
clientId: gitlab
clientSecret:
keyName: gitlab
secretName: orchestra-secrets-source
codeLastMileKeyName: lastmile-oidc
codeTokenSkewMilis: 60000
publicEndpoint: false
redirectURI:
- https://gitlab.local.tremolo.dev/users/auth/openid_connect/callback
signedUserInfo: false
verifyRedirect: true
Here are the details for each option:
Option | Desription |
---|---|
accessTokenSkewMillis | Milliseconds milliseconds added to account for clock skew |
accessTokenTimeToLive | Time an access token should live in milliseconds |
authChainName | The authentication chain to use for login, do not change |
clientId | The client id shared by your application |
clientSecret.scretName | If using a client secret, the name of the Secret storing the client secret |
clientSecret.keyName | The key in the data section of the Secret storing the client secret |
codeLastMileKeyName | The name of the key used to encrypt the code token, do not change |
codeTokenSkewMilis | Milliseconds to add to code token lifetime to account for clock skew |
publicEndpoint | If true , a client secret is required. If false , no client secret is needed |
redirectURI | List of URLs that are authorized for callback. If a URL is provided by your application that isn't in this list SSO will fail |
signedUserInfo | if true , the userinfo endpoint will return a signed JSON Web Token. If false it will return plain JSON |
verifyRedirect | If true , the redirect URL provided by the client MUST be listed in the redirectURI section. Should ALLWAYS be true if not in a development environment |
Once the Trust
is added to the namespace, OpenUnison will pick it up automatically. You can test by trying to login to your application.
When you login to the Orchestra portal, there are badges for your tokens and for the dashboard. You can dynamically add a badge for your application too. Here's an example PortalUrl
object for ArgoCD:
apiVersion: openunison.tremolo.io/v1
kind: PortalUrl
metadata:
name: argocs
namespace: openunison
spec:
label: ArgoCD
org: B158BD40-0C1B-11E3-8FFD-0800200C9A66
url: https://ArgoCD.apps.192-168-2-140.nip.io
icon: iVBORw0KGgoAAAANSUhEUgAAANIAAADwCAYAAAB1/Tp/AAAfQ3pUWHRSYXcgcHJvZ...
azRules:
- constraint: o=Tremolo
scope: dn
Option | Descriptoin |
---|---|
label | The label shown on badge in the portal |
org | If using orgnaizations to organize badges, the uuid of the org. If not using organizations, leave as is |
url | The URL the badge should send the user to |
icon | A base64 encoded icon with a width of 210 pixels and a height of 240 pixels |
azRules | Who is authorized to see this badge? See https://portal.apps.tremolo.io/docs/tremolosecurity-docs/1.0.19/openunison/openunison-manual.html#_applications_applications for an explination of the authorization rules |
Once created, the badge will appear in the Orchestra portal! No need to restart the containers.
If you're adding multiple badges or clusters, you may find that the number of badges on your front page become difficult to manage. In that case you can enable orgnaizations in OpenUnison and organize your badges using an orgnaization tree.
Edit the orchestra
object in the openunison
namespace (kubectl edit openunison orchestra -n openunison
). Look for the non_secret_data
section and add the following:
- name: SHOW_PORTAL_ORGS
value: "true"
Once you save, OpenUnison will restart and when you login there will now be a tree that describes your organizations.
Add an Org
object to the openunison
namespace. Here's an example Org
:
apiVersion: openunison.tremolo.io/v1
kind: Org
metadata:
name: cluster2
namespace: openunison
spec:
description: "My second cluster"
uuid: 04901973-5f4c-46d9-9e22-55e88e168776
parent: B158BD40-0C1B-11E3-8FFD-0800200C9A66
showInPortal: true
showInRequestAccess: false
showInReports: false
azRules:
- scope: dn
constraint: o=Tremolo
Option | Description |
---|---|
description | What appears in the blue box describing the organization |
uuid | A unique ID, recommend using Type 4 UUIDs |
parent | The unique id of the parent. B158BD40-0C1B-11E3-8FFD-0800200C9A66 is the root organization |
showInPortal | Should be true |
showInRequestAccess | N/A |
showInReports | N/A |
azRules | Who is authorized to see this badge? See https://portal.apps.tremolo.io/docs/tremolosecurity-docs/1.0.19/openunison/openunison-manual.html#_applications_applications for an explination of the authorization rules |
Once added, the new organizations will be loaded dynamiclly by OpenUnison. Change the org
in your PortalUrl
object to match the uuid
of the Org
you want it to appear in.
If you want to integrate your own certificates see our wiki entry - https://github.com/TremoloSecurity/OpenUnison/wiki/troubleshooting#how-do-i-change-openunisons-certificates
This deployment comes with a /metrics
endpoint for monitoring. For details on how to integrate it into a Prometheus stack - https://github.com/TremoloSecurity/OpenUnison/wiki/troubleshooting#how-do-i-monitor-openunison-with-prometheus.
Please take a look at https://github.com/TremoloSecurity/OpenUnison/wiki/troubleshooting if you're running into issues. If there isn't an entry there that takes care of your issue, please open an issue on this repo.
To customize Orchestra - https://github.com/TremoloSecurity/OpenUnison/wiki/troubleshooting#customizing-orchestra
Users can now login to create namespaces, request access to cluster admin or request access to other clusters.
Now you can begin mapping OpenUnison's capabilities to your business and compliance needs. For instance you can add multi-factor authentication with TOTP or U2F, Create privileged workflows for onboarding, scheduled workflows that will deprovision users, etc.