From a0e9625b120681be064d849158df9030b185c287 Mon Sep 17 00:00:00 2001 From: Mihail Radkov Date: Wed, 8 May 2024 14:52:33 +0300 Subject: [PATCH] Updated the provisioning user - Moved `provisioningUsername` and `provisioningPassword` under `security.provisioner` - Added `security.provisioner.existingSecret` and `security.provisioner.tokenKey` to provide an existing authentication token - Small bash script cleaning --- CHANGELOG.md | 2 ++ files/config/users.js | 6 ++--- files/scripts/graphdb.sh | 21 ++++++++-------- files/scripts/update-cluster.sh | 25 ++++++++----------- templates/jobs/_labels.tpl | 4 +-- templates/jobs/job-create-cluster.yaml | 8 +++--- templates/jobs/job-patch-cluster.yaml | 8 +++--- .../jobs/job-provision-repositories.yaml | 8 +++--- templates/jobs/job-scale-down-cluster.yaml | 8 +++--- templates/jobs/job-scale-up-cluster.yaml | 8 +++--- templates/jobs/secret-provision-user.yaml | 8 +++--- values.yaml | 19 ++++++++------ 12 files changed, 69 insertions(+), 56 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 49b4c0a8..800dd2b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,7 @@ TODO: decide how detailed we want this to be - Removed configuration overrides from the default `GDB_JAVA_OPTS`: `enable-context-index`, `entity-pool-implementation` and `health.max.query.time.seconds` - Removed `default.min.distinct.threshold` from the default `defaultJavaArguments` values +- Moved `provisioningUsername` and `provisioningPassword` under `security.provisioner` ### New @@ -110,6 +111,7 @@ TODO: decide how detailed we want this to be - Added `jobs.backoffLimit` for configuring the retry count for all jobs - Added `jobs.ttlSecondsAfterFinished` for configuring the time in seconds for all jobs before deleting finished pods - Added `jobs.persistence.emptyDir` configurations for the default temporary storage for all jobs +- Added `security.provisioner.existingSecret` and `security.provisioner.tokenKey` to provide an existing authentication token ### Updates diff --git a/files/config/users.js b/files/config/users.js index 12072650..2afa9685 100644 --- a/files/config/users.js +++ b/files/config/users.js @@ -13,9 +13,9 @@ }, "dateCreated" : 1618403171751 }, - "{{ .Values.security.provisioningUsername }}" : { - "username" : "{{ .Values.security.provisioningUsername }}", - "password" : "{bcrypt}{{ htpasswd .Values.security.provisioningUsername .Values.security.provisioningPassword | trimPrefix (printf "%s:" .Values.security.provisioningUsername) }}", + "{{ .Values.security.provisioner.username }}" : { + "username" : "{{ .Values.security.provisioner.username }}", + "password" : "{bcrypt}{{ htpasswd .Values.security.provisioner.username .Values.security.provisioner.password | trimPrefix (printf "%s:" .Values.security.provisioner.username) }}", "grantedAuthorities" : [ "ROLE_ADMIN" ], "appSettings" : { "DEFAULT_INFERENCE" : true, diff --git a/files/scripts/graphdb.sh b/files/scripts/graphdb.sh index 9960c911..ed4afded 100755 --- a/files/scripts/graphdb.sh +++ b/files/scripts/graphdb.sh @@ -1,17 +1,18 @@ #!/usr/bin/env bash -set -eu +set -o errexit +set -o nounset +set -o pipefail function createCluster { waitAllNodes $1 local configLocation=$2 - local authToken=$PROVISION_USER_AUTH_TOKEN local timeout=$3 echo "Creating cluster" - curl -o response.json -isSL -m $timeout -X POST \ + curl -o response.json -isSL -m "${timeout}" -X POST \ -d @"$configLocation" \ - --header "Authorization: Basic ${authToken}" \ + --header "Authorization: Basic ${GRAPHDB_AUTH_TOKEN}" \ --header 'Content-Type: application/json' \ --header 'Accept: */*' \ "http://${GRAPHDB_POD_NAME}-0.${GRAPHDB_SERVICE_NAME}:${GRAPHDB_SERVICE_PORT}/rest/cluster/config" @@ -30,13 +31,12 @@ function createCluster { function waitService { local address=$1 - local authToken=$PROVISION_USER_AUTH_TOKEN local attempt_counter=0 local max_attempts=100 echo "Waiting for ${address}" - until $(curl --output /dev/null -fsSL -m 5 -H "Authorization: Basic ${authToken}" --silent --fail ${address}); do + until curl --output /dev/null -fsSL -m 5 -H "Authorization: Basic ${GRAPHDB_AUTH_TOKEN}" --silent --fail "${address}"; do if [[ ${attempt_counter} -eq ${max_attempts} ]];then echo "Max attempts reached" exit 1 @@ -51,7 +51,7 @@ function waitService { function waitAllNodes { local node_count=$1 - for (( c=$node_count; c>0; c )) + for (( c=node_count; c>0; c )) do c=$((c-1)) waitService "http://${GRAPHDB_POD_NAME}-$c.${GRAPHDB_SERVICE_NAME}:${GRAPHDB_SERVICE_PORT}/rest/repositories" @@ -61,19 +61,18 @@ function waitAllNodes { function createRepositoryFromFile { waitAllNodes $1 local repositoriesConfigsLocation=$2 - local authToken=$PROVISION_USER_AUTH_TOKEN local timeout=60 local success=true echo "Creating repositories" for filename in ${repositoriesConfigsLocation}/*.ttl; do - repositoryName=$(grep "rep:repositoryID" $filename | sed -ne 's/rep:repositoryID "//p' | sed -ne 's/" ;//p' | sed -ne 's/^[[:space:]]*//p') + repositoryName=$(grep "rep:repositoryID" "${filename}" | sed -ne 's/rep:repositoryID "//p' | sed -ne 's/" ;//p' | sed -ne 's/^[[:space:]]*//p') echo "Provisioning repository ${repositoryName}" response=$( curl -X POST --connect-timeout 60 --retry 3 --retry-all-errors --retry-delay 10 \ - -F config=@${filename} \ - -H "Authorization: Basic ${authToken}" \ + -F config=@"${filename}" \ + -H "Authorization: Basic ${GRAPHDB_AUTH_TOKEN}" \ -H 'Content-Type: multipart/form-data' \ "http://${GRAPHDB_POD_NAME}-0.${GRAPHDB_SERVICE_NAME}:${GRAPHDB_SERVICE_PORT}/rest/repositories" ) diff --git a/files/scripts/update-cluster.sh b/files/scripts/update-cluster.sh index a55df57c..fd0400fc 100644 --- a/files/scripts/update-cluster.sh +++ b/files/scripts/update-cluster.sh @@ -1,16 +1,17 @@ #!/usr/bin/env bash -set -eu +set -o errexit +set -o nounset +set -o pipefail function patchCluster { local configLocation=$1 - local authToken=$PROVISION_USER_AUTH_TOKEN local timeout=$2 echo "Patching cluster" waitService "http://${GRAPHDB_PROXY_SERVICE_NAME}:${GRAPHDB_PROXY_SERVICE_PORT}/proxy/ready" curl -o patchResponse.json -isSL -m "$timeout" -X PATCH \ - --header "Authorization: Basic ${authToken}" \ + --header "Authorization: Basic ${GRAPHDB_AUTH_TOKEN}" \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ -d @"$configLocation" \ @@ -30,7 +31,6 @@ function patchCluster { function removeNodes { local expectedNodes=$1 - local authToken=$PROVISION_USER_AUTH_TOKEN local currentNodes=$(getNodeCountInCurrentCluster) local nodes="" # DNS suffix in the form of namespace.svc.cluster.local @@ -66,7 +66,7 @@ function removeNodes { curl -o clusterRemove.json -isSL -m 15 -X DELETE \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ - --header "Authorization: Basic ${authToken}" \ + --header "Authorization: Basic ${GRAPHDB_AUTH_TOKEN}" \ -d "${nodes}" \ "http://${GRAPHDB_PROXY_SERVICE_NAME}:${GRAPHDB_PROXY_SERVICE_PORT}/rest/cluster/config/node" @@ -82,7 +82,6 @@ function removeNodes { function addNodes { local expectedNodes=$1 - local authToken=$PROVISION_USER_AUTH_TOKEN local timeout=$2 local currentNodes=$(getNodeCountInCurrentCluster) local nodes="" @@ -109,10 +108,10 @@ function addNodes { nodes=\{\"nodes\":\[${nodes}\]\} waitService "http://${GRAPHDB_PROXY_SERVICE_NAME}:${GRAPHDB_PROXY_SERVICE_PORT}/proxy/ready" - curl -o clusterAdd.json -isSL -m ${timeout} -X POST \ + curl -o clusterAdd.json -isSL -m "${timeout}" -X POST \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ - --header "Authorization: Basic ${authToken}" \ + --header "Authorization: Basic ${GRAPHDB_AUTH_TOKEN}" \ -d "${nodes}" \ "http://${GRAPHDB_PROXY_SERVICE_NAME}:${GRAPHDB_PROXY_SERVICE_PORT}/rest/cluster/config/node" @@ -133,10 +132,10 @@ function addNodes { } function deleteCluster { - local authToken=$PROVISION_USER_AUTH_TOKEN waitService "http://${GRAPHDB_POD_NAME}-0.${GRAPHDB_SERVICE_NAME}:${GRAPHDB_SERVICE_PORT}/rest/repositories" + curl -o response.json -isSL -m 15 -X DELETE \ - --header "Authorization: Basic ${authToken}" \ + --header "Authorization: Basic ${GRAPHDB_AUTH_TOKEN}" \ --header 'Accept: */*' \ "http://${GRAPHDB_POD_NAME}-0.${GRAPHDB_SERVICE_NAME}:${GRAPHDB_SERVICE_PORT}/rest/cluster/config?force=false" @@ -153,12 +152,11 @@ function deleteCluster { } function getNodeCountInCurrentCluster { - local authToken=$PROVISION_USER_AUTH_TOKEN local node_address="http://${GRAPHDB_POD_NAME}-0.${GRAPHDB_SERVICE_NAME}:${GRAPHDB_SERVICE_PORT}" waitService "${node_address}/rest/repositories" curl -o clusterResponse.json -isSL -m 15 -X GET \ --header 'Content-Type: application/json' \ - --header "Authorization: Basic ${authToken}" \ + --header "Authorization: Basic ${GRAPHDB_AUTH_TOKEN}" \ --header 'Accept: */*' \ "${node_address}/rest/cluster/config" grep -o "${GRAPHDB_SERVICE_NAME}" "clusterResponse.json" | grep -c "" @@ -166,12 +164,11 @@ function getNodeCountInCurrentCluster { function waitService { local address=$1 - local authToken=$PROVISION_USER_AUTH_TOKEN local attempt_counter=0 local max_attempts=100 - until $(curl --output /dev/null -fsSL -m 5 -H "Authorization: Basic ${authToken}" --silent --fail ${address}); do + until curl --output /dev/null -fsSL -m 5 -H "Authorization: Basic ${GRAPHDB_AUTH_TOKEN}" --silent --fail "${address}"; do if [[ ${attempt_counter} -eq ${max_attempts} ]];then echo "Max attempts reached" exit 1 diff --git a/templates/jobs/_labels.tpl b/templates/jobs/_labels.tpl index c668fea3..1f37db49 100644 --- a/templates/jobs/_labels.tpl +++ b/templates/jobs/_labels.tpl @@ -10,8 +10,8 @@ Helper functions for labels related to Job and provisioning resources {{- printf "%s-%s" (include "graphdb.fullname" .) "utils" -}} {{- end -}} -{{- define "graphdb.fullname.secret.provision-user" -}} - {{- printf "%s-%s" (include "graphdb.fullname" .) "provision-user" -}} +{{- define "graphdb.fullname.secret.provisioning-user" -}} + {{- printf "%s-%s" (include "graphdb.fullname" .) "provisioning-user" -}} {{- end -}} {{- define "graphdb.fullname.job.create-cluster" -}} diff --git a/templates/jobs/job-create-cluster.yaml b/templates/jobs/job-create-cluster.yaml index 52322305..91e07675 100644 --- a/templates/jobs/job-create-cluster.yaml +++ b/templates/jobs/job-create-cluster.yaml @@ -46,9 +46,11 @@ spec: value: {{ include "graphdb.fullname.service.headless" . }} - name: GRAPHDB_SERVICE_PORT value: {{ .Values.headlessService.ports.http | quote }} - envFrom: - - secretRef: - name: {{ include "graphdb.fullname.secret.provision-user" . }} + - name: GRAPHDB_AUTH_TOKEN + valueFrom: + secretKeyRef: + name: {{ coalesce .Values.security.provisioner.existingSecret (include "graphdb.fullname.secret.provisioning-user" .) }} + key: {{ .Values.security.provisioner.tokenKey }} securityContext: {{- .Values.jobs.securityContext | toYaml | nindent 12 }} {{- with .Values.jobs.resources }} resources: {{ toYaml . | nindent 12 }} diff --git a/templates/jobs/job-patch-cluster.yaml b/templates/jobs/job-patch-cluster.yaml index 4ca8949d..e0d40edc 100644 --- a/templates/jobs/job-patch-cluster.yaml +++ b/templates/jobs/job-patch-cluster.yaml @@ -50,9 +50,11 @@ spec: value: {{ include "graphdb-proxy.fullname" . }} - name: GRAPHDB_PROXY_SERVICE_PORT value: {{ .Values.proxy.headlessService.ports.http | quote }} - envFrom: - - secretRef: - name: {{ include "graphdb.fullname.secret.provision-user" . }} + - name: GRAPHDB_AUTH_TOKEN + valueFrom: + secretKeyRef: + name: {{ coalesce .Values.security.provisioner.existingSecret (include "graphdb.fullname.secret.provisioning-user" .) }} + key: {{ .Values.security.provisioner.tokenKey }} securityContext: {{- .Values.jobs.securityContext | toYaml | nindent 12 }} {{- with .Values.jobs.resources }} resources: {{ toYaml . | nindent 12 }} diff --git a/templates/jobs/job-provision-repositories.yaml b/templates/jobs/job-provision-repositories.yaml index 67ba8636..06f5a462 100644 --- a/templates/jobs/job-provision-repositories.yaml +++ b/templates/jobs/job-provision-repositories.yaml @@ -46,9 +46,11 @@ spec: value: {{ include "graphdb.fullname.service.headless" . }} - name: GRAPHDB_SERVICE_PORT value: {{ .Values.headlessService.ports.http | quote }} - envFrom: - - secretRef: - name: {{ include "graphdb.fullname.secret.provision-user" . }} + - name: GRAPHDB_AUTH_TOKEN + valueFrom: + secretKeyRef: + name: {{ coalesce .Values.security.provisioner.existingSecret (include "graphdb.fullname.secret.provisioning-user" .) }} + key: {{ .Values.security.provisioner.tokenKey }} securityContext: {{- .Values.jobs.securityContext | toYaml | nindent 12 }} {{- with .Values.jobs.resources }} resources: {{ toYaml . | nindent 12 }} diff --git a/templates/jobs/job-scale-down-cluster.yaml b/templates/jobs/job-scale-down-cluster.yaml index ae42abbe..85ee586c 100644 --- a/templates/jobs/job-scale-down-cluster.yaml +++ b/templates/jobs/job-scale-down-cluster.yaml @@ -48,9 +48,11 @@ spec: value: {{ include "graphdb-proxy.fullname" . }} - name: GRAPHDB_PROXY_SERVICE_PORT value: {{ .Values.proxy.headlessService.ports.http | quote }} - envFrom: - - secretRef: - name: {{ include "graphdb.fullname.secret.provision-user" . }} + - name: GRAPHDB_AUTH_TOKEN + valueFrom: + secretKeyRef: + name: {{ coalesce .Values.security.provisioner.existingSecret (include "graphdb.fullname.secret.provisioning-user" .) }} + key: {{ .Values.security.provisioner.tokenKey }} securityContext: {{- .Values.jobs.securityContext | toYaml | nindent 12 }} {{- with .Values.jobs.resources }} resources: {{ toYaml . | nindent 12 }} diff --git a/templates/jobs/job-scale-up-cluster.yaml b/templates/jobs/job-scale-up-cluster.yaml index a4b0cec6..2e47f334 100644 --- a/templates/jobs/job-scale-up-cluster.yaml +++ b/templates/jobs/job-scale-up-cluster.yaml @@ -49,9 +49,11 @@ spec: value: {{ include "graphdb-proxy.fullname" . }} - name: GRAPHDB_PROXY_SERVICE_PORT value: {{ .Values.proxy.headlessService.ports.http | quote }} - envFrom: - - secretRef: - name: {{ include "graphdb.fullname.secret.provision-user" . }} + - name: GRAPHDB_AUTH_TOKEN + valueFrom: + secretKeyRef: + name: {{ coalesce .Values.security.provisioner.existingSecret (include "graphdb.fullname.secret.provisioning-user" .) }} + key: {{ .Values.security.provisioner.tokenKey }} securityContext: {{- .Values.jobs.securityContext | toYaml | nindent 12 }} {{- with .Values.jobs.resources }} resources: {{ toYaml . | nindent 12 }} diff --git a/templates/jobs/secret-provision-user.yaml b/templates/jobs/secret-provision-user.yaml index d2d9512a..a273382d 100644 --- a/templates/jobs/secret-provision-user.yaml +++ b/templates/jobs/secret-provision-user.yaml @@ -1,8 +1,9 @@ +{{- if not .Values.security.provisioner.existingSecret }} # Secret used from the jobs to authenticate to running GraphDB instances apiVersion: v1 kind: Secret metadata: - name: {{ include "graphdb.fullname.secret.provision-user" . }} + name: {{ include "graphdb.fullname.secret.provisioning-user" . }} namespace: {{ include "graphdb.namespace" . }} labels: {{- include "graphdb.labels" . | nindent 4 }} @@ -16,6 +17,5 @@ metadata: {{- end }} type: Opaque data: - provisioningUsername: {{ .Values.security.provisioningUsername | b64enc | quote }} - provisioningPassword: {{ .Values.security.provisioningPassword | b64enc | quote }} - PROVISION_USER_AUTH_TOKEN: {{ printf "%s:%s" .Values.security.provisioningUsername .Values.security.provisioningPassword | b64enc | b64enc | quote }} + {{ .Values.security.provisioner.tokenKey }}: {{ printf "%s:%s" .Values.security.provisioner.username .Values.security.provisioner.password | b64enc | b64enc | quote }} +{{- end }} diff --git a/values.yaml b/values.yaml index 97c40d7a..20fdb768 100644 --- a/values.yaml +++ b/values.yaml @@ -147,11 +147,16 @@ logging: security: enabled: false - - # If the security is enabled, it's mandatory to have a provisioning user, so the health-checks and cluster linking can work properly - provisioningUsername: provisioner - # bcrypt encrypted password. default: iHaveSuperpowers - provisioningPassword: iHaveSuperpowers + # If the security is enabled, it's mandatory to have a provisioning user, so the cluster provisioning can work properly + provisioner: + # The following user will be created in the default initial users.js and used in the cluster provisioning + username: provisioner + password: iHaveSuperpowers + # Reference to a basic authentication token of an existing user to use for provisioning instead of the default user in the initial user.js + # Note that the user must already exist in GraphDB for this to work properly. + existingSecret: "" + # Field name in the secret holding the authentication token. + tokenKey: GRAPHDB_AUTH_TOKEN ################################## # GraphDB Cluster Configurations # @@ -161,9 +166,9 @@ cluster: # A secret used for secure communication amongst the nodes in the cluster. clusterSecret: s3cr37 # Reference to an existing Secret that contains the cluster secret token. This overrides cluster.clusterSecret - existingClusterSecret: + existingClusterSecret: "" # Key in the existing Secret that holds the secret cluster token for GraphDB - existingClusterSecretKey: + existingClusterSecretKey: "" # Timeout for the cluster creation CURL query. # Note: By default helm waits for Kubernetes commands to complete for 5 minutes. You can increase that by adding "--timeout 10m" to the helm command.