Secret is not decoding properly using Kubernetes Secrets - kubernetes

I am using Kubernetes to deploy my grafana dashboard and I am trying to use Kubernetes Secrets for saving grafana admin-password .. Here is my yaml file for secret
apiVersion: v1
kind: Secret
metadata:
name: $APP_INSTANCE_NAME-grafana
labels:
app.kubernetes.io/name: $APP_INSTANCE_NAME
app.kubernetes.io/component: grafana
type: Opaque
data:
# By default, admin-user is set to `admin`
admin-user: YWRtaW4=
admin-password: "$GRAFANA_GENERATED_PASSWORD"
value for GRAFANA_GENERATED_PASSWORD is base64 encoded and exported like
export GRAFANA_GENERATED_PASSWORD="$(echo -n $PASSWORD | base64)"
where PASSWORD is a variable which i exported on my machine like
export PASSWORD=qwerty123
I am trying to pass the value of GRAFANA_GENERATED_PASSWORD to the yaml file for secret like
envsubst '$GRAFANA_GENERATED_PASSWORD' > "grafana_secret.yaml"
The yaml file after passing the base64 encoded value looks like
apiVersion: v1
kind: Secret
metadata:
name: kafka-monitor-grafana
labels:
app.kubernetes.io/name: kafka-monitor
app.kubernetes.io/component: grafana
type: Opaque
data:
# By default, admin-user is set to `admin`
admin-user: YWRtaW4=
admin-password: "cXdlcnR5MTIz"
After deploying all my objects i couldn't login to my dashboard using password qwerty123 which is encoded properly ..
But when i try to encode my password like
export GRAFANA_GENERATED_PASSWORD="$(echo -n 'qwerty123' | base64)"
It is working properly and i can login to my dashboard using the password qwerty123 ..
Looks like the problem occur when i encode my password using a variable ...
But i have encode my password using a variable

As mentioned in #Pratheesh comment, after deploy the grafana for the first time, the persistent volume was not deleted/recreated and the file grafana.db that contains the Grafana dashboard password still keeping the old password.
In order to solve, the PersistentVolume (pv) need to be deleted before apply the secret with the new password.

Related

How to create kubernetes secret with multiple values for one key?

This is how I'm trying to create a secret for my kubernetes mongodb, which gets deployed using the bitnami mongodb helm chart:
apiVersion: v1
kind: Secret
metadata:
name: mongodb-secret
namespace: mongodb
labels:
app.kubernetes.io/component: mongodb
type: Opaque
data:
mongodb-root-password: 'encoded value'
mongodb-passwords: '???'
mongodb-metrics-password: 'encoded value'
mongodb-replica-set-key: 'encoded value'
The helm chart values.yaml says:
auth:
## MongoDB(®) custom users and databases
## ref: https://github.com/bitnami/containers/tree/main/bitnami/mongodb#creating-a-user-and-database-on-first-run
## #param auth.usernames List of custom users to be created during the initialization
## #param auth.passwords List of passwords for the custom users set at `auth.usernames`
## #param auth.databases List of custom databases to be created during the initialization
##
usernames: []
passwords: []
databases: []
## #param auth.existingSecret Existing secret with MongoDB(®) credentials (keys: `mongodb-passwords`, `mongodb-root-password`, `mongodb-metrics-password`, ` mongodb-replica-set-key`)
## NOTE: When it's set the previous parameters are ignored.
##
existingSecret: ""
So passwords is an array of strings for each username and each database.
How do I have to implement these multiple passwords in my secret?
The helm template should give me a hint, but I don't understand it: secret.yaml
Or is it a simple string with all passwords separated by , and encoded?
Should be something like:
auth:
usernames: ["bob", "alice"]
passwords: ["bobpass", "alicepass"]
databases: ["bobdb", "alicedb"]
If you want to pass those on the cli --set flag instead, you should be able to use curly braces as per this comment: https://github.com/helm/helm/issues/1987#issuecomment-280497496 - like:
--set auth.usernames={bob,alice},auth.passwords={bobpass,alicepass},auth.databases={bobdb,alicedb}
This would produce a secret like following - which you can check with helm template command:
---
# Source: mongodb/templates/secrets.yaml
apiVersion: v1
kind: Secret
metadata:
name: release-name-mongodb
namespace: default
labels:
app.kubernetes.io/name: mongodb
helm.sh/chart: mongodb-13.4.4
app.kubernetes.io/instance: release-name
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/component: mongodb
type: Opaque
data:
mongodb-root-password: "Uk1tZThhYzNFZg=="
mongodb-passwords: "Ym9icGFzcyxhbGljZXBhc3M="
---
You can decode mongodb-passwords, using:
echo -n Ym9icGFzcyxhbGljZXBhc3M= | base64 -d
and notice that it looks as following: bobpass,alicepass
Also note that there seems to be an option to have mongodb.createSecret flag set to false and creating that secret manually (which may be more secure depending on the exact workflow).

