diff --git a/charts/jit-k8s-agent/README.md b/charts/jit-k8s-agent/README.md index 553f1b8..8c9ad87 100644 --- a/charts/jit-k8s-agent/README.md +++ b/charts/jit-k8s-agent/README.md @@ -38,6 +38,7 @@ The following table lists the configurable parameters of the `jit-k8s-agent` cha | `cluster.name` | Name of the cluster (required) `(1)` | `""` | | `jit.clientId` | Jit service client ID (required) `(2)` | `""` | | `jit.clientSecret` | Jit service client secret (required) `(2)` | `""` | +| `jit.existingSecret` | Name of existing secret with credentials `(2)` | `""` | | `jit.apiUrl` | Jit service API URL | `https://api.jit.io` | | `serviceAccount.name` | Name of the service account | `jit-k8s-agent-sa` | | `resources.requests.cpu` | CPU resource requests | `500m` | @@ -45,7 +46,9 @@ The following table lists the configurable parameters of the `jit-k8s-agent` cha | `resources.limits.cpu` | CPU resource limits | `1000m` | | `resources.limits.memory` | Memory resource limits | `4Gi` | | `kubescape.enabled` | Enable Kubescape security scanning | `true` | +| `nodeSelector` | Node selector for pod scheduling | `{}` | +| `tolerations` | Tolerations for pod scheduling on tainted nodes | `[]` | `(1)` You can retrieve the cluster name by running `kubectl config get-clusters` or `kubectl config current-context`. The cluster name should be unique across all clusters. -`(2)` Refer to [Jit documentation](https://docs.jit.io/docs/managing-users#generating-api-tokens) for more information on how to get the client ID and secret. +`(2)` Authentication: Provide either `clientId` + `clientSecret` OR `existingSecret`. Refer to [Jit documentation](https://docs.jit.io/docs/managing-users#generating-api-tokens) for more information on how to get the client ID and secret. diff --git a/charts/jit-k8s-agent/templates/_job_helper.tpl b/charts/jit-k8s-agent/templates/_job_helper.tpl index 9ec1554..abaa6c2 100644 --- a/charts/jit-k8s-agent/templates/_job_helper.tpl +++ b/charts/jit-k8s-agent/templates/_job_helper.tpl @@ -1,7 +1,16 @@ {{- define "jit-job-spec" -}} +{{- $jitCredentialsSecret := .Values.jit.existingSecret | default (printf "%s-jit-credentials" .Chart.Name) -}} spec: serviceAccountName: {{ .Values.serviceAccount.name }} restartPolicy: OnFailure + {{- if .Values.tolerations }} + tolerations: +{{ toYaml .Values.tolerations | indent 4 }} + {{- end }} + {{- if .Values.nodeSelector }} + nodeSelector: +{{ toYaml .Values.nodeSelector | indent 4 }} + {{- end }} containers: - name: jit-k8s-agent image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" @@ -19,12 +28,12 @@ spec: - name: JIT_CLIENT_ID valueFrom: secretKeyRef: - name: {{ .Chart.Name }}-jit-credentials + name: {{ $jitCredentialsSecret }} key: JIT_CLIENT_ID - name: JIT_CLIENT_SECRET valueFrom: secretKeyRef: - name: {{ .Chart.Name }}-jit-credentials + name: {{ $jitCredentialsSecret }} key: JIT_CLIENT_SECRET - name: JIT_API_URL value: {{ .Values.jit.apiUrl }} diff --git a/charts/jit-k8s-agent/templates/_validation.tpl b/charts/jit-k8s-agent/templates/_validation.tpl new file mode 100644 index 0000000..fb2caf3 --- /dev/null +++ b/charts/jit-k8s-agent/templates/_validation.tpl @@ -0,0 +1,48 @@ +{{/* +Validate required values and provide clear error messages +*/}} +{{- define "jit-k8s-agent.validateValues" -}} +{{- $errors := list -}} + +{{- if not .Values.cluster.name -}} +{{- $errors = append $errors "cluster.name is required and cannot be empty" -}} +{{- end -}} + +{{- if .Values.jit -}} + {{- $hasClientId := and .Values.jit.clientId (ne .Values.jit.clientId "") -}} + {{- $hasClientSecret := and .Values.jit.clientSecret (ne .Values.jit.clientSecret "") -}} + {{- $hasExistingSecret := and .Values.jit.existingSecret (ne .Values.jit.existingSecret "") -}} + + {{- if and $hasClientId $hasClientSecret -}} + {{- if $hasExistingSecret -}} +{{- $errors = append $errors "Cannot specify both direct credentials (clientId/clientSecret) and existingSecret. Choose one authentication method." -}} + {{- end -}} + {{- else if $hasClientId -}} +{{- $errors = append $errors "clientSecret is required when clientId is provided" -}} + {{- else if $hasClientSecret -}} +{{- $errors = append $errors "clientId is required when clientSecret is provided" -}} + {{- else if $hasExistingSecret -}} + {{- /* Valid: using existingSecret */ -}} + {{- else -}} +{{- $errors = append $errors "Jit authentication requires either: 1) Both 'clientId' and 'clientSecret' for direct authentication, or 2) 'existingSecret' to reference an existing Kubernetes secret" -}} + {{- end -}} +{{- else -}} +{{- $errors = append $errors "Jit configuration is required. Please provide either clientId/clientSecret or existingSecret" -}} +{{- end -}} + +{{- if $errors -}} +{{- $errorMsg := printf "Configuration validation failed:\n" -}} +{{- range $errors -}} +{{- $errorMsg = printf "%s • %s\n" $errorMsg . -}} +{{- end -}} +{{- $errorMsg = printf "%s\nExample configurations:\n" $errorMsg -}} +{{- $errorMsg = printf "%s # Option 1: Direct credentials\n" $errorMsg -}} +{{- $errorMsg = printf "%s jit:\n" $errorMsg -}} +{{- $errorMsg = printf "%s clientId: \"your-client-id\"\n" $errorMsg -}} +{{- $errorMsg = printf "%s clientSecret: \"your-client-secret\"\n" $errorMsg -}} +{{- $errorMsg = printf "%s\n # Option 2: Existing secret\n" $errorMsg -}} +{{- $errorMsg = printf "%s jit:\n" $errorMsg -}} +{{- $errorMsg = printf "%s existingSecret: \"jit-credentials\"\n" $errorMsg -}} +{{- fail $errorMsg -}} +{{- end -}} +{{- end -}} \ No newline at end of file diff --git a/charts/jit-k8s-agent/templates/secret.yaml b/charts/jit-k8s-agent/templates/secret.yaml index e331003..70e6ae7 100644 --- a/charts/jit-k8s-agent/templates/secret.yaml +++ b/charts/jit-k8s-agent/templates/secret.yaml @@ -1,3 +1,11 @@ +{{- include "jit-k8s-agent.validateValues" . -}} +{{- if not .Values.jit.existingSecret }} +{{- if not .Values.jit.clientId }} +{{- fail "clientId is required for secret creation but is empty or missing" }} +{{- end }} +{{- if not .Values.jit.clientSecret }} +{{- fail "clientSecret is required for secret creation but is empty or missing" }} +{{- end }} apiVersion: v1 kind: Secret metadata: @@ -7,5 +15,6 @@ metadata: namespace: {{ .Release.Namespace }} type: Opaque data: - JIT_CLIENT_ID: {{ .Values.jit.clientId | b64enc }} - JIT_CLIENT_SECRET: {{ .Values.jit.clientSecret | b64enc }} \ No newline at end of file + JIT_CLIENT_ID: {{ .Values.jit.clientId | toString | b64enc }} + JIT_CLIENT_SECRET: {{ .Values.jit.clientSecret | toString | b64enc }} +{{- end }} \ No newline at end of file diff --git a/charts/jit-k8s-agent/values.schema.json b/charts/jit-k8s-agent/values.schema.json index c9df71a..0dbd391 100644 --- a/charts/jit-k8s-agent/values.schema.json +++ b/charts/jit-k8s-agent/values.schema.json @@ -18,16 +18,22 @@ "properties": { "clientId": { "type": "string", - "minLength": 1, - "description": "The client ID for Jit. This field is required." + "description": "The client ID for Jit. This field is required when not using an existing secret." }, "clientSecret": { "type": "string", - "minLength": 1, - "description": "The client secret for Jit. This field is required." + "description": "The client secret for Jit. This field is required when not using an existing secret." + }, + "existingSecret": { + "type": "string", + "description": "The name of an existing secret to use for Jit credentials. If provided, clientId and clientSecret will be ignored." + }, + "apiUrl": { + "type": "string", + "description": "The Jit API URL" } }, - "required": ["clientId", "clientSecret"] + "description": "Jit authentication requires either: 1) Both 'clientId' and 'clientSecret' for direct authentication, or 2) 'existingSecret' to reference an existing Kubernetes secret containing the credentials." } } -} +} \ No newline at end of file diff --git a/charts/jit-k8s-agent/values.yaml b/charts/jit-k8s-agent/values.yaml index 3742f29..92d101b 100644 --- a/charts/jit-k8s-agent/values.yaml +++ b/charts/jit-k8s-agent/values.yaml @@ -7,8 +7,11 @@ cluster: name: "" # Required, set it while installing the chart. Should be unique across all clusters. jit: - clientId: "" # Required, set it while installing the chart - clientSecret: "" # Required, set it while installing the chart + # Option 1: Direct credentials (required if existingSecret is not provided) + clientId: "" # Set during installation when using direct credentials + clientSecret: "" # Set during installation when using direct credentials + # Option 2: Reference to existing secret (alternative to clientId/clientSecret) + existingSecret: "" # Name of existing secret containing JIT_CLIENT_ID and JIT_CLIENT_SECRET apiUrl: https://api.jit.io kubescape: @@ -24,3 +27,9 @@ resources: limits: cpu: "1000m" memory: "4Gi" + +# Optional: Node selector for pod scheduling +nodeSelector: {} + +# Optional: Tolerations for pod scheduling on tainted nodes +tolerations: [] \ No newline at end of file