Skip to content

Commit 379fac4

Browse files
authored
Merge pull request #120 from cloudymax/password-fix
Fix issues with random passwords when username is templated via env var
2 parents d11a818 + 9e3b5ba commit 379fac4

File tree

7 files changed

+52
-30
lines changed

7 files changed

+52
-30
lines changed

charts/cloud-init/Chart.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ apiVersion: v2
22
name: cloud-init
33
description: A Helm chart that generates cloud-init config files
44
type: application
5-
version: 0.5.0
5+
version: 0.5.1
66
maintainers:
77
- name: cloudymax

charts/cloud-init/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# cloud-init
22

3-
![Version: 0.5.0](https://img.shields.io/badge/Version-0.5.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square)
3+
![Version: 0.5.1](https://img.shields.io/badge/Version-0.5.1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square)
44

55
A Helm chart that generates cloud-init config files
66

@@ -28,7 +28,7 @@ A Helm chart that generates cloud-init config files
2828
| extraEnvVars[1].value | string | `"b8:a3:86:70:cc:e6"` | |
2929
| fs_setup | list | `[]` | |
3030
| hostname | string | `"random"` | virtual-machine hostname |
31-
| image | string | `"deserializeme/kv-cloud-init:v0.0.1"` | image version |
31+
| image | string | `"deserializeme/kv-cloud-init:v0.0.2"` | image version |
3232
| mounts | list | `[]` | Set up mount points. mounts contains a list of lists. The inner list contains entries for an /etc/fstab line |
3333
| namespace | string | `"default"` | namespace in which to create resources |
3434
| network | object | `{"config":"disabled"}` | networking options |
@@ -44,7 +44,7 @@ A Helm chart that generates cloud-init config files
4444
| secret_name | string | `"max-scrapmetal-user-data"` | name of secret in which to save the user-data file |
4545
| serviceAccount | object | `{"create":true,"existingServiceAccountName":"cloud-init-sa","name":"cloud-init-sa"}` | Choose weather to create a service-account or not. Once a SA has been created you should set this to false on subsequent runs. |
4646
| swap | object | `{"enabled":false,"filename":"/swapfile","maxsize":"1G","size":"1G"}` | creates a swap file using human-readable values. |
47-
| users | list | `[{"groups":"users, admin, docker, sudo, kvm","lock_passwd":false,"name":"pool","password":{"random":true},"shell":"/bin/bash","ssh_authorized_keys":[],"ssh_import_id":[],"sudo":"ALL=(ALL) NOPASSWD:ALL"}]` | user configuration options See https://cloudinit.readthedocs.io/en/latest/reference/modules.html#users-and-groups do NOT use 'admin' as username - it conflicts with multiele cloud-images |
47+
| users | list | `[{"groups":"users, admin, docker, sudo, kvm","lock_passwd":false,"name":"$USERNAME","password":{"random":true},"shell":"/bin/bash","ssh_authorized_keys":[],"ssh_import_id":[],"sudo":"ALL=(ALL) NOPASSWD:ALL"}]` | user configuration options See https://cloudinit.readthedocs.io/en/latest/reference/modules.html#users-and-groups do NOT use 'admin' as username - it conflicts with multiele cloud-images |
4848
| users[0].password | object | `{"random":true}` | set user password from existing secret or generate random |
4949
| users[0].ssh_authorized_keys | list | `[]` | provider user ssh pub key as plaintext |
5050
| users[0].ssh_import_id | list | `[]` | import user ssh public keys from github, gitlab, or launchpad See https://cloudinit.readthedocs.io/en/latest/reference/modules.html#ssh |

charts/cloud-init/scripts/optimize.sh

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,38 @@ run_envsubst(){
4141
fi
4242
}
4343

44+
# Create a random password and save it as a kubernetes secret. Must be run after
45+
# envsubst to avoid issues where no username is present
46+
random_password(){
47+
log "Generating a random password for ${USERNAME}."
48+
INPUT=$(golang-petname --words 2)
49+
OUTPUT=""
50+
LENGTH=${#INPUT}
51+
52+
for (( i=0; i<LENGTH; i++ )); do
53+
char="${INPUT:$i:1}"
54+
if (( RANDOM % 2 == 0 )); then
55+
# Convert to uppercase
56+
OUTPUT+="$(echo "$char" | tr '[:lower:]' '[:upper:]')"
57+
else
58+
# Convert to lowercase
59+
OUTPUT+="$(echo "$char" | tr '[:upper:]' '[:lower:]')"
60+
fi
61+
done
62+
63+
export GENERATED_PASSWORD="$OUTPUT-$RANDOM"
64+
65+
export SECRET_EXISTS=$(kubectl get secret ${USERNAME}-password -o yaml |grep -o ${USERNAME}-password |wc -l)
66+
67+
if [ "${SECRET_EXISTS}" -gt 0 ]; then
68+
log "Kubernetes secret ${USERNAME}-password exists and will be replaced"
69+
kubectl patch secret ${USERNAME}-password -p '{"metadata":{"finalizers":null}}' --type=merge
70+
kubectl delete secret ${USERNAME}-password
71+
kubectl create secret generic ${USERNAME}-password --from-literal=password="$GENERATED_PASSWORD"
72+
fi
73+
74+
}
75+
4476
# Hash and insert passwd field for each specified user
4577
admin_password(){
4678
read -ra users <<< $(yq '.users[].name' $USER_DATA_PATH |xargs)
@@ -50,8 +82,16 @@ admin_password(){
5082
CHECK=$(yq '.users[env(COUNT)].passwd' $USER_DATA_PATH)
5183
if [ "${CHECK}" != "null" ]; then
5284
log "Setting hashed password for user: $user\n"
85+
5386
CAP_USER=$(echo "${user}" | tr '[:lower:]' '[:upper:]')
54-
PASSWORD=$(env |grep "${CAP_USER}_PASSWORD" |cut -d '=' -f2)
87+
88+
if [ ${RANDOM_PASSWORD} == "true" ]; then
89+
random_password
90+
export PASSWORD=$GENERATED_PASSWORD
91+
else
92+
export PASSWORD=$(env |grep "${CAP_USER}_PASSWORD" |cut -d '=' -f2)
93+
fi
94+
5595
export HASHED_PASSWORD=$(mkpasswd --method=SHA-512 --rounds=4096 "${PASSWORD}" -s "${SALT}")
5696
yq -i '.users[env(COUNT)].passwd = env(HASHED_PASSWORD)' $USER_DATA_PATH
5797
fi
@@ -116,7 +156,6 @@ create_secret(){
116156
kubectl delete secret ${SECRET_NAME}
117157
fi
118158

119-
120159
if [ "$NETWORK_DATA_PRESENT" == "true" ]; then
121160
log "Creating kubernetes secret ${SECRET_NAME} from ${USER_DATA_PATH} & ${NETWORK_DATA_PATH}"
122161
kubectl create secret generic ${SECRET_NAME} \
@@ -127,12 +166,15 @@ create_secret(){
127166
kubectl create secret generic ${SECRET_NAME} --from-file=userdata="${USER_DATA_PATH}"
128167
fi
129168

169+
log "Adding argocd tracking annotation."
130170
kubectl annotate --overwrite secret ${SECRET_NAME} \
131171
argocd.argoproj.io/tracking-id="${ARGOCD_APP_NAME}:v1/Secret:${NAMESPACE}/${SECRET_NAME}"
132172

173+
log "Adding argocd sync options."
133174
kubectl annotate --overwrite secret ${SECRET_NAME} \
134175
argocd.argoproj.io/sync-options="Prune=false,Delete=false"
135176

177+
log "Adding argocd comparison options."
136178
kubectl annotate --overwrite secret ${SECRET_NAME} \
137179
argocd.argoproj.io/compare-options="IgnoreExtraneous"
138180

charts/cloud-init/templates/cluster-role-binding.yaml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@ kind: ClusterRoleBinding
33
apiVersion: rbac.authorization.k8s.io/v1
44
metadata:
55
name: cloud-init
6-
annotations:
7-
"helm.sh/hook": pre-install
8-
"helm.sh/hook-weight": "-1"
96
subjects:
107
- kind: ServiceAccount
118
name: {{ .Values.serviceAccount.name}}

charts/cloud-init/templates/job.yaml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,8 @@ spec:
4444
key: {{ $props.password.existingSecret.key }}
4545
{{- end }}
4646
{{- if $props.password.random }}
47-
- name: {{ upper $props.name }}_PASSWORD
48-
valueFrom:
49-
secretKeyRef:
50-
name: {{ $props.name }}-password
51-
key: password
47+
- name: RANDOM_PASSWORD
48+
value: "true"
5249
{{- end }}
5350
{{- end }}
5451
{{- with .Values.extraEnvVars }}

charts/cloud-init/templates/password-secret.yaml

Lines changed: 0 additions & 14 deletions
This file was deleted.

charts/cloud-init/values.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ argocdAppName: cloud-init-test
88
secret_name: max-scrapmetal-user-data
99

1010
# -- image version
11-
image: deserializeme/kv-cloud-init:v0.0.1
11+
image: deserializeme/kv-cloud-init:v0.0.2
1212

1313
# -- Choose weather to create a service-account or not. Once a SA has been created
1414
# you should set this to false on subsequent runs.
@@ -106,7 +106,7 @@ wireguard: []
106106
# See https://cloudinit.readthedocs.io/en/latest/reference/modules.html#users-and-groups
107107
# do NOT use 'admin' as username - it conflicts with multiele cloud-images
108108
users:
109-
- name: pool
109+
- name: $USERNAME
110110
groups: users, admin, docker, sudo, kvm
111111
sudo: ALL=(ALL) NOPASSWD:ALL
112112
shell: /bin/bash

0 commit comments

Comments
 (0)