diff --git a/helm/1password-scim-bridge/Chart.lock b/helm/1password-scim-bridge/Chart.lock new file mode 100644 index 0000000..fcb1b8d --- /dev/null +++ b/helm/1password-scim-bridge/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: op-scim-bridge + repository: "" + version: 2.11.7 +digest: sha256:e45626ac423c2472e3cc0f862197f688bc24e0b96a796f746d9243f96ae7e37a +generated: "2024-12-19T18:11:22.744711729-05:00" diff --git a/helm/1password-scim-bridge/Chart.yaml b/helm/1password-scim-bridge/Chart.yaml index e3b9890..c651902 100644 --- a/helm/1password-scim-bridge/Chart.yaml +++ b/helm/1password-scim-bridge/Chart.yaml @@ -14,4 +14,4 @@ annotations: application.giantswarm.io/team: "shield" dependencies: - name: op-scim-bridge - # version: 0.1.0-alpha.1 + version: 2.11.7 diff --git a/helm/1password-scim-bridge/charts/op-scim-bridge/Chart.lock b/helm/1password-scim-bridge/charts/op-scim-bridge/Chart.lock new file mode 100644 index 0000000..68890e2 --- /dev/null +++ b/helm/1password-scim-bridge/charts/op-scim-bridge/Chart.lock @@ -0,0 +1,9 @@ +dependencies: +- name: redis + repository: https://charts.bitnami.com/bitnami + version: 20.6.0 +- name: common + repository: https://charts.bitnami.com/bitnami + version: 2.27.0 +digest: sha256:de7f240531402b2d3f6bddca4f7e343202b4f5dbb7c85bccaacccfbffea98630 +generated: "2024-12-16T14:38:33.452735-05:00" diff --git a/helm/1password-scim-bridge/charts/op-scim-bridge/Chart.yaml b/helm/1password-scim-bridge/charts/op-scim-bridge/Chart.yaml new file mode 100644 index 0000000..9b1c1ab --- /dev/null +++ b/helm/1password-scim-bridge/charts/op-scim-bridge/Chart.yaml @@ -0,0 +1,28 @@ +apiVersion: v2 +name: op-scim-bridge +version: 2.11.7 +description: A Helm chart for deploying the 1Password SCIM bridge +keywords: + - "1Password" + - "1Password SCIM bridge" + - "SCIM" + - "automated provisioning" + - "Azure Active Directory" + - "JumpCloud" + - "Okta" + - "OneLogin" + - "Rippling" +home: https://support.1password.com/scim +maintainers: + - name: 1Password Provisioning Team + email: support+scim@1password.com +icon: https://1password.com/img/logo-v1.svg +appVersion: v2.9.9 +dependencies: + - name: redis + version: ~20 + repository: https://charts.bitnami.com/bitnami + condition: redis.enabled + - name: common + version: ~2 + repository: https://charts.bitnami.com/bitnami diff --git a/helm/1password-scim-bridge/charts/op-scim-bridge/README.md b/helm/1password-scim-bridge/charts/op-scim-bridge/README.md new file mode 100644 index 0000000..b8c1bc1 --- /dev/null +++ b/helm/1password-scim-bridge/charts/op-scim-bridge/README.md @@ -0,0 +1,133 @@ +# 1Password SCIM bridge + +This repository defines the Helm chart for the 1Password SCIM bridge application. + +We intend to use this as a repository that can be referenced in our various kubernetes marketplace solutions. It may also be used outside of that context with an appropriate deployment script. + +**Homepage:** https://support.1password.com/scim + +## Maintainers + +| Name | Email | +| ---- | ----- | +| 1Password Provisioning Team | support+scim@1password.com | + +## Dependencies + +| Repository | Name | Version | +| ---------- |------|---------| +| [bitnami](https://github.com/bitnami/charts) | [redis](https://github.com/bitnami/charts/tree/master/bitnami/redis) | 12.0.0 | + +## Prerequisites + +You will need Helm installed to use this chart. Get the latest [Helm](https://github.com/kubernetes/helm#install) release. + +## Installation + +### Add repository + +```shell +helm repo add 1password https://1password.github.io/op-scim-helm +helm repo update +``` + +### Install chart + +```shell +helm install my-release 1password/op-scim-bridge +``` + +### Uninstall chart + +```shell +helm uninstall my-release +``` + +## Values + +The values are split into two sections: +- [scim](#scim) options +- [redis](#redis) options + +### scim + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| name | string | `op-scim-bridge` | SCIM bridge name. | +| version | string | `major.minor.patch` | SCIM bridge verion. | +| credentialsVolume | object | `{}` | Use a volume for the SCIM bridge credentials. See [credentialsVolume](#credentialsVolume) for details. | +| credentialsSecrets | object | `{}` | Use a secret for the SCIM bridge credentials. See [credentialsSecrets](#credentialsSecrets) for details. | +| imageRepository | string | `1password/scim` | 1Password SCIM bridge image. | +| imagePullPolicy | string | `Always` | Image pull policy. | +| imagePullSecrets | list | `[]` | Image pull secrets. | +| httpPort | int | `8080` | HTTP port. | +| httpsPort | int | `8443` | HTTPS port. | +| service | object | `{ "enabled": true, "type": "LoadBalancer" }` | Service configuration. | +| ingress | object | `{}` | Ingress configuration. | +| probes | object | `{ "liveness": { "enabled": true, "path": "/ping" } }` | Liveness probe that uses the `GET /ping` endpoint for health checks. | +| config | object | `{}` | SCIM bridge config options. See [config](#config) for details. | +| resources | object | `{}` | Resource requests and/or limits for the SCIM bridge pod. | +| annotations | object | `{}` | Additional annotations. | +| labels | object | `{}` | Additional labels. | +| podAnnotations | object | `{}` | Annotations for SCIM bridge pod. | +| podLabels | object | `{}` | Labels for SCIM bridge pod. | +| nodeSelector | object | `{}` | Node selector for SCIM bridge pod. | +| affinity | object | `{ "podAntiAffinity": {} }` | Affinity for SCIM bridge pod. By default we configure pod anti-affinity to ensure redis and SCIM bridge pods are not scheduled on the same node. | +| tolerations | list | `[]` | Tolerations for SCIM bridge pod. | +| initContainers | object | `{}` | Configuration options for init containers. | +| replicaCount | int | `1` | Number of replicas in deployment. | +| autoscaling | object | `{}` | Configuration for `HorizontalPodAutoscaler` resource. Will override `replicaCount` when set. | +| podDisruptionBudget | object | `{}` | Configuration for `PodDisruptionBudget` resource. Requires more than 1 replica or `autoscaling` to be enabled to be effective. | +| serviceAccount | object | `{}` | Service account configuration. Default service account is used when disabled. | +| serviceMonitor | object | `{}` | Service monitor for Prometheus Operator. See [getting started](https://github.com/prometheus-operator/prometheus-operator/blob/main/Documentation/user-guides/getting-started.md) guide. | + +#### config + +These values set available SCIM bridge configuation options. For details on the options see the help output of the `op-scim` binary (`./op-scim --help`). + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| redisURL | string | `redis://op-scim-bridge-redis-master:6379` | Redis connection URL. | +| domain | string | unset | Allowed 1Password sign in URL. Not set by default. | +| tlsDomain | string | unset | Domain to attempt to get a certificate for via Let's Encrypt. Not set by default. | +| debug | bool | `false` | Enable `DEBUG` log level instead of the default `INFO` level. | +| jsonLogs | bool | `false` | Enable JSON log output. | +| prettyLogs | bool | `false` | Enable colorized log output. | + + +#### credentialsVolume + +Note that you should configure accessing the SCIM bridge credentials through either the `credentialsVolume` or the `credentialsSecrets`, and not both. + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| name | string | `op-scim-bridge-credentials` | Volume name. | +| files | object | `{ "scimFile": "scimsession", "workspaceSettingsFile": "workspace-settings.json", "workspaceKeyFile":"workspace-credentials.json" }` | File names for SCIM bridge credentials. | +| accessModes | list | `[ReadWriteOnce]` | Access modes. | +| resources | object | `{ "requests": { "storage": "1Gi" } }` | The default storage request is `1Gi`. | +| storageClass | string | unset | Storage class. Set to `"—"` to set value to `""` in resulting application. `do-block-storage` is recommended for Digital Ocean. | + +#### credentialsSecrets + +Note that you should configure accessing the SCIM bridge credentials through either the `credentialsVolume` or the `credentialsSecrets`, and not both. + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| scimsession | object | `{ “name”:”op-scim-bridge-credentials”, “key”: “scimsession”, “value_json”: “{}”, “value_base64”: “base64 encoded scimsession file” }` | scimsession secret definition. | +| workspaceSettings | object | `{ “name”:”op-scim-bridge-workspace-settings”, “key”: “workspace-settings”, “value_json”: “{}”, “value_base64”: “base64 encoded workspace settings file” }` | workspace settings secret definition. | +| workspaceCredentials | object | `{ “name”:”op-scim-bridge-workspace-credentials”, “key”: “workspace-credentials”, “value_json”: “{}”, “value_base64”: “base64 encoded workspace credentials file” }` | workspace credentials secret definition. | + + +### redis + +This is a small subset of possible the values that you can configure for Redis. See the [bitnami/redis](https://github.com/bitnami/charts/tree/master/bitnami/redis) chart documentation for more details. + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| enabled | bool | `true` | Controls whether redis is deployed with the SCIM bridge. | +| image | object | `{ "registry": "docker.io", "repository": "bitnami/redis", "tag": "latest", "pullPolicy": "IfNotPreset" }` | Use the latest `bitnami/redis` image from `docker.io` and pull the image if it is not present. | +| cluster | object | `{"enabled": false }` | Redis cluster is disabled by default. | +| usePassword | bool | `false` | Use password is disabled by default. | +| master.affinity | object | `{ "affinity": "podAntiAffinity": {} }` | Master affinity. By default we configure pod anti-affinity to ensure redis and SCIM bridge pods are not scheduled on the same node. Note that this configuration should be duplicated for the slave when not running redis in standalone mode. | +| master.resources | object | `{}` | Master resource requests and limits. | +| master.extraFlags | object | `{}` | Master extra flags. By default set a maximum memory limit and define the policy to use when key eviction is required. | diff --git a/helm/1password-scim-bridge/charts/op-scim-bridge/charts/common-2.27.0.tgz b/helm/1password-scim-bridge/charts/op-scim-bridge/charts/common-2.27.0.tgz new file mode 100644 index 0000000..54431d6 Binary files /dev/null and b/helm/1password-scim-bridge/charts/op-scim-bridge/charts/common-2.27.0.tgz differ diff --git a/helm/1password-scim-bridge/charts/op-scim-bridge/charts/redis-20.6.0.tgz b/helm/1password-scim-bridge/charts/op-scim-bridge/charts/redis-20.6.0.tgz new file mode 100644 index 0000000..2726e55 Binary files /dev/null and b/helm/1password-scim-bridge/charts/op-scim-bridge/charts/redis-20.6.0.tgz differ diff --git a/helm/1password-scim-bridge/charts/op-scim-bridge/ci/with-scim-values.yaml b/helm/1password-scim-bridge/charts/op-scim-bridge/ci/with-scim-values.yaml new file mode 100644 index 0000000..4735575 --- /dev/null +++ b/helm/1password-scim-bridge/charts/op-scim-bridge/ci/with-scim-values.yaml @@ -0,0 +1,23 @@ +scim: + + credentials: + volume: + enabled: false + secret: + scimsession: + key: scimsession + value_json: '{}' + workspaceSettings: + key: workspace-settings + value_json: '{}' + workspaceCredentials: + key: workspace-credentials + value_json: '{}' + service: + enabled: true + type: NodePort + probes: + liveness: + enabled: false + config: + redisURL: "redis://{{ .Release.Namespace }}-redis-master:6379" diff --git a/helm/1password-scim-bridge/charts/op-scim-bridge/templates/_helpers.tpl b/helm/1password-scim-bridge/charts/op-scim-bridge/templates/_helpers.tpl new file mode 100644 index 0000000..f9537ca --- /dev/null +++ b/helm/1password-scim-bridge/charts/op-scim-bridge/templates/_helpers.tpl @@ -0,0 +1,56 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "op-scim-bridge.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "op-scim-bridge.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "op-scim-bridge.labels" -}} +helm.sh/chart: {{- include "op-scim-bridge.chart" . -}} +{{- include "op-scim-bridge.selectorLabels" . -}} +{{- if .Chart.AppVersion -}} +app.kubernetes.io/version: {{- .Chart.AppVersion | quote -}} +{{- end -}} +app.kubernetes.io/managed-by: {{- .Release.Service -}} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "op-scim-bridge.selectorLabels" -}} +app.kubernetes.io/name: {{- include "op-scim-bridge.name" . -}} +app.kubernetes.io/instance: {{- .Release.Name -}} +{{- end -}} + + +{{- define "helm-toolkit.utils.joinListWithComma" -}} +{{- $local := dict "first" true -}} +{{- range $k, $v := . -}}{{- if not $local.first -}},{{- end -}}{{- $v -}}{{- $_ := set $local "first" false -}}{{- end -}} +{{- end -}} + +{{- define "op-scim-bridge.port" -}} +{{- if .Values.scim.tls.enabled -}} +{{- .Values.scim.httpsPort -}} +{{- else -}} +{{- .Values.scim.httpPort -}} +{{- end -}} +{{- end -}} + +{{- define "op-scim-bridge.url" -}} +{{- if .Values.scim.tls.enabled -}} +https://{{- tpl .Values.scim.name . -}}-svc +{{- else -}} +http://{{- tpl .Values.scim.name . -}}-svc +{{- end -}} +{{- end -}} diff --git a/helm/1password-scim-bridge/charts/op-scim-bridge/templates/deployment.yaml b/helm/1password-scim-bridge/charts/op-scim-bridge/templates/deployment.yaml new file mode 100644 index 0000000..a63fac3 --- /dev/null +++ b/helm/1password-scim-bridge/charts/op-scim-bridge/templates/deployment.yaml @@ -0,0 +1,177 @@ +{{- if and .Values.scim.credentials.volume.enabled .Values.scim.credentials.secrets.enabled }} +{{- fail "scim.credentials.volume.enabled and scim.credentials.secrets.enabled are mutually exclusive." }} +{{- end }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ tpl .Values.scim.name . }} + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/component: {{ tpl .Values.scim.name . }} + {{- with .Values.scim.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.scim.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + app: {{ tpl .Values.scim.name . }} + {{- if not .Values.scim.autoscaling.enabled }} + replicas: {{ .Values.scim.replicaCount }} + {{- end }} + strategy: + type: Recreate + template: + metadata: + labels: + app: {{ tpl .Values.scim.name . }} + version: {{ tpl .Values.scim.version . }} + app.kubernetes.io/component: {{ tpl .Values.scim.name . }} + {{- with .Values.scim.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.scim.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- if .Values.scim.serviceAccount.create }} + {{- if .Values.scim.serviceAccount.name }} + serviceAccountName: {{ .Values.scim.serviceAccount.name }} + {{- else }} + serviceAccountName: {{ tpl .Values.scim.name . }} + {{- end }} + {{- end }} + {{- with .Values.scim.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.scim.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.scim.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if .Values.scim.credentials.volume.enabled }} + volumes: + - name: "{{ tpl .Values.scim.credentials.volume.name . }}" + persistentVolumeClaim: + claimName: "{{ tpl .Values.scim.credentials.volume.claimName . }}" + {{- end }} + {{- if .Values.scim.credentials.volume.enabled }} + initContainers: + - name: opuser-home-permissions + image: alpine:3.16 + command: + - "/bin/sh" + - "-c" + args: + - "mkdir -p /home/opuser/.op && chown -R 999 /home/opuser && chmod -R 700 /home/opuser" + volumeMounts: + - mountPath: /home/opuser/.op + name: "{{ tpl .Values.scim.credentials.volume.name . }}" + {{- with .Values.scim.initContainers.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- end }} + containers: + - name: {{ tpl .Values.scim.name . }} + image: {{ .Values.scim.imageRepository }}:{{ tpl .Values.scim.version . }} + imagePullPolicy: {{ .Values.scim.imagePullPolicy }} + command: ["/op-scim/op-scim"] + securityContext: + runAsUser: 999 + runAsGroup: 999 + allowPrivilegeEscalation: false + {{- with .Values.scim.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.scim.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + env: + - name: "OP_PORT" + value: "{{ .Values.scim.httpPort }}" + - name: "OP_SESSION" + {{- if .Values.scim.credentials.volume.enabled }} + value: "/home/opuser/.op/{{ .Values.scim.credentials.volume.files.scimsessionFile }}" + {{- end }} + {{- if .Values.scim.credentials.secrets.enabled }} + valueFrom: + secretKeyRef: + name: "{{ tpl .Values.scim.credentials.secrets.name . }}" + key: {{ .Values.scim.credentials.secrets.scimsession.key }} + {{- end }} + - name: "OP_WORKSPACE_SETTINGS" + {{- if .Values.scim.credentials.volume.enabled }} + value: "/home/opuser/.op/{{ .Values.scim.credentials.volume.files.workspaceSettingsFile }}" + {{- end }} + {{- if .Values.scim.credentials.secrets.enabled }} + valueFrom: + secretKeyRef: + name: "{{ tpl .Values.scim.credentials.secrets.name . }}" + key: {{ .Values.scim.credentials.secrets.workspaceSettings.key }} + optional: true + {{- end }} + - name: "OP_WORKSPACE_CREDENTIALS" + {{- if .Values.scim.credentials.volume.enabled }} + value: "/home/opuser/.op/{{ .Values.scim.credentials.volume.files.workspaceCredentialsFile }}" + {{- end }} + {{- if .Values.scim.credentials.secrets.enabled }} + valueFrom: + secretKeyRef: + name: "{{ tpl .Values.scim.credentials.secrets.name . }}" + key: {{ .Values.scim.credentials.secrets.workspaceCredentials.key }} + optional: true + {{- end }} + - name: "OP_REDIS_URL" + value: "{{ tpl .Values.scim.config.redisURL . }}" + - name: "OP_PING_SERVER" + value: "{{ .Values.scim.probes.liveness.enabled }}" + {{- if .Values.scim.config.tlsDomain }} + - name: "OP_TLS_DOMAIN" + value: "{{ .Values.scim.config.tlsDomain }}" + {{- end }} + {{- if .Values.scim.config.domain }} + - name: "OP_DOMAIN" + value: {{ .Values.scim.config.domain }} + {{- end }} + {{- if .Values.scim.config.debug }} + - name: "OP_DEBUG" + value: "{{ .Values.scim.config.debug }}" + {{- end }} + {{- if .Values.scim.config.jsonLogs }} + - name: "OP_JSON_LOGS" + value: "{{ .Values.scim.config.jsonLogs }}" + {{- end }} + {{- if .Values.scim.config.prettyLogs }} + - name: "OP_PRETTY_LOGS" + value: "{{ .Values.scim.config.prettyLogs }}" + {{- end }} + ports: + - containerPort: {{ .Values.scim.httpPort }} + - containerPort: {{ .Values.scim.httpsPort }} + {{- if .Values.scim.probes.liveness.enabled }} + livenessProbe: + httpGet: + path: {{ .Values.scim.probes.liveness.path }} + scheme: HTTP + port: {{ .Values.scim.httpPort }} + failureThreshold: 3 + periodSeconds: 30 + initialDelaySeconds: 15 + {{- end }} + {{- if .Values.scim.credentials.volume.enabled }} + volumeMounts: + - name: "{{ tpl .Values.scim.credentials.volume.name . }}" + mountPath: "/home/opuser/.op" + readOnly: false + {{- end }} diff --git a/helm/1password-scim-bridge/charts/op-scim-bridge/templates/horizontalPodAutoscaler.yaml b/helm/1password-scim-bridge/charts/op-scim-bridge/templates/horizontalPodAutoscaler.yaml new file mode 100644 index 0000000..a66d15c --- /dev/null +++ b/helm/1password-scim-bridge/charts/op-scim-bridge/templates/horizontalPodAutoscaler.yaml @@ -0,0 +1,48 @@ +{{- if .Values.scim.autoscaling.enabled }} +{{- if semverCompare ">=1.23-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: autoscaling/v2 +{{- else }} +apiVersion: autoscaling/v2beta1 +{{- end }} +kind: HorizontalPodAutoscaler +metadata: + name: {{ tpl .Values.scim.name . }} + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/component: {{ tpl .Values.scim.name . }} + {{- with .Values.scim.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ tpl .Values.scim.name . }} + minReplicas: {{ .Values.scim.autoscaling.minReplicas }} + maxReplicas: {{ .Values.scim.autoscaling.maxReplicas }} + metrics: + {{- if .Values.scim.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + {{- if semverCompare ">=1.23-0" .Capabilities.KubeVersion.GitVersion }} + target: + type: Utilization + averageUtilization: {{ .Values.scim.autoscaling.targetCPUUtilizationPercentage }} + {{- else }} + targetAverageUtilization: {{ .Values.scim.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- end }} + {{- if .Values.scim.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + {{- if semverCompare ">=1.23-0" .Capabilities.KubeVersion.GitVersion -}} + target: + type: Utilization + averageUtilization: {{ .Values.scim.autoscaling.targetMemoryUtilizationPercentage }} + {{- else }} + targetAverageUtilization: {{ .Values.scim.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} + {{- end }} +{{- end }} diff --git a/helm/1password-scim-bridge/charts/op-scim-bridge/templates/ingress.yaml b/helm/1password-scim-bridge/charts/op-scim-bridge/templates/ingress.yaml new file mode 100644 index 0000000..339fd81 --- /dev/null +++ b/helm/1password-scim-bridge/charts/op-scim-bridge/templates/ingress.yaml @@ -0,0 +1,64 @@ +{{- if .Values.scim.ingress.enabled -}} +{{- $name := tpl .Values.scim.name . -}} +{{- if and .Values.scim.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.scim.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.scim.ingress.annotations "kubernetes.io/ingress.class" .Values.scim.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $name }} + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/component: {{ $name }} + {{- with .Values.scim.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.scim.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.scim.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.scim.ingress.className }} + {{- end }} + {{- if .Values.scim.ingress.tls }} + tls: + {{- range .Values.scim.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.scim.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: "{{$name}}-svc" + port: + number: 80 + {{- else }} + serviceName: "{{$name}}-svc" + servicePort: 80 + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/helm/1password-scim-bridge/charts/op-scim-bridge/templates/persistentvolumeclaim.yaml b/helm/1password-scim-bridge/charts/op-scim-bridge/templates/persistentvolumeclaim.yaml new file mode 100644 index 0000000..fb77c51 --- /dev/null +++ b/helm/1password-scim-bridge/charts/op-scim-bridge/templates/persistentvolumeclaim.yaml @@ -0,0 +1,32 @@ +{{- if .Values.scim.credentials.volume.enabled }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: "{{ tpl .Values.scim.credentials.volume.claimName . }}" + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/application: {{ tpl .Values.scim.name . }} + {{- with .Values.scim.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.scim.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- with .Values.scim.credentials.volume.accessModes }} + accessModes: + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.scim.credentials.volume.resources }} + resources: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- if .Values.scim.credentials.volume.storageClass }} + {{- if (eq "-" .Values.scim.credentials.volume.storageClass) }} + storageClassName: '""' + {{- else }} + storageClassName: "{{ .Values.scim.credentials.volume.storageClass }}" + {{- end }} +{{- end }} +{{- end }} diff --git a/helm/1password-scim-bridge/charts/op-scim-bridge/templates/podDisruptionBudget.yaml b/helm/1password-scim-bridge/charts/op-scim-bridge/templates/podDisruptionBudget.yaml new file mode 100644 index 0000000..42c3479 --- /dev/null +++ b/helm/1password-scim-bridge/charts/op-scim-bridge/templates/podDisruptionBudget.yaml @@ -0,0 +1,21 @@ +{{- if .Values.scim.podDisruptionBudget.enabled -}} +{{- if semverCompare ">=1.21-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: policy/v1 +{{- else -}} +apiVersion: policy/v1beta1 +{{- end }} +kind: PodDisruptionBudget +metadata: + name: {{ tpl .Values.scim.name . }} + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/component: {{ tpl .Values.scim.name . }} + {{- with .Values.scim.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + minAvailable: {{ .Values.scim.podDisruptionBudget.minAvailable }} + selector: + matchLabels: + app: {{ tpl .Values.scim.name . }} +{{- end }} diff --git a/helm/1password-scim-bridge/charts/op-scim-bridge/templates/secret.yaml b/helm/1password-scim-bridge/charts/op-scim-bridge/templates/secret.yaml new file mode 100644 index 0000000..6a68c8f --- /dev/null +++ b/helm/1password-scim-bridge/charts/op-scim-bridge/templates/secret.yaml @@ -0,0 +1,42 @@ +{{- if .Values.scim.credentials.secrets.enabled }} +{{- if .Values.scim.credentials.secrets.create }} +kind: Secret +apiVersion: v1 +metadata: + name: "{{ tpl .Values.scim.credentials.secrets.name . }}" + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/application: {{ tpl .Values.scim.name . }} + {{- with .Values.scim.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.scim.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +type: Opaque +{{- if not .Values.scim.credentials.secrets.googleWorkspace }} +{{- $secrets := pick .Values.scim.credentials.secrets "scimsession" }} +stringData: + {{- range $secret := $secrets }} + {{ $secret.key }}: |- + {{ if $secret.value_json }} + {{- $secret.value_json | b64enc | indent 2 }} + {{ else if $secret.value_base64 }} + {{- $secret.value_base64 | indent 2 }} + {{ end }} + {{- end }} +{{- else }} +{{- $secrets := pick .Values.scim.credentials.secrets "workspaceSettings" "workspaceCredentials" "scimsession" }} +stringData: + {{- range $secret := $secrets }} + {{ $secret.key }}: |- + {{ if $secret.value_json }} + {{- $secret.value_json | b64enc | indent 2 }} + {{ else }} + {{- $secret.value_base64 | indent 2 }} + {{ end }} + {{- end }} +{{- end }} +{{- end }} +{{- end }} diff --git a/helm/1password-scim-bridge/charts/op-scim-bridge/templates/service.yaml b/helm/1password-scim-bridge/charts/op-scim-bridge/templates/service.yaml new file mode 100644 index 0000000..c4dbf2f --- /dev/null +++ b/helm/1password-scim-bridge/charts/op-scim-bridge/templates/service.yaml @@ -0,0 +1,29 @@ +{{- if .Values.scim.service.enabled -}} +apiVersion: v1 +kind: Service +metadata: + name: "{{ tpl .Values.scim.name . }}-svc" + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/component: {{ tpl .Values.scim.name . }} + {{- with .Values.scim.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.scim.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.scim.service.type }} + selector: + app: {{ tpl .Values.scim.name . }} + ports: + - name: http + port: 80 + protocol: TCP + targetPort: {{ .Values.scim.httpPort }} + - name: https + port: 443 + protocol: TCP + targetPort: {{ .Values.scim.httpsPort }} +{{- end }} diff --git a/helm/1password-scim-bridge/charts/op-scim-bridge/templates/serviceAccount.yaml b/helm/1password-scim-bridge/charts/op-scim-bridge/templates/serviceAccount.yaml new file mode 100644 index 0000000..ac9d3b1 --- /dev/null +++ b/helm/1password-scim-bridge/charts/op-scim-bridge/templates/serviceAccount.yaml @@ -0,0 +1,20 @@ +{{- if .Values.scim.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + {{- if .Values.scim.serviceAccount.name }} + name: {{ .Values.scim.serviceAccount.name }} + {{- else }} + name: {{ tpl .Values.scim.name . }} + {{- end }} + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/component: {{ tpl .Values.scim.name . }} + {{- with .Values.scim.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.scim.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/helm/1password-scim-bridge/charts/op-scim-bridge/templates/serviceMonitor.yaml b/helm/1password-scim-bridge/charts/op-scim-bridge/templates/serviceMonitor.yaml new file mode 100644 index 0000000..4401a63 --- /dev/null +++ b/helm/1password-scim-bridge/charts/op-scim-bridge/templates/serviceMonitor.yaml @@ -0,0 +1,30 @@ +{{- if .Values.scim.serviceMonitor.enabled -}} +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: {{ tpl .Values.scim.name . }} + {{- if .Values.scim.serviceMonitor.namespace }} + namespace: {{ .Values.scim.serviceAccount.namespace }} + {{- else }} + namespace: {{ .Release.Namespace }} + {{- end }} + labels: + app.kubernetes.io/component: {{ tpl .Values.scim.name . }} + {{- with .Values.scim.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + selector: + matchLabels: + app.kubernetes.io/component: {{ tpl .Values.scim.name . }} + namespaceSelector: + matchNames: + - {{ .Release.Namespace }} + endpoints: + - port: http + path: /metrics + {{- with .Values.scim.serviceMonitor.bearerTokenSecret }} + bearerTokenSecret: + {{- toYaml . | nindent 6 }} + {{- end }} +{{- end }} diff --git a/helm/1password-scim-bridge/charts/op-scim-bridge/templates/tests/auth.yaml b/helm/1password-scim-bridge/charts/op-scim-bridge/templates/tests/auth.yaml new file mode 100644 index 0000000..ed581ff --- /dev/null +++ b/helm/1password-scim-bridge/charts/op-scim-bridge/templates/tests/auth.yaml @@ -0,0 +1,25 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ .Release.Name }}-auth-check" + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/component: {{ tpl .Values.scim.name . }} + {{- with .Values.scim.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + helm.sh/hook: test + helm.sh/hook-weight: "1" + {{- with .Values.scim.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + restartPolicy: Never + containers: + - name: curl + image: curlimages/curl + command: + - "curl" + - "-H 'Authorization: Bearer {{ .Values.scim.serviceMonitor.bearerTokenSecret }}'" + - "{{ include "op-scim-bridge.url" . }}/health" diff --git a/helm/1password-scim-bridge/charts/op-scim-bridge/templates/tests/ping.yaml b/helm/1password-scim-bridge/charts/op-scim-bridge/templates/tests/ping.yaml new file mode 100644 index 0000000..305cf1c --- /dev/null +++ b/helm/1password-scim-bridge/charts/op-scim-bridge/templates/tests/ping.yaml @@ -0,0 +1,22 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ .Release.Name }}-ping-check" + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/component: {{ tpl .Values.scim.name . }} + {{- with .Values.scim.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + annotations: + helm.sh/hook: test + helm.sh/hook-weight: "1" + {{- with .Values.scim.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + restartPolicy: Never + containers: + - name: curl + image: curlimages/curl + command: ["curl", "{{ include "op-scim-bridge.url" . }}/ping"] diff --git a/helm/1password-scim-bridge/charts/op-scim-bridge/values.yaml b/helm/1password-scim-bridge/charts/op-scim-bridge/values.yaml new file mode 100644 index 0000000..e5aaf80 --- /dev/null +++ b/helm/1password-scim-bridge/charts/op-scim-bridge/values.yaml @@ -0,0 +1,228 @@ +# scim configuration options +scim: + # name sets the name used for the various constructs used by the SCIM bridge setup + name: '{{ template "common.names.fullname" . }}' + # version of the SCIM bridge + version: "{{ .Chart.AppVersion }}" + # configure the credentials used by the SCIM bridge + credentials: + volume: + # setting enabled:true configures the SCIM bridge to access the credentials via a volume + enabled: true + # name of an existing volume to use for the credentials + name: '{{ template "common.names.fullname" . }}-credentials' + claimName: '{{ template "common.names.fullname" . }}-pvc' + # name of the file to mount within the volume + files: + scimsessionFile: scimsession + workspaceSettingsFile: workspace-settings.json + workspaceCredentialsFile: workspace-credentials.json + # accessModes for the volume + accessModes: + - ReadWriteOnce + # resources configuration for the volume + resources: + requests: + storage: 1Gi + # storageClass for the volume. do-block-storage is recommended for Digital Ocean. Set to "-" to set storageClass to "". + # storageClass: + secrets: + # Set to true if you are using Google Workspace as your identity provider + googleWorkspace: false + # setting enabled:true configures the SCIM bridge to access the credentials via a secret + enabled: false + # create the secret if it does not exist + create: false + # name of the secret + name: '{{ template "common.names.fullname" . }}-credentials' + scimsession: + # key of the secret + key: scimsession + # value_json is the JSON contents of the scimsession file + # value_base64 is the base64 encoded contents of the scimsession file + # value_base64: "base64-encoded scimsession file" + workspaceSettings: + # key of the secret + key: workspace-settings + # value_json is the JSON contents of the scimsession file + # value_json: '{}' + # value_base64 is the base64 encoded contents of the workspace settings file + # value_base64: "base64 encoded contents of the workspace settings file" + workspaceCredentials: + # key of the secret + key: workspace-credentials + # value_json is the JSON contents of the scimsession file + # value_json: '{}' + # value_base64 is the base64 encoded contents of the workspace key file + # value_base64: "base64 encoded contents of the workspace key file" + # imageRepository sets the 1Password SCIM bridge image to use + imageRepository: 1password/scim + # imagePullPolicy sets the image pull policy + imagePullPolicy: Always + # imagePullPolicy sets the image pull secret + imagePullSecrets: [] + # httpPort sets the HTTP port used by the SCIM bridge + httpPort: 8080 + # httpsPort sets the HTTPS port used by the SCIM bridge + httpsPort: 8443 + # service defines the configuration for a service resource + service: + enabled: true + type: LoadBalancer + # ingress defines the configuration for an ingress resource + ingress: + enabled: false + className: "" + annotations: {} + hosts: + [] + # - host: chart-example.local + # paths: + # - path: / + # pathType: ImplementationSpecific + tls: + [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + # probes configures the liveness probe used for the SCIM bridge pod + probes: + # liveness contains the liveness probe config + liveness: + # enabled determines whether to enable the liveness probe + enabled: true + # path sets the URL path to use for the liveness probe + path: "/ping" + # config sets the configuration options + config: + # redisURL sets the Redis connection URL + redisURL: "redis://{{ .Release.Name }}-redis-master:6379" + # domain sets the allowed 1Password sign in URL. Not set by default. + # domain: example.1password.com + # tlsDomain sets the domain to attempt to get a certificate for via Let's Encrypt. + # debug enables DEBUG log level instead of the default INFO level + # debug: false + # jsonLogs enables JSON log output + # jsonLogs: false + # prettyLogs enables colorized log output + # prettyLogs: false + tls: + enabled: false + secret: "{{ .Release.Name }}-tls" + # resource sets the requests and/or limits for the SCIM bridge pod + resources: + requests: + cpu: 125m + memory: 256M + limits: + cpu: 250m + memory: 512M + # annotations adds additional annotations + annotations: {} + # labels adds additional labels + labels: {} + # podAnnotations sets annotations for the SCIM bridge pod + podAnnotations: {} + # podLabels sets the labels for the SCIM bridge pod + podLabels: {} + # nodeSelector sets the node selector for the SCIM bridge pod + nodeSelector: {} + # affinity sets the affinity for the SCIM bridge pod + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - redis + topologyKey: "kubernetes.io/hostname" + # tolerations sets the tolerations for the SCIM bridge pod + tolerations: [] + # replicaCount sets number of replicas to deploy + replicaCount: 1 + # autoscaling if enabled creates a HorizontalPodAutoscaler resource. Will override replicaCount + autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 2 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + # podDisruptionBudget configuration. Requires more than 1 replica or + # autoscaling to be enabled to be effective. + podDisruptionBudget: + enabled: false + minAvailable: 1 + # serviceAccount configuration. Default service account is used when disabled. + serviceAccount: + # create determines whether a service account should be created + create: true + # name of the service account to use + # If not set and create is true, a name is generated using the full name template. + name: "" + # serviceMonitor if enabled create prometheus ServiceMonitor for auto discovery + serviceMonitor: + enabled: false + # namespace to deploy the service monitor to + namespace: "" + # bearerTokenSecret specifies the secret that contains the SCIM bridge bearer token + bearerTokenSecret: + {} + # key: secret-key + # name: secret-name + # initContainers sets config options for the init containers + initContainers: + resources: {} +# redis configuration options (see upstream chart documentation and README.MD) +redis: + enabled: true + auth: + enabled: false + # this can be changed to "replication" if you wish to have more redis nodes; see bitnami chart documentation + architecture: standalone + image: + registry: docker.io + repository: bitnami/redis + tag: latest + pullPolicy: IfNotPresent + cluster: + enabled: false + usePassword: false + # redis config options applied to all instances in the configuration + commonConfiguration: |- + maxmemory 256mb + maxmemory-policy volatile-lru + # Disable RDB persistence + save "" + master: + kind: Deployment + # prefer to schedule redis and SCIM bridge pods on separate nodes + # this configuration should be duplicated for replica.affinity when not running redis as a standalone instance + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app + operator: In + values: + - op-scim-bridge + topologyKey: "kubernetes.io/hostname" + persistence: + enabled: false + resources: + requests: + cpu: 125m + memory: 256M + limits: + cpu: 250m + memory: 512M + +# acceptanceTests is used by the tests run during CI (see templates/tests) +acceptanceTests: + enabled: false