diff --git a/chart/.helmignore b/chart/.helmignore new file mode 100644 index 000000000..691fa13d6 --- /dev/null +++ b/chart/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ \ No newline at end of file diff --git a/chart/Chart.yaml b/chart/Chart.yaml new file mode 100644 index 000000000..6b3dad7a6 --- /dev/null +++ b/chart/Chart.yaml @@ -0,0 +1,28 @@ +apiVersion: v2 +name: tsidp +description: A Helm chart for Tailscale tsidp (OIDC Identity Provider) +home: https://github.com/tailscale/tsidp + +keywords: + - "tailscale" + - "vpn" + - "ingress" + - "egress" + - "wireguard" + - "oidc" + - "tsidp" + +sources: + - https://github.com/tailscale/tsidp + +type: application + +maintainers: + - name: tailscale-maintainers + url: https://tailscale.com/ + +# version will be set to Tailscale repo tag (without 'v') at release time. +version: 0.1.0 + +# appVersion will be set to Tailscale repo tag at release time. +appVersion: "latest" diff --git a/chart/templates/_helpers.tpl b/chart/templates/_helpers.tpl new file mode 100644 index 000000000..ba189c35a --- /dev/null +++ b/chart/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "tsidp.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 "tsidp.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 "tsidp.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "tsidp.labels" -}} +helm.sh/chart: {{ include "tsidp.chart" . }} +{{ include "tsidp.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "tsidp.selectorLabels" -}} +app.kubernetes.io/name: {{ include "tsidp.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "tsidp.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "tsidp.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/chart/templates/authkey-secret.yaml b/chart/templates/authkey-secret.yaml new file mode 100644 index 000000000..2713d3d13 --- /dev/null +++ b/chart/templates/authkey-secret.yaml @@ -0,0 +1,9 @@ +{{- if .Values.auth_key -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "tsidp.fullname" . }}-authkey + namespace: {{ .Release.Namespace }} +stringData: + auth_key: {{ .Values.auth_key }} +{{- end -}} \ No newline at end of file diff --git a/chart/templates/deployment.yaml b/chart/templates/deployment.yaml new file mode 100644 index 000000000..3b7d8f719 --- /dev/null +++ b/chart/templates/deployment.yaml @@ -0,0 +1,94 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "tsidp.fullname" . }} + labels: + {{- include "tsidp.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + strategy: + type: Recreate + selector: + matchLabels: + {{- include "tsidp.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "tsidp.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "tsidp.serviceAccountName" . }} + {{- with .Values.podSecurityContext }} + securityContext: + {{- toYaml . | nindent 8 }} + {{- end }} + containers: + - name: {{ .Chart.Name }} + {{- with .Values.securityContext }} + securityContext: + {{- toYaml . | nindent 12 }} + {{- end }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + env: + - name: TAILSCALE_USE_WIP_CODE + value: "1" + - name: TS_STATE_DIR + value: "/data" + - name: TS_HOSTNAME + value: "{{ .Values.hostname }}" + - name: TSIDP_PORT + value: "{{ .Values.port }}" + {{- if .Values.enable_sts }} + - name: TSIDP_ENABLE_STS + value: "1" + {{- end }} + {{- if .Values.enable_funnel }} + - name: TSIDP_USE_FUNNEL + value: "1" + {{- end }} + {{- if .Values.auth_key }} + - name: TS_AUTHKEY + valueFrom: + secretKeyRef: + name: {{ include "tsidp.fullname" . }}-authkey + key: auth_key + {{- end }} + {{- with .Values.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + volumeMounts: + - name: tsidp-data + mountPath: /data + volumes: + {{- if .Values.persistentVolumeClaim.enabled }} + - name: tsidp-data + persistentVolumeClaim: + claimName: {{ include "tsidp.fullname" . }} + {{- else }} + - name: tsidp-data + emptyDir: {} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} \ No newline at end of file diff --git a/chart/templates/pvc.yaml b/chart/templates/pvc.yaml new file mode 100644 index 000000000..070ad25a7 --- /dev/null +++ b/chart/templates/pvc.yaml @@ -0,0 +1,25 @@ +{{- if .Values.persistentVolumeClaim.enabled -}} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: +{{- if .Values.persistentVolumeClaim.annotations }} + annotations: +{{ toYaml .Values.persistentVolumeClaim.annotations | indent 4 }} +{{- end }} + labels: + {{- include "tsidp.labels" . | nindent 4 }} + name: {{ include "tsidp.fullname" . }} +spec: + accessModes: +{{ toYaml .Values.persistentVolumeClaim.accessModes | indent 4 }} +{{- if .Values.persistentVolumeClaim.storageClass }} + {{- if (eq "-" .Values.persistentVolumeClaim.storageClass) }} + storageClassName: "" + {{- else }} + storageClassName: {{ .Values.persistentVolumeClaim.storageClass | quote }} + {{- end }} +{{- end }} + resources: + requests: + storage: {{ .Values.persistentVolumeClaim.size | quote }} +{{- end -}} \ No newline at end of file diff --git a/chart/templates/serviceaccount.yaml b/chart/templates/serviceaccount.yaml new file mode 100644 index 000000000..3fd00a440 --- /dev/null +++ b/chart/templates/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "tsidp.serviceAccountName" . }} + labels: + {{- include "tsidp.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automount }} +{{- end }} \ No newline at end of file diff --git a/chart/values.yaml b/chart/values.yaml new file mode 100644 index 000000000..ea9e0020f --- /dev/null +++ b/chart/values.yaml @@ -0,0 +1,83 @@ +# This will set the replicaset count more information can be found here: https://kubernetes.io/docs/concepts/workloads/controllers/replicaset/ +replicaCount: 1 + +# This sets the container image more information can be found here: https://kubernetes.io/docs/concepts/containers/images/ +image: + repository: ghcr.io/tailscale/tsidp + # This sets the pull policy for images. + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "" + +# This is for the secrets for pulling an image from a private repository more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ +imagePullSecrets: [] +# This is to override the chart name. +nameOverride: "" +fullnameOverride: "" + +# This section builds out the service account more information can be found here: https://kubernetes.io/docs/concepts/security/service-accounts/ +serviceAccount: + # Specifies whether a service account should be created + create: true + # Automatically mount a ServiceAccount's API credentials? + automount: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +# This is for setting Kubernetes Annotations to a Pod. +# For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ +podAnnotations: {} +# This is for setting Kubernetes Labels to a Pod. +# For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ +podLabels: {} + +podSecurityContext: + fsGroup: 1001 + +securityContext: + runAsUser: 1001 + runAsNonRoot: true + readOnlyRootFilesystem: false + +resources: {} + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +nodeSelector: {} + +tolerations: [] + +affinity: {} + +persistentVolumeClaim: + enabled: false + annotations: {} + accessModes: + - ReadWriteOnce + storageClass: "" + size: "500Mi" + +# Set logging level: debug, info, warn, error +logLevel: info + +# Optional: Tailscale auth key for automatic node registration +auth_key: "" + +# Hostname on tailnet. Will become .your-tailnet.ts.net +hostname: "idp" + +# Port to listen on +port: "443" + +# Enable OAuth token exchange using RFC 8693 +enable_sts: true + +# Use Tailscale Funnel to make tsidp available on the public internet so it works with SaaS products +enable_funnel: false