RabbitMQ Kubernetes Operator - Set Username and Password with Secret

I am using the RabbitMQ Kubernetes operator for a dev-instance and it works great. What isn't great is that the credentials generated by the operator are different for everyone on the team (I'm guessing it generates random creds upon init).
Is there a way to provide a secret and have the operator use those credentials in place of the generated ones?
Yaml:
apiVersion: rabbitmq.com/v1beta1
kind: RabbitmqCluster
metadata:
name: rabbitmq-cluster-deployment
namespace: message-brokers
spec:
replicas: 1
service:
type: LoadBalancer
Ideally, I can just configure some yaml to point to a secret and go from there. But, struggling to find the documentation around this piece.
Example Username/Password generated:
user: default_user_wNSgVBIyMIElsGRrpwb
pass: cGvQ6T-5gRt0Rc4C3AdXdXDB43NRS6FJ
I figured it out. Looks like you can just add a secret configured like the below example and it'll work. I figured this out by reverse engineering what the operator generated. So, please chime in if this is bad.
The big thing to remember is the default_user.confg setting. Other than that, it's just a secret.
kind: Secret
apiVersion: v1
metadata:
name: rabbitmq-cluster-deployment-default-user
namespace: message-brokers
stringData:
default_user.conf: |
default_user = user123
default_pass = password123
password: password123
username: user123
type: Opaque
rabbitmq-cluster-deployment-default-user comes from the Deployment mdatadata.name + -default-user (see yaml in question)

Removed k8s secret's data persists after updates

I have a k8s secret yaml definition with some data items already applied in the cluster. After removing some data items from the yaml file, and updating the secret with kubectl apply, those removed data items still persists in the secret object existing in the k8s cluster, not being able to remove them without deleting and recreating the secret from scratch. However, this is not the usual behavior and only happens on rare occasions. Any idea why this is happening and how can I fix it without deleting the whole secret?
Example:
$ cat <<EOF|kubectl apply -f -
apiVersion: v1
kind: Secret
metadata:
name: db-credentials-secret
namespace: default
type: Opaque
stringData:
user: foo
password: bar
EOF
The secret is created with data items user and password.
$ cat <<EOF|kubectl apply -f -
apiVersion: v1
kind: Secret
metadata:
name: db-credentials-secret
namespace: default
type: Opaque
stringData:
password: bar
EOF
After removing user from the secret definition, the secret is updated with kubectl apply but the user data item still remains in the secret.

How to deploy a secret resource?

