- Notifications
You must be signed in to change notification settings - Fork3
Kubernetes login portal for both kubectl and the dashboard using GitHub. Use organizations and teams in RBAC policies to control access to your cluster. Supports impersonation and OpenID Connect integration with your API server.
License
OpenUnison/openunison-k8s-login-github
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
⚠️ Please go tohttps://openunison.github.io/ to integrate your cluster with OpenUnison. This repo is no longer supported and will no longer get updated builds
⚠️
Short video of logging into Kubernetes and using kubectl using GitHub
Orchestra Login Portal provides a login portal for Kubernetes that allows you to authenticate with GitHub, use GitHub teams and organizations for RBAC authorizations and provides integration for bothkubectl
and the Kubernetes Dashboard (https://github.com/kubernetes/dashboard). The portal runs inside of Kubernetes, leveraging Kubernetes for scalability, secret management and deployment.
When a user accesses Kubernetes using Orchestra, they'll access both the login portal and the dashboard through OpenUnison (instead of directly via an ingress). OpenUnison will inject the user's identity into each request, allowing the dashboard to act on their behalf. The login portal has no external dependencies outside of GitHub and Kubernetes. All objects for session state are stored as CRDs.
This 7 minute video shows the entire deployment and user onboarding process
Prior to deploying Orchestra you will need:
- Kubernetes 1.10 or higher
- The Nginx Ingress Controller deployed (https://kubernetes.github.io/ingress-nginx/deploy/)
- Client id and secret from a GitHub OAuth2 Application
- Deploy the dashboard to your cluster
- helm 3.0+
When creating your GitHub OAuth2 application, the callback URL ishttps://host_name/auth/github
wherehost_name
is the host you want to use for your login portal.
The deployment is a four step process:
- Add Tremolo Security's Helm repo to your own
- Deploy the OpenUnison Operator
- Create a secret for your Active Directory password
- Deploy OpenUnison
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 theopenunison
namespace:
apiVersion: v1type: Opaquemetadata: name: orchestra-secrets-source namespace: openunisondata: GITHUB_SECRET_ID: aW0gYSBzZWNyZXQ= K8S_DB_SECRET: aW0gYSBzZWNyZXQ= unisonKeystorePassword: aW0gYSBzZWNyZXQ=kind: Secret
Property | Description |
---|---|
GITHUB_SECRET_ID | The secret from your GitHub OAuth2 application |
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 (& ) |
Copyvalues.yaml
(https://raw.githubusercontent.com/OpenUnison/helm-charts/master/openunison-k8s-login-github/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 andnetwork.dashboard_host Bothnetwork.openunison_host andnetwork.dashboard_host MUST point to OpenUnison |
network.api_server_host | The host name to use for the api server reverse proxy. This is whatkubectl will interact with to access your cluster.NOTE:network.openunison_host andnetwork.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 |
network.createIngressCertificate | If true (default), the operator will create a self signed Ingress certificate. Set to false if using an existing certificate or LetsEncrypt |
network.force_redirect_to_tls | Iftrue , all traffic that reaches OpenUnison over http will be redirected to https. Defaults totrue . Set tofalse when using an external TLS termination point, such as an istio sidecar proxy |
network.ingress_type | The type ofIngress object to create.nginx andistio is supported |
network.ingress_annotations | Annotations to add to theIngress object |
network.ingress_certificate | The certificate that theIngress object should reference |
network.istio.selectors | Labels that the istioGateway object will be applied to. Default isistio: ingressgateway |
cert_template.ou | TheOU attribute for the forward facing certificate |
cert_template.o | TheO attribute for the forward facing certificate |
cert_template.l | TheL attribute for the forward facing certificate |
cert_template.st | TheST attribute for the forward facing certificate |
cert_template.c | TheC 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, useWEB-INF/myvd.conf |
dashboard.namespace | The namespace for the dashboard. For the 1.x dashboard this iskube-system , for the 2.x dashboard this iskubernetes-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 tokubernetes |
image | The name of the image to use |
enable_impersonation | Iftrue , 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 |
github.client_id | The client id from your OAuth2 application configuration |
github.teams | A comma separated list of authorized teams and organizations. An organization is listed in the formatOrgName/ and a team in the formateOrgName/TeamName |
network_policies.enabled | Iftrue , creates a deny-all network policy and additional policies based on below configurations |
network_policies.ingress.enabled | iftrue , a policy will be created that allows access from theNamespace identified by thelabels |
network_policies.ingress.labels | Labels for theNamespace hosting theIngress |
network_policies.monitoring.enabled | iftrue , a policy will be created that allows access from theNamespace identified by thelabels to support monitoring |
network_policies.monitoring.labels | Labels for theNamespace hosting monitoring |
network_policies.apiserver.enabled | iftrue , a policy will be created that allows access from thekube-ns Namespace identified by thelabels |
network_policies.apiserver.labels | Labels for theNamespace hosting the api server |
services.enable_tokenrequest | Iftrue , the OpenUnisonDeployment will use theTokenRequest API instead of staticServiceAccount tokens. *** NOT AVAILABLE UNTIL OPENUNISON 1.0.21 *** |
services.token_request_audience | The audience expected by the API server *** NOT AVAILABLE UNTIL OPENUNISON 1.0.21 *** |
services.token_request_expiration_seconds | The number of seconds TokenRequest tokens should be valid for, minimum 600 seconds *** NOT AVAILABLE UNTIL OPENUNISON 1.0.21 *** |
services.node_selectors | annotations to use when choosing nodes to run OpenUnison, maps to theDeployment nodeSelector |
services.pullSecret | The name of theSecret that stores the pull secret for pulling the OpenUnison image |
services.resources.requests.memory | Memory requested by OpenUnison |
services.resources.requests.cpu | CPU requested by OpenUnison |
services.resources.limits.memory | Maximum memory allocated to OpenUnison |
services.resources.limits.cpu | Maximum CPU allocated to OpenUnison |
openunison.replicas | The number of OpenUnison replicas to run, defaults to 1 |
openunison.non_secret_data | Add additional non-secret configuration options, added to thenon_secret_data secrtion of theOpenUnison object |
openunison.secrets | Add additional keys from theorchestra-secrets-source Secret |
impersonation.use_jetstack | iftrue , the operator will deploy an instance of JetStack's OIDC Proxy (https://github.com/jetstack/kube-oidc-proxy). Default isfalse |
impersonation.jetstack_oidc_proxy_image | The name of the image to use |
impersonation.explicit_certificate_trust | Iftrue , oidc-proxy will explicitly trust thetls.crt key of theSecret named inimpersonation.ca_secret_name . Defaults totrue |
impersonation.ca_secret_name | Ifimpersonation.explicit_certificate_trust istrue , the name of the tlsSecret that stores the certificate for OpenUnison that the oidc proxy needs to trust. Defaults toou-tls-secret |
impersonation.resources.requests.memory | Memory requested by oidc proxy |
impersonation.resources.requests.cpu | CPU requested by oidc proxy |
impersonation.resources.limits.memory | Maximum memory allocated to oidc proxy |
impersonation.resources.limits.cpu | Maximum CPU allocated to oidc proxy |
Additionally, you can add your identity provider's TLS base64 encoded PEM certificate to your values undertrusted_certs
forpem_b64
. This will allow OpenUnison to talk to your identity provider using TLS if it doesn't use a commercially signed certificate. If you don't need a certificate to talk to your identity provider, replace thetrusted_certs
section withtrusted_certs: []
.
Finally, run the helm chart:
helm install orchestra tremolo/openunison-k8s-login-github --namespace openunison -f /path/to/values.yaml
Runkubectl 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 theou-tls-certificate
secret in theopenunison
namespace.
To login, open your browser and go to the host you specified forOU_HOST
in yourinput.props
. For instance ifOU_HOST
isk8sou.tremolo.lan
then navigate tohttps://k8sou.tremolo.lan. You'll be prompted for your github username and password. Once authenticated you'll be able login to the portal and generate your.kube/config
from the Tokens screen.
You can bypass manually launching a browser with theoulogin
kubectl plugin -https://github.com/TremoloSecurity/kubectl-login. This plugin will launch a browser for you, authenticate you then configure your kubectl configuration without any pre-configuration on your clients.
OpenUnison's built in reverse proxy doesn't support the SPDY protocol which kubectl, and the client-go sdk, uses forexec
,cp
, andport-forward
. If you require these options, and are using impersonation, you can now enable the JetStack OIDC proxy (https://github.com/jetstack/kube-oidc-proxy) instead of using OpenUnison's built in reverse proxy. To enable it, add theimpersonation
options from the helm chart configuration to your chart.NOTE when using the oidc-proxyservices.enable_tokenrequest
must befalse
. TheDeployment
created for the oidc proxy will inherrit theServiceAccount
from OpenUnison, as well as theservices.pullSecret
andservices.node_selectors
configuration in your helm chart. Resource requests and limits should be set specifically for the OIDC proxy under theimpersonation
section. The proxy is run as a non-privileged unix user as well. An example configuration when deploying with Let's Encrypt:
impersonation: use_jetstack: true jetstack_oidc_proxy_image: quay.io/jetstack/kube-oidc-proxy:v0.3.0 explicit_certificate_trust: false
On first login, if you haven't authorized access to any Kubernetes roles you won't be able to do anything. There are two approaches you can take:
Kubernetes will see your user's organizations and teams as groups. To authorize users based on these groups, list them in your RBAC policies as groups with organizations being in the formatOrgName/
and teams being the formatOrgName/TeamName
. To authorize members of teamTremnoloSecurity/Ownsers
to be cluster administrators, we create aClusterRoleBinding
:
kind: ClusterRoleBindingapiVersion: rbac.authorization.k8s.io/v1metadata: name: github-cluster-adminssubjects:- kind: Group name: TremoloSecurity/OwnersroleRef: kind: ClusterRole name: cluster-admin apiGroup: rbac.authorization.k8s.io
If you are not able to use teams or organizations in GitHub, you can directly add users to role bindings. Kubernetes requires that you identify openid connect users with the prefix of the url of the identity provider. So if yourOU_HOST
isk8sou.tremolo.lan
and your user's login ismmosley
your username to Kubernetes would behttps://k8sou.tremolo.lan/auth/idp/k8sIdp#mmosley
. To create a cluster role binding to give cluster-admin access to a specific user:
kind: ClusterRoleBindingapiVersion: rbac.authorization.k8s.io/v1metadata: name: github-cluster-adminssubjects:- kind: User name: https://k8sou.tremolo.lan/auth/idp/k8sIdp#mmosleyroleRef: kind: ClusterRole name: cluster-admin apiGroup: rbac.authorization.k8s.io
NOTE: There are multiple reasons this is a bad idea:
- Hard to audit - There is no easy way to say "what role bindings is
mmosley
a member of? - Difficult to remove access - Same reason as #1, you need to figure out every role binding a user is a member of to remove
- Easy to get wrong - If you mistype a user's login id Kubernetes won't tell you
If you can't use github orgnization and teams, take a look at the OpenUnison Identity Manager for Kubernetes -https://github.com/TremoloSecurity/openunison-qs-kubernetes/tree/activedirectory. This tool adds on to the login capabilities with the ability to manage access to the cluster and namespaces, along with providing a self service way for users to request new namespaces and manage access.
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 youropenunison
namespace.
TheTrust
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 theTrust
object.
If you're application is using a client secret, aSecret
needs to be created to hold it. This can either be a newSecret
or it can be a new one. Which everSecret
you add it to, keep a note of the name of theSecret
and the key in thedata
section used to store it.
If your application doesn't have a client secret, skip this step.
Create aTrust
object in theopenunison
namespace. Here's one for GitLab you can use as an example:
apiVersion: openunison.tremolo.io/v1kind: Trustmetadata: name: gitlab namespace: openunisonspec: 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 theSecret storing the client secret |
clientSecret.keyName | The key in thedata section of theSecret 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 | Iftrue , a client secret is required. Iffalse , 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 | iftrue , the userinfo endpoint will return a signed JSON Web Token. Iffalse it will return plain JSON |
verifyRedirect | Iftrue , the redirect URL provided by the clientMUST be listed in theredirectURI section. ShouldALLWAYS betrue if not in a development environment |
Once theTrust
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 examplePortalUrl
object for ArgoCD:
apiVersion: openunison.tremolo.io/v1kind: PortalUrlmetadata: name: argocs namespace: openunisonspec: 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? Seehttps://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 theorchestra
object in theopenunison
namespace (kubectl edit openunison orchestra -n openunison
). Look for thenon_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 anOrg
object to theopenunison
namespace. Here's an exampleOrg
:
apiVersion: openunison.tremolo.io/v1kind: Orgmetadata: name: cluster2 namespace: openunisonspec: 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 betrue |
showInRequestAccess | N/A |
showInReports | N/A |
azRules | Who is authorized to see this badge? Seehttps://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 theorg
in yourPortalUrl
object to match theuuid
of theOrg
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 athttps://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.
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.
To customize Orchestra -https://github.com/TremoloSecurity/OpenUnison/wiki/troubleshooting#customizing-orchestra
Using GitHub To Login to Kubernetes -https://www.tremolosecurity.com/post/using-github-to-access-kubernetes
About
Kubernetes login portal for both kubectl and the dashboard using GitHub. Use organizations and teams in RBAC policies to control access to your cluster. Supports impersonation and OpenID Connect integration with your API server.
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Releases
Packages0
Uh oh!
There was an error while loading.Please reload this page.
Contributors2
Uh oh!
There was an error while loading.Please reload this page.