semaphore icon indicating copy to clipboard operation
semaphore copied to clipboard

Kubernetes Installation - setup shifts environment variables if there are special characters in the database password

Open papierkorp opened this issue 1 year ago • 3 comments
trafficstars

So after searching for a whole day :(, I found this bug:

I have a running Kubernetes Cluster (no minikube) and installed a bitnami postgresql helm Chart: helm install semaphore-postgresql bitnami/postgresql --namespace semaphore --create-namespace --set auth.username="semaphore" --set auth.password="G668&ucq" --set auth.database="semaphore" --set auth.postgresPassword="G668&ucq"

After that I created a deployment:

apiVersion: v1
kind: Secret
metadata:
  name: semaphore-secret
  namespace: semaphore
type: Opaque
data:
  SEMAPHORE_ADMIN: YWRtaW4=  # admin
  SEMAPHORE_ADMIN_NAME: YWRtaW4=  # admin
  SEMAPHORE_ADMIN_PASSWORD: dUFjb25USGVtRQ==  # uAconTHemE
  SEMAPHORE_DB_USER: c2VtYXBob3Jl  # semaphore
  SEMAPHORE_DB_PASS: RzY2OCZ1Y3EK  # G668&ucq
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: semaphore
  name: semaphore
  namespace: semaphore
spec:
  replicas: 1
  selector:
    matchLabels:
      app: semaphore
  template:
    metadata:
      labels:
        app: semaphore
    spec:
      containers:
        - name: semaphore
          image: semaphoreui/semaphore:latest
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 3000
          env:
            - name: SEMAPHORE_DB_DIALECT
              value: postgres
            - name: SEMAPHORE_ADMIN
              valueFrom:
                secretKeyRef:
                  name: semaphore-secret
                  key: SEMAPHORE_ADMIN
                  optional: false
            - name: SEMAPHORE_ADMIN_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: semaphore-secret
                  key: SEMAPHORE_ADMIN_PASSWORD
                  optional: false
            - name: SEMAPHORE_ADMIN_NAME
              valueFrom:
                secretKeyRef:
                  name: semaphore-secret
                  key: SEMAPHORE_ADMIN_NAME
                  optional: false
            - name: SEMAPHORE_DB_PASS
              valueFrom:
                secretKeyRef:
                  name: semaphore-secret
                  key: SEMAPHORE_DB_PASS
                  optional: false
            - name: SEMAPHORE_DB_USER
              valueFrom:
                secretKeyRef:
                  name: semaphore-secret
                  key: SEMAPHORE_DB_USER
                  optional: false

            - name: SEMAPHORE_PORT
              value: "3000"

            - name: SEMAPHORE_DB
              value: semaphore  # ?sslmode=disable

            - name: SEMAPHORE_DB_HOST
              value: semaphore-postgresql

            - name: SEMAPHORE_DB_PORT
              value: "5432"

            - name: SEMAPHORE_PLAYBOOK_PATH
              value: /tmp/semaphore

            - name: SEMAPHORE_LDAP_ACTIVATED
              value: this_is_the_value_taken_for_config_output

            - name: SEMAPHORE_ACCESS_KEY_ENCRYPTION
              value: M9OVPDjaFQZViN11Mz2RFx+pXLUhrkYE34fN+lzdJCY=
      restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: semaphore
  name: semaphore
  namespace: semaphore
spec:
  ports:
    - name: "3000"
      port: 3000
      targetPort: 3000
  selector:
    app: semaphore
  type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
#...

and applied my Deployment: kubectl apply -f semaphore.yml

Which finally gave this Log Output:

Attempting to connect to database semaphore on semaphore-postgresql:5432 with user semaphore ...
Generating /tmp/semaphore/config.stdin ...
3
semaphore-postgresql:5432
semaphore
G668&ucq

semaphore
/tmp/semaphore

no
no
no
this_is_the_value_taken_for_config_output
/etc/semaphore
admin
admin@localhost
admin
semaphore

Hello! You will now be guided through a setup to:

1. Set up configuration for a MySQL/MariaDB database
2. Set up a path for your playbooks (auto-created)
3. Run database Migrations
4. Set up initial semaphore user & password

What database to use:
   1 - MySQL
   2 - BoltDB
   3 - PostgreSQL
 (default 1): 
db Hostname (default 127.0.0.1:5432): 
db User (default root): 
db Password: 
db Name (default semaphore): 
Playbook path (default /tmp/semaphore): 
Public URL (optional, example: https://example.com/semaphore): 
Enable email alerts? (yes/no) (default no): 
Enable telegram alerts? (yes/no) (default no): 
Enable slack alerts? (yes/no) (default no): 
Enable LDAP authentication? (yes/no) (default no): 
Config output directory (default /home/semaphore): 
Running: mkdir -p this_is_the_value_taken_for_config_output..
Configuration written to this_is_the_value_taken_for_config_output/config.json..
 Pinging db..
time="2023-12-05T14:02:07Z" level=warning msg="pq: password authentication failed for user \"semaphore\""
panic: pq: password authentication failed for user "semaphore"
	panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x10 pc=0xa831b7]

goroutine 1 [running]:
github.com/ansible-semaphore/semaphore/db/sql.(*SqlDb).Close(0x22fbc60?, {0x278b998?, 0xc0000ccf30?})
	/go/src/github.com/ansible-semaphore/semaphore/db/sql/SqlDb.go:263 +0x17
panic({0xb4c9a0, 0xc00044a000})
	/usr/local/go/src/runtime/panic.go:884 +0x212
github.com/ansible-semaphore/semaphore/db/sql.(*SqlDb).Connect(0xc000012718, {0xc000012018?, 0xc0000cd988?})
	/go/src/github.com/ansible-semaphore/semaphore/db/sql/SqlDb.go:290 +0xb05
github.com/ansible-semaphore/semaphore/cli/cmd.doSetup()
	/go/src/github.com/ansible-semaphore/semaphore/cli/cmd/setup.go:41 +0x17f
github.com/ansible-semaphore/semaphore/cli/cmd.glob..func5(0x274f400?, {0xbf6e8e?, 0x1?, 0x1?})
	/go/src/github.com/ansible-semaphore/semaphore/cli/cmd/setup.go:23 +0x17
github.com/spf13/cobra.(*Command).execute(0x274f400, {0xc00016f230, 0x1, 0x1})
	/go/src/github.com/ansible-semaphore/semaphore/vendor/github.com/spf13/cobra/command.go:860 +0x663
github.com/spf13/cobra.(*Command).ExecuteC(0x274db00)
	/go/src/github.com/ansible-semaphore/semaphore/vendor/github.com/spf13/cobra/command.go:974 +0x3bd
github.com/spf13/cobra.(*Command).Execute(...)
	/go/src/github.com/ansible-semaphore/semaphore/vendor/github.com/spf13/cobra/command.go:902
github.com/ansible-semaphore/semaphore/cli/cmd.Execute()
	/go/src/github.com/ansible-semaphore/semaphore/cli/cmd/root.go:37 +0x5b
main.main()
	/go/src/github.com/ansible-semaphore/semaphore/cli/main.go:8 +0x17

or after commenting SEMAPHORE_LDAP_ACTIVATED out:

Config output directory (default /home/semaphore): 
Running: mkdir -p no..
Configuration written to no/config.json..
 Pinging db..
Running db Migrations..


 > Username:  > Email: 
 Welcome back, admin@localhost! (a user with this username/email is already set up..)

 Re-launch this program pointing to the configuration file

./semaphore server --config no/config.json

 To run as daemon:

nohup ./semaphore server --config no/config.json &

 You can login with admin or /etc/semaphore.
Run Semaphore with semaphore server --config /etc/semaphore/config.json
Loading config
Cannot Find configuration! Use --config parameter to point to a JSON file generated by `semaphore setup`.

So after printing my correct DB Password (as seen in the wrapper: https://github.com/ansible-semaphore/semaphore/blob/develop/deployment/docker/common/semaphore-wrapper) every env Shifts one Position down.

In the end i tested everything with a neutral password:

helm install semaphore-postgresql bitnami/postgresql --namespace semaphore --create-namespace --set auth.username="semaphore" --set auth.password="semaphore" --set auth.database="semaphore" --set auth.postgresPassword="semaphore"
apiVersion: v1
kind: Secret
metadata:
  name: semaphore-secret
  namespace: semaphore
type: Opaque
data:
  SEMAPHORE_ADMIN: YWRtaW4=  # admin
  SEMAPHORE_ADMIN_NAME: YWRtaW4=  # admin
  SEMAPHORE_ADMIN_PASSWORD: c2VtYXBob3Jl  # semaphore
  SEMAPHORE_DB_USER: c2VtYXBob3Jl  # semaphore
  SEMAPHORE_DB_PASS: c2VtYXBob3Jl  # semaphore

and it worked.

I hope this helps someone who made the same mistake as me -.-' or maybe the input can be sanitized?

Markus

papierkorp avatar Dec 05 '23 14:12 papierkorp

I just had the same thing using kubernetes secrets .. In my case \n was base64 encoded into the password i was using and this shifted all the inputs.

I came up with workaround to generate secure passwords:

openssl rand -hex 20 | tr -d '\n' | base64

eg:

---
apiVersion: v1
kind: Secret
metadata:
  name: semaphore-secret
  namespace: semaphore
type: Opaque
data:
  # openssl rand -hex 20 | tr -d '\n' | base64
  MYSQL_PASSWORD: ZjgyNmEzYjIxYWE4NjdkN2E0MGM3OGNmZDcwYWE3NWU5OTc2NjZhOQ==
  SEMAPHORE_ADMIN_PASSWORD: NjJhY2E0NmYxNDJlZmFmNTU3OTA0NzM2MWYwOWM5YTAwNTkwZjBhNg==

GeoffWilliams avatar Feb 09 '24 03:02 GeoffWilliams

My helm chart https://artifacthub.io/packages/helm/cloudhippie/ansible-semaphore wouldn't have this issue since the installer gets skipped because of all the used environment variables :)

tboerger avatar Feb 09 '24 06:02 tboerger

the exact moment i get it all working :joy: ... I saw a few helm charts, not sure if this was one of em. Normally skip the "unofficial" ones. The pipping answers into setup looked off to me as well - was about to just start writing a config file myself in the container but gave this one more go! Maybe yours can be adopted ;-)

GeoffWilliams avatar Feb 09 '24 06:02 GeoffWilliams