I am new to Kubernetes, and trying to wrap my head around how to set secrets. I will try to illustrate with an example. Let's say I have a secret resource that looks like:
apiVersion: v1
kind: Secret
metadata:
name: big-secrets
type: Opaque
data:
secret-password: "secretMeow"
secret-key: "angryWoof"
database-password: "happyWhale"
How do I set up (not sure if set up is the right word here) these secrets using kubectl, and how do I retrieve them? I have tried reading through the following documentation but I am still not sure how to set up from a yaml file as mentioned above.
Using stringData it is possible to create a secret using plain text values:
apiVersion: v1
kind: Secret
metadata:
name: big-secrets
type: Opaque
stringData:
secret-password: "secretMeow"
secret-key: "angryWoof"
database-password: "happyWhale"
However it's worth noting it's provided more for convenience and the docs say:
It is provided as a write-only convenience method. All keys and values are merged into the data field on write, overwriting any existing values. It is never output when reading from the API.
For the question of how to read the secret, if you wanted it programatically, you could use a tool like jq to parse the Kubernetes output and base64 decode:
kubectl get secret big-secrets -o json | jq -r '.data["secret-password"] | #base64d'
This would get the created secret as JSON (-o yaml is also an option), read the data field for a given secret (secret-password in this case) and then base64 decode it.
Using yaml file you cannot create secret without encoded string value. Secret data value must be in base64 encoded in yaml file. If you want to create a secret from yaml file then you need to decode data value like below.
apiVersion: v1
kind: Secret
metadata:
name: big-secrets
type: Opaque
data:
secret-password: c2VjcmV0TWVvdwo=
secret-key: YW5ncnlXb29mCg==
database-password: aGFwcHlXaGFsZQo=
Or
You can use kubectl imperative command to create a secret from literal values like below.
kubectl create secret generic big-secrets --from-literal=secret-password="secretMeow" --from-literal=secret-key="angryWoof"

How to Kubernetes Secret from parameter stored in the AWS System manager

I would like to avoid keeping secret in the Git as a best practise, and store it in AWS SSM.
Is there any way to get the value from AWS System Manager and use to create Kubernetes Secret?
I manage to create secret by fetching value from AWS Parameter store using the following script.
cat <<EOF | ./kubectl apply -f -
apiVersion: v1
kind: Secret
metadata:
name: kiali
namespace: istio-system
type: Opaque
data:
passphrase: $(echo -n "`aws ssm get-parameter --name /dev/${env_name}/kubernetes/kiali_password --with-decrypt --region=eu-west-2 --output text --query Parameter.Value`" | base64 -w0)
username: $(echo -n "admin" | base64 -w0)
EOF
For sure, 12factors requires to externalize configuration outside Codebase.
For your question, there is an attempt to integrate AWS SSM (AWS Secret Manager) to be used as the single source of truth for Secrets.
You just need to deploy the controller :
helm repo add secret-inject https://aws-samples.github.io/aws-secret-sidecar-injector/
helm repo update
helm install secret-inject secret-inject/secret-inject
Then annotate your deployment template with 2 annotations:
template:
metadata:
annotations:
secrets.k8s.aws/sidecarInjectorWebhook: enabled
secrets.k8s.aws/secret-arn: arn:aws:secretsmanager:us-east-1:123456789012:secret:database-password-hlRvvF
Other steps are explained here.
But I think that I highlighted the most important steps which clarifies the approach.
You can use GoDaddy external secrets. Installing it, creates a controller, and the controller will sync the AWS secrets within specific intervals. After creating the secrets in AWS SSM and installing GoDaddy external secrets, you have to create an ExternalSecret type as follows:
apiVersion: 'kubernetes-client.io/v1'
kind: ExtrenalSecret
metadata:
name: cats-and-dogs
secretDescriptor:
backendType: secretsManager
data:
- key: cats-and-dogs/mysql-password
name: password`
This will create a Kubernetes secrets for you. That secret can be exposed to your service as an environment variable or through volume mount.
Use Kubernetes External Secret. This below solution uses Secret Manager (not SSM) but servers the purpose.
Deploy using Helm
$ `helm repo add external-secrets https://external-secrets.github.io/kubernetes-external-secrets/`
$ `helm install kubernetes-external-secrets external-secrets/kubernetes-external-secrets`
Create new secret with required parameter in AWS Secret Manager:
For example - create a secret with secret name as "dev/db-cred" with below values.
{"username":"user01","password":"pwd#123"}
Secret.YAML:
apiVersion: kubernetes-client.io/v1
kind: ExternalSecret
metadata:
name: my-kube-secret
namespace: my-namespace
spec:
backendType: secretsManager
region: us-east-1
dataFrom:
- dev/db-cred
Refer it in helm values file as below
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: my-kube-secret
key: password