From 920ab2e239e75a071a4d46b442aeb29e4852781b Mon Sep 17 00:00:00 2001 From: Dario Blanco Date: Wed, 3 Apr 2019 19:55:44 +0200 Subject: [PATCH] Initial buzzfeed-sso chart - Oauth over your Kubernetes services (#8157) * Initial sso chart Signed-off-by: Dario Blanco * Rename to buzzfeed-sso Signed-off-by: Dario Blanco * Remove auth code secret from proxy Signed-off-by: Dario Blanco * Make tls templating more flexible Signed-off-by: Dario Blanco * Remove proxy code secret from the configuration Signed-off-by: Dario Blanco * Use buzzfeed-sso in README Signed-off-by: Dario Blanco * Use quote filter in proxy virtualHost variable Signed-off-by: Dario Blanco * Set CLUSTER in proxy as configurable and dev by default Signed-off-by: Dario Blanco * Quote all templated environment variables Signed-off-by: Dario Blanco * Set cookie secure to true by default Signed-off-by: Dario Blanco * Allow definition of a custom secret key This will skip secret creation via helm Signed-off-by: Dario Blanco * Make auth ingress tls secret name configurable Signed-off-by: Dario Blanco * Separate upstream configuration from ingress Signed-off-by: Dario Blanco * Update image to v1.1.0 Adds a new optional environment variable for the proxy that allows split dns deployments Signed-off-by: Dario Blanco * Move chart to incubator Signed-off-by: Dario Blanco * Fix auth configuration variables Signed-off-by: Dario Blanco * Use component label to distinguish between auth and proxy Signed-off-by: Dario Blanco * Make google admin email optional Signed-off-by: Dario Blanco * Fix proxy url internal environment variable Signed-off-by: Dario Blanco * Remove unnecessary virtual host Signed-off-by: Dario Blanco * Add only google service account credentials when admin email is given Signed-off-by: Dario Blanco * Make annotations configurable It also adds the secret file to the checksum Signed-off-by: Dario Blanco * Fix ingress hosts example Signed-off-by: Dario Blanco * Allow installation with default values showing errors Signed-off-by: Dario Blanco * Remove unusued virtualHost parameter Signed-off-by: Dario Blanco * Add OWNERS file Signed-off-by: Dario Blanco --- incubator/buzzfeed-sso/Chart.yaml | 16 ++ incubator/buzzfeed-sso/OWNERS | 4 + incubator/buzzfeed-sso/README.md | 182 ++++++++++++++++++ incubator/buzzfeed-sso/templates/NOTES.txt | 134 +++++++++++++ incubator/buzzfeed-sso/templates/_helpers.tpl | 32 +++ .../templates/auth-deployment.yaml | 150 +++++++++++++++ .../buzzfeed-sso/templates/auth-service.yaml | 22 +++ .../buzzfeed-sso/templates/configmap.yaml | 14 ++ .../buzzfeed-sso/templates/google-secret.yaml | 18 ++ incubator/buzzfeed-sso/templates/ingress.yaml | 48 +++++ .../templates/proxy-deployment.yaml | 112 +++++++++++ .../buzzfeed-sso/templates/proxy-service.yaml | 22 +++ incubator/buzzfeed-sso/templates/secret.yaml | 22 +++ incubator/buzzfeed-sso/values.yaml | 98 ++++++++++ 14 files changed, 874 insertions(+) create mode 100644 incubator/buzzfeed-sso/Chart.yaml create mode 100644 incubator/buzzfeed-sso/OWNERS create mode 100644 incubator/buzzfeed-sso/README.md create mode 100644 incubator/buzzfeed-sso/templates/NOTES.txt create mode 100644 incubator/buzzfeed-sso/templates/_helpers.tpl create mode 100644 incubator/buzzfeed-sso/templates/auth-deployment.yaml create mode 100644 incubator/buzzfeed-sso/templates/auth-service.yaml create mode 100644 incubator/buzzfeed-sso/templates/configmap.yaml create mode 100644 incubator/buzzfeed-sso/templates/google-secret.yaml create mode 100644 incubator/buzzfeed-sso/templates/ingress.yaml create mode 100644 incubator/buzzfeed-sso/templates/proxy-deployment.yaml create mode 100644 incubator/buzzfeed-sso/templates/proxy-service.yaml create mode 100644 incubator/buzzfeed-sso/templates/secret.yaml create mode 100644 incubator/buzzfeed-sso/values.yaml diff --git a/incubator/buzzfeed-sso/Chart.yaml b/incubator/buzzfeed-sso/Chart.yaml new file mode 100644 index 0000000000..fe2f3f9725 --- /dev/null +++ b/incubator/buzzfeed-sso/Chart.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +description: Single sign-on for your Kubernetes services using Google OAuth +name: buzzfeed-sso +version: 0.0.1 +appVersion: 1.1.0 +home: https://github.com/buzzfeed/sso +sources: + - https://hub.docker.com/r/buzzfeed/sso/ +keywords: + - sso + - octoboi + - ssoctopus +icon: https://user-images.githubusercontent.com/10510566/44476420-a64e5980-a605-11e8-8ad9-2820109deb75.png +maintainers: + - name: darioblanco + email: dblanco@minddoc.de diff --git a/incubator/buzzfeed-sso/OWNERS b/incubator/buzzfeed-sso/OWNERS new file mode 100644 index 0000000000..3ee6653c63 --- /dev/null +++ b/incubator/buzzfeed-sso/OWNERS @@ -0,0 +1,4 @@ +approvers: +- darioblanco +reviewers: +- darioblanco diff --git a/incubator/buzzfeed-sso/README.md b/incubator/buzzfeed-sso/README.md new file mode 100644 index 0000000000..420f0331d8 --- /dev/null +++ b/incubator/buzzfeed-sso/README.md @@ -0,0 +1,182 @@ +# Buzzfeed SSO + +Single sign-on for your Kubernetes services using Google OAuth (more providers are welcomed) + +[Blogpost](https://tech.buzzfeed.com/unleashing-the-a6a1a5da39d6?gi=e6db395406ae) +[Quickstart guide](https://github.com/buzzfeed/sso/blob/master/docs/quickstart.md) +[SSO in Kubernetes with Google Auth](https://medium.com/@while1eq1/single-sign-on-for-internal-apps-in-kubernetes-using-google-oauth-sso-2386a34bc433) +[Repo](https://github.com/buzzfeed/sso) + +This helm chart is heavily inspired in [Buzzfeed's example](https://github.com/buzzfeed/sso/tree/master/quickstart/kubernetes), and provides a way of protecting Kubernetes services that have no authentication layer globally from a single OAuth proxy. + +Many of the Kubernetes OAuth solutions require to run an extra container within the pod using [oauth2_proxy](https://github.com/bitly/oauth2_proxy), but the project seems to not be maintained anymore. The approach presented on this chart allows to have a global OAuth2 Proxy that can protect services even in different namespaces, thanks to [Kube DNS](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/). + +We use this chart in production at [MindDoc](https://minddoc.de) for protecting endpoints that have no built-in authentication (or that would require to run inner containers), like `Kibana`, `Prometheus`, etc... + +## Introduction + +This chart creates a SSO deployment on a [Kubernetes](http://kubernetes.io) +cluster using the [Helm](https://helm.sh) package manager. + +## Prerequisites + +- Kubernetes 1.8+ with Beta APIs enabled +- Kube DNS + +## Installing the Chart + +To install the chart with the release name `my-release`: + +```bash +$ helm install --name my-release stable/buzzfeed-sso +``` + +The command deploys SSO on the Kubernetes cluster using the default configuration. The [configuration](#configuration) section lists the parameters that can be configured during installation. + +This chart has required variables, see [Configuration](#configuration). + +## Uninstalling the Chart + +To uninstall/delete the `my-release` deployment: + +```bash +$ helm delete --purge my-release +``` +The command removes all the Kubernetes components associated with the chart and deletes the release. + +## Configuration + +The following table lists the configurable parameters of the SSO chart and their default/required values. + +Parameter | Description | Default +--- | --- | --- +`namespace` | namespace to use | `default` +`emailDomain` | the sso email domain for authentication | REQUIRED +`rootDomain` | the parent domain used for protecting your backends | REQUIRED +`auth.annotations` | extra annotations for auth pods | `{}` +`auth.domain` | the auth domain used for OAuth callbacks | REQUIRED +`auth.replicaCount` | desired number of auth pods | `1` +`auth.resources` | resource limits and requests for auth pods | `{ limits: { memory: "256Mi", cpu: "200m" }}` +`auth.nodeSelector` | node selector logic for auth pods | `{}` +`auth.tolerations` | resource tolerations for auth pods | `{}` +`auth.affinity` | node affinity for auth pods | `{}` +`auth.service.type` | type of auth service to create | `ClusterIP` +`auth.service.port` | port for the http auth service | `80` +`auth.secret` | secrets to be generated randomly with `openssl rand -base64 32 | head -c 32`. | REQUIRED if `auth.customSecret` is not set +`auth.tls` | tls configuration for central sso auth ingress. | `{ secretName: "sso-auth-tls-secret" }` +`auth.customSecret` | the secret key to reuse (avoids secret creation via helm) | REQUIRED if `auth.secret` is not set +`proxy.annotations` | extra annotations for proxy pods | `{}` +`proxy.providerUrlInternal` | url for split dns deployments | +`proxy.cluster` | the cluster name for SSO | `dev` +`proxy.replicaCount` | desired number of proxy pods | `1` +`proxy.resources` | resource limits and requests for proxy pods | `{ limits: { memory: "256Mi", cpu: "200m" }}` +`proxy.nodeSelector` | node selector logic for proxy pods | `{}` +`proxy.tolerations` | resource tolerations for proxy pods | `{}` +`proxy.affinity` | node affinity for proxy pods | `{}` +`proxy.service.type` | type of proxy service to create | `ClusterIP` +`proxy.service.port` | port for the http proxy service | `80` +`proxy.secret` | secrets to be generated randomly with `openssl rand -base64 32 | head -c 32 | base64`. | REQUIRED if `proxy.customSecret` is not set +`proxy.customSecret` | the secret key to reuse (avoids secret creation via helm) | REQUIRED if `proxy.secret` is not set +`provider.google` | the Oauth provider to use (only Google support for now) | REQUIRED +`provider.google.adminEmail` | the Google admin email | `undefined` +`provider.google.secret` | the Google OAuth secrets | REQUIRED if `provider.google.customSecret` is not set +`provider.google.customSecret` | the secret key to reuse instead of creating it via helm | REQUIRED if `provider.google.secret` is not set +`image.repository` | container image repository | `buzzfeed/sso` +`image.tag` | container image tag | `v1.0.0` +`image.pullPolicy` | container image pull policy | `IfNotPresent` +`ingress.annotations` | ingress load balancer annotations | `{}` +`ingress.hosts` | proxied hosts | `[]` +`ingress.tls` | tls certificates for the proxied hosts | `[]` +`upstreams` | configuration of services that use sso | `[]` + +Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`. For example, + +```bash +$ helm install --name my-release \ + --set key_1=value_1,key_2=value_2 \ + stable/buzzfeed-sso +``` + +Alternatively, a YAML file that specifies the values for the parameters can be provided while installing the chart. For example, + +```bash +$ helm install --name my-release -f values.yaml stable/buzzfeed-sso +``` + +> **Tip**: This will merge parameters with [values.yaml](values.yaml), which does not specify all the required values + +### Example + +**NEVER expose your `auth.secret`, `proxy.secret`, `provider.google.clientId`, `provider.google.clientSecret` and `provider.google.serviceAccount`.** Always keep them in a safe place and do not push them to any repository. As values are merged, you can always generate a different `.yaml` file. For instance: + +```yaml +# values.yaml +emailDomain: 'email.coolcompany.foo' + +rootDomain: 'coolcompany.foo' + +auth: + domain: sso-auth.coolcompany.foo + +proxy: + cluster: dev + +google: + adminEmail: iamtheadmin@email.coolcompany.foo +``` + +```yaml +# secrets.yaml +auth: + secret: + codeSecret: 'randomSecret1' + cookieSecret: 'randomSecret2' + +proxy: + secret: + clientId: 'randomSecret3' + clientSecret: 'randomSecret4' + cookieSecret: 'randomSecret6' + +google: + secret: + clientId: 'googleSecret!' + clientSecret: 'evenMoreSecret' + serviceAccount: '{ }' +``` + +Therefore, you could push your own `values.yaml` to a repo and keep `secrets.yaml` locally safe, and then install/update the chart: + +```bash +$ helm install --name my-release -f values.yaml -f secrets.yaml stable/buzzfeed-sso +``` + +Alternatively, you can specify your own secret key, if you have already created it in the cluster. The secret should follow the data format defined in `secret.yaml` (auth and proxy) and `google-secret.yaml` (google provider). + +```yaml +# values.yaml +emailDomain: 'email.coolcompany.foo' + +rootDomain: 'coolcompany.foo' + +auth: + domain: sso-auth.coolcompany.foo + customSecret: my-sso-auth-secret + +proxy: + cluster: dev + customSecret: my-sso-proxy-secret + +provider: + google: + adminEmail: iamtheadmin@email.coolcompany.foo + customSecret: my-sso-google-secret +``` + +## Updating the Chart + +You can update the chart values and trigger a pod reload. If the configmap changes, it will automatically retrieve the new values. + +```bash +$ helm upgrade -f values.yaml my-release stable/buzzfeed-sso +``` diff --git a/incubator/buzzfeed-sso/templates/NOTES.txt b/incubator/buzzfeed-sso/templates/NOTES.txt new file mode 100644 index 0000000000..1810b9cf7f --- /dev/null +++ b/incubator/buzzfeed-sso/templates/NOTES.txt @@ -0,0 +1,134 @@ +Please be patient: buzzfeed-sso might take a few minutes to install. + +{{- if eq .Values.emailDomain "" }} + +############################################################################### +#### ERROR: You did not provide an email domain. #### +############################################################################### + +This deployment will be incomplete until you configure a valid email domain. +The email domain is required for the auth and proxy deployments. + +{{- end }} + +{{- if eq .Values.rootDomain "" }} + +############################################################################### +#### ERROR: You did not provide a root domain. #### +############################################################################### + +This deployment will be incomplete until you configure a valid root domain. +The root domain is required for the auth deployment. + +{{- end }} + +{{- if eq .Values.auth.domain "" }} + +############################################################################### +#### ERROR: You did not provide proper auth domain. #### +############################################################################### + +This deployment will be incomplete until you configure a valid auth domain. +For instance, "sso-auth.mydomain.foo". + +{{- end }} + +{{- if not (or .Values.auth.secret .Values.auth.customSecret) }} + +############################################################################### +#### ERROR: You did not provide proper auth secrets. #### +############################################################################### + +This deployment will be incomplete until you configure proper auth secrets. +You can generate an auth secret by running + helm upgrade {{ .Release.Name }} \ + --reuse-values \ + --set auth.secret.codeSecret="$(openssl rand -base64 32 | head -c 32 | base64)" \ + --set auth.secret.cookieSecret="$(openssl rand -base64 32 | head -c 32 | base64)" \ + incubator/buzzfeed-sso + +Or you can provide a custom auth secret that is a reference to an already created +Kubernetes secret resource. + kubectl create secret generic buzzfeed-sso-auth-secret \ + --namespace={{ .Release.Namespace }} \ + --from-literal=auth-code-secret="auth-code-secret" + --from-literal=auth-cookie-secret="auth-cookie-secret" + + helm upgrade {{ .Release.Name }} \ + --reuse-values \ + --set auth.customSecret="buzzfeed-sso-auth-secret" \ + incubator/buzzfeed-sso + +{{- end }} + +{{- if not (or .Values.proxy.secret .Values.proxy.customSecret) }} + +############################################################################### +#### ERROR: You did not provide proper proxy secrets. #### +############################################################################### + +This deployment will be incomplete until you configure proper proxy secrets. +You can generate a proxy secret by running + helm upgrade {{ .Release.Name }} \ + --reuse-values \ + --set proxy.secret.clientId="$(openssl rand -base64 32 | head -c 32 | base64)" \ + --set proxy.secret.clientSecret="$(openssl rand -base64 32 | head -c 32 | base64)" \ + --set proxy.secret.cookieSecret="$(openssl rand -base64 32 | head -c 32 | base64)" \ + incubator/buzzfeed-sso + +Or you can provide a custom proxy secret that is a reference to an already created +Kubernetes secret resource. + kubectl create secret generic buzzfeed-sso-proxy-secret \ + --namespace={{ .Release.Namespace }} \ + --from-literal=proxy-client-id="proxy-client-id" + --from-literal=proxy-client-secret="proxy-client-secret" + --from-literal=proxy-cookie-secret="proxy-cookie-secret" + + helm upgrade {{ .Release.Name }} \ + --reuse-values \ + --set proxy.customSecret="buzzfeed-sso-proxy-secret" \ + incubator/buzzfeed-sso + +{{- end }} + +{{- if not (or .Values.provider.google.secret .Values.provider.google.customSecret) }} + +############################################################################### +#### ERROR: You did not provide a proper Google provider. #### +############################################################################### + +This deployment will be incomplete until you configure a valid provider. + +Currently, the only accepted provider is Google. You need to specify it with +a given secret or custom secret. + +You can define the secret with your Google's client id, client secret and +service account in JSON format. + helm upgrade {{ .Release.Name }} \ + --reuse-values \ + --set provider.google.secret.clientId="foo123123-fake123123.apps.googleusercontent.com" \ + --set provider.google.secret.clientSecret="googleOauthClientSecret" \ + --set provider.google.secret.serviceAccount="$(cat myserviceaccount.json)" \ + incubator/buzzfeed-sso + +Or you can provide a custom secret that is a reference to an already created +Kubernetes secret resource. + kubectl create secret generic buzzfeed-sso-google-secret \ + --namespace={{ .Release.Namespace }} \ + --from-literal=google-client-id="foo123123-fake123123.apps.googleusercontent.com" + --from-literal=google-client-secret="googleOauthClientSecret" + --from-literal=service-account="$(cat myserviceaccount.json)" + + helm upgrade {{ .Release.Name }} \ + --reuse-values \ + --set provider.google.customSecret="buzzfeed-sso-google-secret" \ + incubator/buzzfeed-sso + +{{- end }} + +{{- if .Values.ingress.hosts }} +Visit the external application URLs to use your application: +{{- range .Values.ingress.hosts }} + https://{{ .domain }}{{ .path }} +{{- end }} +{{- end }} diff --git a/incubator/buzzfeed-sso/templates/_helpers.tpl b/incubator/buzzfeed-sso/templates/_helpers.tpl new file mode 100644 index 0000000000..7e2fb0a663 --- /dev/null +++ b/incubator/buzzfeed-sso/templates/_helpers.tpl @@ -0,0 +1,32 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "buzzfeed-sso.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "buzzfeed-sso.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "buzzfeed-sso.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} diff --git a/incubator/buzzfeed-sso/templates/auth-deployment.yaml b/incubator/buzzfeed-sso/templates/auth-deployment.yaml new file mode 100644 index 0000000000..748879288c --- /dev/null +++ b/incubator/buzzfeed-sso/templates/auth-deployment.yaml @@ -0,0 +1,150 @@ +{{- if and (or .Values.auth.customSecret .Values.auth.secret) (or .Values.provider.google.customSecret .Values.provider.google.secret) (ne .Values.auth.domain "") -}} +{{- $fullName := include "buzzfeed-sso.fullname" . -}} +{{- $googleSecret := .Values.provider.google.customSecret | default (printf "%s-google" ($fullName)) -}} +{{- $authSecret := .Values.auth.customSecret | default ($fullName) -}} +{{- $name := include "buzzfeed-sso.name" . -}} +{{- $authDomain := .Values.auth.domain -}} +apiVersion: apps/v1beta1 +kind: Deployment +metadata: + name: {{ $fullName }}-auth + labels: + app: {{ $name }} + chart: {{ template "buzzfeed-sso.chart" . }} + component: {{ $name }}-auth + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +spec: + replicas: {{ .Values.auth.replicaCount }} + selector: + matchLabels: + app: {{ $name }} + component: {{ $name }}-auth + release: {{ .Release.Name }} + template: + metadata: + annotations: + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} + {{- with .Values.auth.annotations }} +{{ toYaml . | indent 8 }} + {{- end }} + labels: + app: {{ $name }} + component: {{ $name }}-auth + release: {{ .Release.Name }} + spec: + {{- if .Values.provider.google }} + volumes: + - name: google-service-account + secret: + secretName: {{ $googleSecret }} + items: + - key: service-account + path: sso-serviceaccount.json + {{- end }} + containers: + - name: {{ .Chart.Name }}-auth + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: ["/bin/sso-auth"] + ports: + - name: http + containerPort: 4180 + protocol: TCP + env: + - name: SSO_EMAIL_DOMAIN + value: {{ .Values.emailDomain | quote }} + - name: HOST + value: {{ $authDomain }} + - name: REDIRECT_URL + value: https://{{ $authDomain }} + - name: PROXY_ROOT_DOMAIN + value: {{ .Values.rootDomain | quote }} + - name: PROXY_CLIENT_ID + valueFrom: + secretKeyRef: + name: {{ $authSecret }} + key: proxy-client-id + - name: PROXY_CLIENT_SECRET + valueFrom: + secretKeyRef: + name: {{ $authSecret }} + key: proxy-client-secret + - name: AUTH_CODE_SECRET + valueFrom: + secretKeyRef: + name: {{ $authSecret }} + key: auth-code-secret + - name: COOKIE_SECRET + valueFrom: + secretKeyRef: + name: {{ $authSecret }} + key: auth-cookie-secret + # # OLD_COOKIE_SECRET is the same as COOKIE_SECRET, not sure why its even needed at this point + - name: OLD_COOKIE_SECRET + valueFrom: + secretKeyRef: + name: {{ $authSecret }} + key: auth-cookie-secret + # STATSD_HOST and STATSD_PORT must be defined or the app wont launch, they dont need to be a real host / port + - name: STATSD_HOST + value: localhost + - name: STATSD_PORT + value: "11111" + - name: COOKIE_SECURE + value: "true" + - name: CLUSTER + value: dev + # Provider variables + {{- with .Values.provider.google }} + {{- if .adminEmail }} + - name: GOOGLE_ADMIN_EMAIL + value: {{ .adminEmail | quote }} + - name: GOOGLE_SERVICE_ACCOUNT_JSON + value: /creds/sso-serviceaccount.json + {{- end }} + - name: CLIENT_ID + valueFrom: + secretKeyRef: + name: {{ $googleSecret }} + key: google-client-id + - name: CLIENT_SECRET + valueFrom: + secretKeyRef: + name: {{ $googleSecret }} + key: google-client-secret + {{- end }} + readinessProbe: + httpGet: + path: /ping + port: 4180 + scheme: HTTP + livenessProbe: + httpGet: + path: /ping + port: 4180 + scheme: HTTP + initialDelaySeconds: 10 + timeoutSeconds: 1 + {{- if .Values.provider.google.adminEmail }} + volumeMounts: + - name: google-service-account + mountPath: /creds + readOnly: true + {{- end }} + resources: +{{ toYaml .Values.auth.resources | indent 12 }} + {{- with .Values.auth.nodeSelector }} + nodeSelector: +{{ toYaml . | indent 8 }} + {{- end }} + {{- with .Values.auth.affinity }} + affinity: +{{ toYaml . | indent 8 }} + {{- end }} + {{- with .Values.auth.tolerations }} + tolerations: +{{ toYaml . | indent 8 }} + {{- end }} +{{- end }} diff --git a/incubator/buzzfeed-sso/templates/auth-service.yaml b/incubator/buzzfeed-sso/templates/auth-service.yaml new file mode 100644 index 0000000000..7b24477376 --- /dev/null +++ b/incubator/buzzfeed-sso/templates/auth-service.yaml @@ -0,0 +1,22 @@ +{{- $name := include "buzzfeed-sso.name" . -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "buzzfeed-sso.fullname" . }}-auth + labels: + app: {{ $name }} + chart: {{ template "buzzfeed-sso.chart" . }} + component: {{ $name }}-auth + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +spec: + type: {{ .Values.auth.service.type }} + ports: + - name: http + port: {{ .Values.auth.service.port }} + targetPort: 4180 + protocol: TCP + selector: + app: {{ $name }} + component: {{ $name }}-auth + release: {{ .Release.Name }} diff --git a/incubator/buzzfeed-sso/templates/configmap.yaml b/incubator/buzzfeed-sso/templates/configmap.yaml new file mode 100644 index 0000000000..12f9a4f6e0 --- /dev/null +++ b/incubator/buzzfeed-sso/templates/configmap.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ template "buzzfeed-sso.fullname" . }} + labels: + app: {{ template "buzzfeed-sso.name" . }} + chart: {{ template "buzzfeed-sso.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +data: +{{- with .Values.upstreams }} + upstream_configs.yml: |- +{{ toYaml . | indent 4 }} +{{- end }} diff --git a/incubator/buzzfeed-sso/templates/google-secret.yaml b/incubator/buzzfeed-sso/templates/google-secret.yaml new file mode 100644 index 0000000000..9a3f46ea8b --- /dev/null +++ b/incubator/buzzfeed-sso/templates/google-secret.yaml @@ -0,0 +1,18 @@ +{{- if .Values.provider.google.secret }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "buzzfeed-sso.fullname" . }}-google + labels: + app: {{ template "buzzfeed-sso.name" . }} + chart: {{ template "buzzfeed-sso.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +type: Opaque +data: +{{- with .Values.provider.google.secret }} + google-client-id: {{ .clientId | b64enc }} + google-client-secret: {{ .clientSecret | b64enc }} + service-account: {{ .serviceAccount | b64enc }} +{{- end }} +{{- end }} diff --git a/incubator/buzzfeed-sso/templates/ingress.yaml b/incubator/buzzfeed-sso/templates/ingress.yaml new file mode 100644 index 0000000000..5f7c3f3b7c --- /dev/null +++ b/incubator/buzzfeed-sso/templates/ingress.yaml @@ -0,0 +1,48 @@ +{{- if ne .Values.auth.domain "" -}} +{{- $fullName := include "buzzfeed-sso.fullname" . -}} +{{- $authDomain := .Values.auth.domain -}} +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + app: {{ template "buzzfeed-sso.name" . }} + chart: {{ template "buzzfeed-sso.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +{{- with .Values.ingress.annotations }} + annotations: +{{ toYaml . | indent 4 }} +{{- end }} +spec: + tls: + - hosts: + - {{ $authDomain }} + secretName: {{ .Values.auth.tls.secretName -}} + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + rules: + # Upstreams that need SSO authentication + {{- range .Values.ingress.hosts }} + - host: {{ .domain }} + http: + paths: + - path: {{ .path }} + backend: + serviceName: {{ $fullName }}-proxy + servicePort: http + {{- end }} + # Global SSO used in the callback for login + - host: {{ $authDomain }} + http: + paths: + - path: / + backend: + serviceName: {{ $fullName }}-auth + servicePort: http +{{- end }} diff --git a/incubator/buzzfeed-sso/templates/proxy-deployment.yaml b/incubator/buzzfeed-sso/templates/proxy-deployment.yaml new file mode 100644 index 0000000000..e636a8cf5c --- /dev/null +++ b/incubator/buzzfeed-sso/templates/proxy-deployment.yaml @@ -0,0 +1,112 @@ +{{- if or .Values.proxy.customSecret .Values.proxy.secret -}} +{{- $fullName := include "buzzfeed-sso.fullname" . -}} +{{- $proxySecret := .Values.proxy.customSecret | default ($fullName) -}} +{{- $name := include "buzzfeed-sso.name" . -}} +apiVersion: apps/v1beta1 +kind: Deployment +metadata: + name: {{ $fullName }}-proxy + labels: + app: {{ $name }} + chart: {{ template "buzzfeed-sso.chart" . }} + component: {{ $name }}-proxy + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +spec: + replicas: {{ .Values.proxy.replicaCount }} + selector: + matchLabels: + app: {{ $name }} + component: {{ $name }}-proxy + release: {{ .Release.Name }} + template: + metadata: + annotations: + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }} + {{- with .Values.proxy.annotations }} +{{ toYaml . | indent 8 }} + {{- end }} + labels: + app: {{ $name }} + component: {{ $name }}-proxy + release: {{ .Release.Name }} + spec: + volumes: + - name: {{ $fullName }} + configMap: + name: {{ $fullName }} + containers: + - name: {{ .Chart.Name }}-proxy + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + command: ["/bin/sso-proxy"] + ports: + - name: http + containerPort: 8080 + protocol: TCP + env: + - name: CLIENT_ID + valueFrom: + secretKeyRef: + name: {{ $proxySecret }} + key: proxy-client-id + - name: CLIENT_SECRET + valueFrom: + secretKeyRef: + name: {{ $proxySecret }} + key: proxy-client-secret + - name: COOKIE_SECRET + valueFrom: + secretKeyRef: + name: {{ $proxySecret }} + key: proxy-cookie-secret + - name: EMAIL_DOMAIN + value: {{ .Values.emailDomain | quote }} + - name: UPSTREAM_CONFIGS + value: /sso/upstream_configs.yml + - name: PROVIDER_URL + value: https://{{ .Values.auth.domain }} + # STATSD_HOST and STATSD_PORT must be defined or the app wont launch, they dont need to be a real host / port, but they do need to be defined. + - name: STATSD_HOST + value: localhost + - name: STATSD_PORT + value: "11111" + - name: COOKIE_SECURE + value: "true" + - name: CLUSTER + value: {{ .Values.proxy.cluster | quote }} + {{- if .Values.proxy.providerUrlInternal }} + - name: PROVIDER_URL_INTERNAL + value: {{ .Values.proxy.providerUrlInternal | quote }} + {{- end }} + readinessProbe: + httpGet: + path: /ping + port: 4180 + scheme: HTTP + livenessProbe: + httpGet: + path: /ping + port: 4180 + scheme: HTTP + initialDelaySeconds: 10 + timeoutSeconds: 1 + volumeMounts: + - name: {{ $fullName }} + mountPath: /sso + resources: +{{ toYaml .Values.proxy.resources | indent 12 }} + {{- with .Values.proxy.nodeSelector }} + nodeSelector: +{{ toYaml . | indent 8 }} + {{- end }} + {{- with .Values.proxy.affinity }} + affinity: +{{ toYaml . | indent 8 }} + {{- end }} + {{- with .Values.proxy.tolerations }} + tolerations: +{{ toYaml . | indent 8 }} + {{- end }} +{{- end }} diff --git a/incubator/buzzfeed-sso/templates/proxy-service.yaml b/incubator/buzzfeed-sso/templates/proxy-service.yaml new file mode 100644 index 0000000000..2bf38711f0 --- /dev/null +++ b/incubator/buzzfeed-sso/templates/proxy-service.yaml @@ -0,0 +1,22 @@ +{{- $name := include "buzzfeed-sso.name" . -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ template "buzzfeed-sso.fullname" . }}-proxy + labels: + app: {{ $name }} + chart: {{ template "buzzfeed-sso.chart" . }} + component: {{ $name }}-proxy + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +spec: + type: {{ .Values.proxy.service.type }} + ports: + - name: http + port: {{ .Values.proxy.service.port }} + targetPort: 4180 + protocol: TCP + selector: + app: {{ $name }} + component: {{ $name }}-proxy + release: {{ .Release.Name }} diff --git a/incubator/buzzfeed-sso/templates/secret.yaml b/incubator/buzzfeed-sso/templates/secret.yaml new file mode 100644 index 0000000000..6c27d77240 --- /dev/null +++ b/incubator/buzzfeed-sso/templates/secret.yaml @@ -0,0 +1,22 @@ +{{- if or .Values.auth.secret .Values.proxy.secret }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ template "buzzfeed-sso.fullname" . }} + labels: + app: {{ template "buzzfeed-sso.name" . }} + chart: {{ template "buzzfeed-sso.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +type: Opaque +data: +{{- with .Values.proxy.secret }} + proxy-client-id: {{ .clientId | b64enc }} + proxy-client-secret: {{ .clientSecret | b64enc }} + proxy-cookie-secret: {{ .cookieSecret | b64enc }} +{{- end }} +{{- with .Values.auth.secret }} + auth-code-secret: {{ .codeSecret | b64enc }} + auth-cookie-secret: {{ .cookieSecret | b64enc }} +{{- end }} +{{- end }} diff --git a/incubator/buzzfeed-sso/values.yaml b/incubator/buzzfeed-sso/values.yaml new file mode 100644 index 0000000000..dfaf3c1ca5 --- /dev/null +++ b/incubator/buzzfeed-sso/values.yaml @@ -0,0 +1,98 @@ +# Default values for buzzfeed-sso. + +emailDomain: "" # Required. e.g "email.mydomain.foo" +rootDomain: "" # Required. e.g "mydomain.foo" + +auth: + annotations: {} + domain: "" # Required. e.g "sso-auth.mydomain.foo" + replicaCount: 1 + resources: + limits: + memory: "256Mi" + cpu: "200m" + nodeSelector: {} + tolerations: [] + affinity: {} + service: + type: ClusterIP + port: 80 + # Generate these secrets with the command: + # 'openssl rand -base64 32 | head -c 32 | base64' + secret: {} # Required (if customSecret is not set) + # codeSecret: '' + # cookieSecret: '' + # # Or if you do not want to create the secret via helm + # customSecret: my-sso-auth-secret + tls: + secretName: sso-auth-tls-secret + +proxy: + annotations: {} + # providerUrlInternal: https://sso-auth.mydomain.com + cluster: dev + replicaCount: 1 + resources: + limits: + memory: "256Mi" + cpu: "200m" + nodeSelector: {} + tolerations: [] + affinity: {} + service: + type: ClusterIP + port: 80 + # Generate these secrets with the command: + # 'openssl rand -base64 32 | head -c 32 | base64' + secret: {} # Required (if customSecret is not set) + # clientId: '' + # clientSecret: '' + # cookieSecret: '' + # # Or if you do not want to create the secret via helm + # customSecret: my-sso-proxy-secret + +provider: + google: {} # Required. + # google: + # adminEmail: me@mydomain.foo + # secret: + # clientId: foo123123-fake123123.apps.googleusercontent.com + # clientSecret: googleOauthClientSecret + # serviceAccount: 'service account content in JSON format' + # # Or if you do not want to create the secret via helm + # google: + # adminEmail: me@mydomain.foo + # customSecret: my-sso-google-secret + +image: + repository: buzzfeed/sso + tag: v1.1.0 + pullPolicy: IfNotPresent + +ingress: + annotations: {} + # kubernetes.io/ingress.class: nginx + # certmanager.k8s.io/cluster-issuer: my-letsencrypt-issuer + # ingress.kubernetes.io/ssl-redirect: "true" + hosts: [] + # - domain: mybackend.mydomain.foo + # path: / + tls: [] + # - secretName: mybackend-mydomain-tls + # hosts: + # - mybackend.mydomain.foo + +upstreams: [] +# See https://github.com/buzzfeed/sso/blob/f437f237ac977201f15868601c9bc0e9dff11f40/docs/sso_config.md#proxy-config +# - service: mybackend +# default: +# from: mybackend.mydomain.foo +# to: http://mybackend.mynamespace.svc.cluster.local:9091 +# options: +# allowed_groups: +# - sso-test-group-1@example.com +# - sso-test-group-2@example.com +# skip_auth_regex: +# - ^\/github-webhook\/$ +# header_overrides: +# X-Frame-Options: DENY