From 05a4152f1aeca7d1fb05ad2e1f5609d49d559ee7 Mon Sep 17 00:00:00 2001 From: Oleksandr Dzhychko Date: Tue, 17 Dec 2024 15:35:38 +0100 Subject: [PATCH] feat(helm): add password protection to internal Docker registry Fixes MODELIX-1058 --- .../common/docker-registry-deployment.yaml | 18 +++++++++++++ .../common/docker-registry-secret.yaml | 26 +++++++++++++++++++ .../common/docker-registry-service.yaml | 1 + .../common/instances-manager-deployment.yaml | 4 +-- .../common/workspace-client-deployment.yaml | 3 ++- .../common/workspace-manager-deployment.yaml | 2 ++ helm/modelix/values.yaml | 10 +++++++ versions.properties | 2 +- 8 files changed, 62 insertions(+), 4 deletions(-) create mode 100644 helm/modelix/templates/common/docker-registry-secret.yaml diff --git a/helm/modelix/templates/common/docker-registry-deployment.yaml b/helm/modelix/templates/common/docker-registry-deployment.yaml index 72d0f20..8aa1bbe 100644 --- a/helm/modelix/templates/common/docker-registry-deployment.yaml +++ b/helm/modelix/templates/common/docker-registry-deployment.yaml @@ -29,6 +29,13 @@ spec: name: docker-registry ports: - containerPort: 5000 + env: + - name: REGISTRY_AUTH + value: "htpasswd" + - name: REGISTRY_AUTH_HTPASSWD_REALM + value: "Registry Realm" + - name: REGISTRY_AUTH_HTPASSWD_PATH + value: "/auth/htpasswd" resources: requests: memory: "800Mi" @@ -36,5 +43,16 @@ spec: limits: memory: "800Mi" cpu: "1.0" + volumeMounts: + - name: "docker-registry-secret" + mountPath: "/auth" + readOnly: true + volumes: + - name: "docker-registry-secret" + secret: + secretName: "{{ include "modelix.fullname" . }}-docker-registry-secret" + items: + - key: htpasswd + path: htpasswd restartPolicy: Always {{- include "modelix.pullSecret" . | nindent 6 }} diff --git a/helm/modelix/templates/common/docker-registry-secret.yaml b/helm/modelix/templates/common/docker-registry-secret.yaml new file mode 100644 index 0000000..33b4a50 --- /dev/null +++ b/helm/modelix/templates/common/docker-registry-secret.yaml @@ -0,0 +1,26 @@ +apiVersion: v1 +kind: Secret +metadata: + name: "{{ include "modelix.fullname" . }}-docker-registry-secret" + labels: + component: docker-registry + {{- include "modelix.labels" . | nindent 4 }} +type: kubernetes.io/dockerconfigjson +data: + {{- $username := "docker-registry-user" }} + # retrieve the secret data using lookup function and when not exists, return an empty dictionary / map as result + {{- $secretObj := (lookup "v1" "Secret" .Release.Namespace (printf "%s%s" ( include "modelix.fullname" . ) "-docker-registry-secret")) | default dict }} + {{- $secretData := (get $secretObj "data") | default dict }} + {{- $password := (get $secretData "password" | b64dec ) | default (randAlphaNum 64) }} + username: {{ $username | b64enc | quote }} + password: {{ $password | b64enc | quote }} + htpasswd: {{ (htpasswd $username $password) | b64enc | quote }} + {{- $authValue := printf "%s:%s" $username $password | b64enc }} + # Kubernetes accesses the internal registry through the static node port exposed at localhost. + # The secrete used in `imagePullSecretes` needs to use this local address. + {{- $registryLocal := printf "%s:%.0f" "localhost" .Values.internalDockerRegistry.nodePort }} + .dockerconfigjson: {{ (printf "%s%s%s%s%s" "{ \"auths\": { \"" $registryLocal "\": {\"auth\": \"" $authValue "\"}}}") | b64enc | quote }} + # Pods access a the registry by its service name. + # They need an auth the uses the service name. + {{- $registryServiceName := printf "%s%s" ( include "modelix.fullname" . ) "-docker-registry"}} + .dockerconfigjsonUsingServiceName: {{ (printf "%s%s%s%s%s" "{ \"auths\": { \"" $registryServiceName ":5000\": {\"auth\": \"" $authValue "\"}}}") | b64enc | quote }} diff --git a/helm/modelix/templates/common/docker-registry-service.yaml b/helm/modelix/templates/common/docker-registry-service.yaml index 62f8d93..63cbb31 100644 --- a/helm/modelix/templates/common/docker-registry-service.yaml +++ b/helm/modelix/templates/common/docker-registry-service.yaml @@ -11,6 +11,7 @@ spec: - name: "5000" port: 5000 targetPort: 5000 + nodePort: {{ .Values.internalDockerRegistry.nodePort }} selector: component: docker-registry {{- include "modelix.selectorLabels" . | nindent 4 }} diff --git a/helm/modelix/templates/common/instances-manager-deployment.yaml b/helm/modelix/templates/common/instances-manager-deployment.yaml index 807cc70..8058140 100644 --- a/helm/modelix/templates/common/instances-manager-deployment.yaml +++ b/helm/modelix/templates/common/instances-manager-deployment.yaml @@ -46,8 +46,8 @@ spec: value: http://{{ include "modelix.fullname" . }}-workspace-manager:28104/ - name: WORKSPACE_DOCKER_REGISTRY value: localhost:5000 - - name: DOCKER_REGISTRY_SERVICE_NAME - value: "{{ include "modelix.fullname" . }}-docker-registry" + - name: INTERNAL_DOCKER_REGISTRY_AUTHORITY + value: "localhost:{{ .Values.internalDockerRegistry.nodePort }}" {{- include "modelix.authorizationConfig" . | nindent 10 }} ports: - containerPort: 33332 diff --git a/helm/modelix/templates/common/workspace-client-deployment.yaml b/helm/modelix/templates/common/workspace-client-deployment.yaml index 41dbdfc..f675858 100644 --- a/helm/modelix/templates/common/workspace-client-deployment.yaml +++ b/helm/modelix/templates/common/workspace-client-deployment.yaml @@ -74,5 +74,6 @@ spec: periodSeconds: 20 timeoutSeconds: 10 restartPolicy: Always - {{- include "modelix.pullSecret" . | nindent 6 }} + imagePullSecrets: + - name: "{{ include "modelix.fullname" . }}-docker-registry-secret" {{- end -}} \ No newline at end of file diff --git a/helm/modelix/templates/common/workspace-manager-deployment.yaml b/helm/modelix/templates/common/workspace-manager-deployment.yaml index 51f18d3..d11a75c 100644 --- a/helm/modelix/templates/common/workspace-manager-deployment.yaml +++ b/helm/modelix/templates/common/workspace-manager-deployment.yaml @@ -51,6 +51,8 @@ spec: - name: DOCKER_CONFIG_SECRET_NAME value: "{{ include "modelix.fullname" . }}-docker-secret" {{- end }} + - name: DOCKER_CONFIG_INTERN_REGISTRY_SECRET_NAME + value: "{{ include "modelix.fullname" . }}-docker-registry-secret" {{- include "modelix.authorizationConfig" . | nindent 10 }} image: "{{ .Values.dockerProxy.prefix }}modelix/modelix-workspace-manager:{{ .Values.imageTags.wsManager | default .Values.versions.modelix.workspaces }}" imagePullPolicy: IfNotPresent diff --git a/helm/modelix/values.yaml b/helm/modelix/values.yaml index e5dbff8..5e8230e 100644 --- a/helm/modelix/values.yaml +++ b/helm/modelix/values.yaml @@ -76,6 +76,16 @@ dockerProxy: secret64: "" caCertificate: "" +internalDockerRegistry: + # The internal docker registry does not use HTTPS. + # Kubernetes only allows pulling images from such insecure repositories when they run on localhost. + # Therefore, the internal docker registry is exposed through NodePort on each cluster node. + # The node port on which it is exposed needs + # to be known in advance because we need to specify the address for authentication. + # The node port is configurable to allow + # changing it in deployments where it conflicts with other statically assigned node ports. + nodePort: 30033 + serviceAccount: "" authorization: diff --git a/versions.properties b/versions.properties index 8575929..cc91960 100644 --- a/versions.properties +++ b/versions.properties @@ -1,5 +1,5 @@ # Modelix core version. modelixCoreVersion=10.1.0-pr1190-817f4549 # Modelix Workspaces versions -modelixWorkspacesVersion=0.5.0 +modelixWorkspacesVersion=0.8.0 vncBaseImageVersion=0.8.3