diff --git a/docs/examples/kafka/rotate-auth/kafka-rotate-auth-generated.yaml b/docs/examples/kafka/rotate-auth/kafka-rotate-auth-generated.yaml new file mode 100644 index 0000000000..9aa25568f8 --- /dev/null +++ b/docs/examples/kafka/rotate-auth/kafka-rotate-auth-generated.yaml @@ -0,0 +1,11 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: KafkaOpsRequest +metadata: + name: kfops-rotate-auth-generated + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: kafka-prod + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/examples/kafka/rotate-auth/kafka-rotate-auth-user.yaml b/docs/examples/kafka/rotate-auth/kafka-rotate-auth-user.yaml new file mode 100644 index 0000000000..c9a22bb58e --- /dev/null +++ b/docs/examples/kafka/rotate-auth/kafka-rotate-auth-user.yaml @@ -0,0 +1,14 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: KafkaOpsRequest +metadata: + name: kfops-rotate-auth-user + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: kafka-prod + authentication: + secretRef: + name: kafka-user-auth + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/examples/memcached/rotate-auth/rotate-auth-generated.yaml b/docs/examples/memcached/rotate-auth/rotate-auth-generated.yaml new file mode 100644 index 0000000000..3f8bcd4881 --- /dev/null +++ b/docs/examples/memcached/rotate-auth/rotate-auth-generated.yaml @@ -0,0 +1,11 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: MemcachedOpsRequest +metadata: + name: mcops-rotate-auth-generated + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: memcd-quickstart + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/examples/memcached/rotate-auth/rotate-auth-user.yaml b/docs/examples/memcached/rotate-auth/rotate-auth-user.yaml new file mode 100644 index 0000000000..f71c347c0f --- /dev/null +++ b/docs/examples/memcached/rotate-auth/rotate-auth-user.yaml @@ -0,0 +1,14 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: MemcachedOpsRequest +metadata: + name: mcops-rotate-auth-user + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: memcd-quickstart + authentication: + secretRef: + name: mc-new-auth + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/examples/memcached/rotate-auth/secret.yaml b/docs/examples/memcached/rotate-auth/secret.yaml new file mode 100644 index 0000000000..ced0ef7cfb --- /dev/null +++ b/docs/examples/memcached/rotate-auth/secret.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +data: + authData: dXNlcjpwYXNzCg== +kind: Secret +metadata: + name: mc-new-auth + namespace: demo +type: Opaque \ No newline at end of file diff --git a/docs/examples/mongodb/rotate-auth/rotate-auth-generated.yaml b/docs/examples/mongodb/rotate-auth/rotate-auth-generated.yaml new file mode 100644 index 0000000000..3a712d7a54 --- /dev/null +++ b/docs/examples/mongodb/rotate-auth/rotate-auth-generated.yaml @@ -0,0 +1,11 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: MongoDBOpsRequest +metadata: + name: mgops-rotate-auth-generated + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: mgo-quickstart + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/examples/mongodb/rotate-auth/rotate-auth-user.yaml b/docs/examples/mongodb/rotate-auth/rotate-auth-user.yaml new file mode 100644 index 0000000000..6f02bb1458 --- /dev/null +++ b/docs/examples/mongodb/rotate-auth/rotate-auth-user.yaml @@ -0,0 +1,14 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: MongoDBOpsRequest +metadata: + name: mgops-rotate-auth-user + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: mgo-quickstart + authentication: + secretRef: + name: quick-mg-user-auth + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/examples/mssqlserver/rotate-auth/rotate-auth-generated.yaml b/docs/examples/mssqlserver/rotate-auth/rotate-auth-generated.yaml new file mode 100644 index 0000000000..f8471af943 --- /dev/null +++ b/docs/examples/mssqlserver/rotate-auth/rotate-auth-generated.yaml @@ -0,0 +1,11 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: MSSQLServerOpsRequest +metadata: + name: msops-rotate-auth-generated + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: mssqlserver-quickstart + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/examples/mssqlserver/rotate-auth/rotate-auth-user.yaml b/docs/examples/mssqlserver/rotate-auth/rotate-auth-user.yaml new file mode 100644 index 0000000000..32a4e2f006 --- /dev/null +++ b/docs/examples/mssqlserver/rotate-auth/rotate-auth-user.yaml @@ -0,0 +1,14 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: MSSQLServerOpsRequest +metadata: + name: msops-rotate-auth-user + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: mssqlserver-quickstart + authentication: + secretRef: + name: quick-mssql-user-auth + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/examples/mysql/rotate-auth/rotate-auth-generated.yaml b/docs/examples/mysql/rotate-auth/rotate-auth-generated.yaml new file mode 100644 index 0000000000..8f5985779b --- /dev/null +++ b/docs/examples/mysql/rotate-auth/rotate-auth-generated.yaml @@ -0,0 +1,11 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: MySQLOpsRequest +metadata: + name: myops-rotate-auth-generated + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: mysql-quickstart + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/examples/mysql/rotate-auth/rotate-auth-user.yaml b/docs/examples/mysql/rotate-auth/rotate-auth-user.yaml new file mode 100644 index 0000000000..791567916e --- /dev/null +++ b/docs/examples/mysql/rotate-auth/rotate-auth-user.yaml @@ -0,0 +1,14 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: MySQLOpsRequest +metadata: + name: myops-rotate-auth-user + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: mysql-quickstart + authentication: + secretRef: + name: mysql-quickstart-auth-user + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/examples/pgbouncer/rotateauth/rotateauth.yaml b/docs/examples/pgbouncer/rotateauth/rotateauth.yaml new file mode 100644 index 0000000000..634a3a8d2c --- /dev/null +++ b/docs/examples/pgbouncer/rotateauth/rotateauth.yaml @@ -0,0 +1,11 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: PgBouncerOpsRequest +metadata: + name: pbops-rotate-auth-generated + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: pgbouncer-server + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/examples/pgbouncer/rotateauth/rotateauthuser.yaml b/docs/examples/pgbouncer/rotateauth/rotateauthuser.yaml new file mode 100644 index 0000000000..634b8e9c1e --- /dev/null +++ b/docs/examples/pgbouncer/rotateauth/rotateauthuser.yaml @@ -0,0 +1,14 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: PgBouncerOpsRequest +metadata: + name: pbops-rotate-auth-user + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: pgbouncer-server + authentication: + secretRef: + name: quick-pb-user-auth + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/examples/pgpool/rotateauth/rotateauth.yaml b/docs/examples/pgpool/rotateauth/rotateauth.yaml new file mode 100644 index 0000000000..546caa9b65 --- /dev/null +++ b/docs/examples/pgpool/rotateauth/rotateauth.yaml @@ -0,0 +1,11 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: PgpoolOpsRequest +metadata: + name: pgpops-rotate-auth-generated + namespace: pool +spec: + type: RotateAuth + databaseRef: + name: quick-pgpool + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/examples/pgpool/rotateauth/rotateauthuser.yaml b/docs/examples/pgpool/rotateauth/rotateauthuser.yaml new file mode 100644 index 0000000000..5a2f11495d --- /dev/null +++ b/docs/examples/pgpool/rotateauth/rotateauthuser.yaml @@ -0,0 +1,14 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: PgpoolOpsRequest +metadata: + name: ppops-rotate-auth-user + namespace: pool +spec: + type: RotateAuth + databaseRef: + name: quick-pgpool + authentication: + secretRef: + name: quick-pb-user-auth + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/examples/postgres/rotate-auth/rotate-auth-generated.yaml b/docs/examples/postgres/rotate-auth/rotate-auth-generated.yaml new file mode 100644 index 0000000000..cb52a494b6 --- /dev/null +++ b/docs/examples/postgres/rotate-auth/rotate-auth-generated.yaml @@ -0,0 +1,11 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: PostgresOpsRequest +metadata: + name: pgops-rotate-auth-generated + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: quick-postgres + timeout: 5m + apply: IfReady diff --git a/docs/examples/postgres/rotate-auth/rotate-auth-user.yaml b/docs/examples/postgres/rotate-auth/rotate-auth-user.yaml new file mode 100644 index 0000000000..274bca8332 --- /dev/null +++ b/docs/examples/postgres/rotate-auth/rotate-auth-user.yaml @@ -0,0 +1,14 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: PostgresOpsRequest +metadata: + name: pgops-rotate-auth-user + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: quick-postgres + authentication: + secretRef: + name: quick-postgres-user-auth + timeout: 5m + apply: IfReady diff --git a/docs/examples/rabbitmq/rotate-auth/rotate-auth-generated.yaml b/docs/examples/rabbitmq/rotate-auth/rotate-auth-generated.yaml new file mode 100644 index 0000000000..65f3775889 --- /dev/null +++ b/docs/examples/rabbitmq/rotate-auth/rotate-auth-generated.yaml @@ -0,0 +1,11 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: RabbitMQOpsRequest +metadata: + name: rm-rotate-auth-generated + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: rabbitmq + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/examples/rabbitmq/rotate-auth/rotate-auth-user.yaml b/docs/examples/rabbitmq/rotate-auth/rotate-auth-user.yaml new file mode 100644 index 0000000000..4b96f5a445 --- /dev/null +++ b/docs/examples/rabbitmq/rotate-auth/rotate-auth-user.yaml @@ -0,0 +1,14 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: RabbitMQOpsRequest +metadata: + name: rmops-rotate-auth-user + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: rabbitmq + authentication: + secretRef: + name: rm-auth-user + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/examples/redis/rotate-auth/Redis-rotate-auth-generated.yaml b/docs/examples/redis/rotate-auth/Redis-rotate-auth-generated.yaml new file mode 100644 index 0000000000..4f84204973 --- /dev/null +++ b/docs/examples/redis/rotate-auth/Redis-rotate-auth-generated.yaml @@ -0,0 +1,11 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: RedisOpsRequest +metadata: + name: rdops-rotate-auth-generated + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: redis-quickstart + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/examples/redis/rotate-auth/rotate-auth-user.yaml b/docs/examples/redis/rotate-auth/rotate-auth-user.yaml new file mode 100644 index 0000000000..7457d2baa6 --- /dev/null +++ b/docs/examples/redis/rotate-auth/rotate-auth-user.yaml @@ -0,0 +1,14 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: RedisOpsRequest +metadata: + name: rdops-rotate-auth-user + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: redis-quickstart + authentication: + secretRef: + name: redis-quickstart-user-auth + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/examples/solr/rotateauth/rotateauth.yaml b/docs/examples/solr/rotateauth/rotateauth.yaml new file mode 100644 index 0000000000..83061f86ef --- /dev/null +++ b/docs/examples/solr/rotateauth/rotateauth.yaml @@ -0,0 +1,11 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: SolrOpsRequest +metadata: + name: solrops-rotate-auth-generated + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: solr-combined + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/examples/solr/rotateauth/rotateauthuser.yaml b/docs/examples/solr/rotateauth/rotateauthuser.yaml new file mode 100644 index 0000000000..c2a4de99a0 --- /dev/null +++ b/docs/examples/solr/rotateauth/rotateauthuser.yaml @@ -0,0 +1,14 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: SolrOpsRequest +metadata: + name: solrops-rotate-auth-user + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: solr-combined + authentication: + secretRef: + name: solr-combined-user-auth + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/guides/druid/configuration/podtemplating/index.md b/docs/guides/druid/configuration/podtemplating/index.md index 6b4a64c0de..ae68297d64 100644 --- a/docs/guides/druid/configuration/podtemplating/index.md +++ b/docs/guides/druid/configuration/podtemplating/index.md @@ -440,7 +440,7 @@ Init Containers: /opt/druid/extensions/mysql-metadata-storage from mysql-metadata-storage (rw) /tmp/config/custom-config from custom-config (rw) /tmp/config/operator-config from operator-config-volume (rw) - /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-9t5kp (ro) + /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-9t5kp (rotate-auth) Containers: druid: Container ID: containerd://3a52f120ca09f90fcdc062c94bf404964add7a5b6ded4a372400267a9d0fd598 @@ -468,7 +468,7 @@ Containers: Mounts: /opt/druid/conf from main-config-volume (rw) /opt/druid/extensions/mysql-metadata-storage from mysql-metadata-storage (rw) - /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-9t5kp (ro) + /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-9t5kp (rotate-auth) Conditions: Type Status diff --git a/docs/guides/druid/quickstart/guide/index.md b/docs/guides/druid/quickstart/guide/index.md index 2615f59c59..48fb3a8d7a 100644 --- a/docs/guides/druid/quickstart/guide/index.md +++ b/docs/guides/druid/quickstart/guide/index.md @@ -194,7 +194,7 @@ Here, Let's create the Druid CR that is shown above: ```bash -$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/druid/quickstart/druid-with-monitoring.yaml +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/druid/quickstart/druid-quickstart.yaml druid.kubedb.com/druid-quickstart created ``` diff --git a/docs/guides/druid/rotate-auth/_index.md b/docs/guides/druid/rotate-auth/_index.md new file mode 100644 index 0000000000..8a7f9c2cba --- /dev/null +++ b/docs/guides/druid/rotate-auth/_index.md @@ -0,0 +1,10 @@ +--- +title: Rotate Authentication Druid +menu: + docs_{{ .version }}: + identifier: guides-druid-rotate-auth + name: Rotate Authentication + parent: guides-druid + weight: 135 +menu_name: docs_{{ .version }} +--- \ No newline at end of file diff --git a/docs/guides/druid/rotate-auth/guide.md b/docs/guides/druid/rotate-auth/guide.md new file mode 100644 index 0000000000..37fb7bf55d --- /dev/null +++ b/docs/guides/druid/rotate-auth/guide.md @@ -0,0 +1,606 @@ +--- +title: Rotate Authentication Guide +menu: + docs_{{ .version }}: + identifier: guides-druid-rotate-auth-guide + name: Guide + parent: guides-druid-rotate-auth + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- +# Rotate Authentication of Druid + +**Rotate Authentication** is a feature of the KubeDB Ops-Manager that allows you to rotate a `Druid` user's authentication credentials using a `DruidOpsRequest`. There are two ways to perform this rotation. + +1. **Operator Generated:** The KubeDB operator automatically generates a random credential, updates the existing secret with the new credential. +2. **User Defined:** The user can create their own credentials by defining a Secret of type `kubernetes.io/basic-auth` containing the desired `password`and then reference this secret in the `DruidOpsRequest`. + +## Before You Begin + +- You should be familiar with the following `KubeDB` concepts: + - [Druid](/docs/guides/druid/concepts/druid.md) + - [DruidOpsRequest](/docs/guides/druid/concepts/druidopsrequest.md) + +- At first, you need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Now, install KubeDB cli on your workstation and KubeDB operator in your cluster following the steps [here](/docs/setup/README.md). + +- To keep things isolated, this tutorial uses a separate namespace called `demo` throughout this tutorial. + +```bash + $ kubectl create ns demo + namespace/demo created +``` + +> Note: YAML files used in this tutorial are stored in [docs/examples/druid](https://github.com/kubedb/docs/tree/{{< param "info.version" >}}/docs/examples/druid) folder in GitHub repository [kubedb/docs](https://github.com/kubedb/docs). + +## Deploy Druid + +In this section, we are going to deploy a `Druid` database using `KubeDB`. + +### Create External Dependency (Deep Storage) + +Before proceeding further, we need to prepare deep storage, which is one of the external dependency of Druid and used for storing the segments. It is a storage mechanism that Apache Druid does not provide. **Amazon S3**, **Google Cloud Storage**, or **Azure Blob Storage**, **S3-compatible storage** (like **Minio**), or **HDFS** are generally convenient options for deep storage. + +In this tutorial, we will run a `minio-server` as deep storage in our local `kind` cluster using `minio-operator` and create a bucket named `druid` in it, which the deployed druid database will use. + +```bash + +$ helm repo add minio https://operator.min.io/ +$ helm repo update minio +$ helm upgrade --install --namespace "minio-operator" --create-namespace "minio-operator" minio/operator --set operator.replicaCount=1 + +$ helm upgrade --install --namespace "demo" --create-namespace druid-minio minio/tenant \ +--set tenant.pools[0].servers=1 \ +--set tenant.pools[0].volumesPerServer=1 \ +--set tenant.pools[0].size=1Gi \ +--set tenant.certificate.requestAutoCert=false \ +--set tenant.buckets[0].name="druid" \ +--set tenant.pools[0].name="default" + +``` + +Now we need to create a `Secret` named `deep-storage-config`. It contains the necessary connection information using which the druid database will connect to the deep storage. + +```yaml +apiVersion: v1 +kind: Secret +metadata: + name: deep-storage-config + namespace: demo +stringData: + druid.storage.type: "s3" + druid.storage.bucket: "druid" + druid.storage.baseKey: "druid/segments" + druid.s3.accessKey: "minio" + druid.s3.secretKey: "minio123" + druid.s3.protocol: "http" + druid.s3.enablePathStyleAccess: "true" + druid.s3.endpoint.signingRegion: "us-east-1" + druid.s3.endpoint.url: "http://myminio-hl.demo.svc.cluster.local:9000/" +``` + +Let’s create the `deep-storage-config` Secret shown above: + +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/guides/druid/restart/yamls/deep-storage-config.yaml +secret/deep-storage-config created +``` + +Now, lets go ahead and create a druid database. + +```yaml +apiVersion: kubedb.com/v1alpha2 +kind: Druid +metadata: + name: druid-cluster + namespace: demo +spec: + version: 28.0.1 + deepStorage: + type: s3 + configSecret: + name: deep-storage-config + topology: + routers: + replicas: 1 + deletionPolicy: Delete +``` + +Let's create the `Druid` CR we have shown above, + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/druid/quickstart/druid-quickstart.yaml +druid.kubedb.com/druid-quickstart created +``` +Now, wait until `druid-quickstart` has status Ready. i.e, + +```shell +$ kubectl get druid -n demo +NAME TYPE VERSION STATUS AGE +druid-quickstart kubedb.com/v1alpha2 28.0.1 Ready 5m3s +``` + +## Verify authentication + +````shell +$ kubectl get druid -n demo druid-quickstart -ojson | jq .spec.authSecret.name +"druid-quickstart-auth" +$ kubectl get secret -n demo druid-quickstart-auth -o jsonpath='{.data.username}' | base64 -d +admin⏎ +$ kubectl get secret -n demo druid-quickstart-auth -o jsonpath='{.data.password}' | base64 -d +e4qcqnS.tt_zFQDa⏎ +```` + +## Create RotateAuth DruidOpsRequest + +#### 1. Using operator generated credentials: + +In order to rotate authentication to the Druid using operator generated, we have to create a `DruidOpsRequest` CRO with `RotateAuth` type. Below is the YAML of the `DruidOpsRequest` CRO that we are going to create, +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: DruidOpsRequest +metadata: + name: druidops-rotate-auth-generated + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: druid-quickstart + timeout: 5m + apply: IfReady +``` +Here, + +- `spec.databaseRef.name` specifies that we are performing rotate authentication operation on `druid-quickstart` cluster. +- `spec.type` specifies that we are performing `RotateAuth` on Druid. + +Let's create the `DruidOpsRequest` CR we have shown above, +```shell + $ kubectl apply -f kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/guides/druid/rotate-auth/yamls/Druid-rotate-auth-generated.yaml + Druidopsrequest.ops.kubedb.com/druidops-rotate-auth-generated created +``` +Let's wait for `DruidOpsrequest` to be `Successful`. Run the following command to watch `DruidOpsrequest` CRO +```shell +$ kubectl get Druidopsrequest -n demo +NAME TYPE STATUS AGE +druidops-rotate-auth-generated RotateAuth Successful 6m28s +``` +If we describe the `DruidOpsRequest` we will get an overview of the steps that were followed. +```shell +$ kubectl describe Druidopsrequest -n demo druidops-rotate-auth-generated +Name: druidops-rotate-auth-generated +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: DruidOpsRequest +Metadata: + Creation Timestamp: 2025-07-15T08:41:30Z + Generation: 1 + Resource Version: 730862 + UID: 8e7127b0-5eb5-4f7d-8140-7b2519d6b288 +Spec: + Apply: IfReady + Database Ref: + Name: druid-quickstart + Timeout: 5m + Type: RotateAuth +Status: + Conditions: + Last Transition Time: 2025-07-15T08:41:30Z + Message: Druid ops-request has started to rotate auth for druid nodes + Observed Generation: 1 + Reason: RotateAuth + Status: True + Type: RotateAuth + Last Transition Time: 2025-07-15T08:41:33Z + Message: Successfully generated new credentials + Observed Generation: 1 + Reason: UpdateCredential + Status: True + Type: UpdateCredential + Last Transition Time: 2025-07-15T08:41:34Z + Message: Successfully updated druid credential dynamically + Observed Generation: 1 + Reason: UpdateCredentialDynamically + Status: True + Type: UpdateCredentialDynamically + Last Transition Time: 2025-07-15T08:41:52Z + Message: successfully reconciled the Druid with new configure + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2025-07-15T08:42:47Z + Message: Successfully restarted all nodes + Observed Generation: 1 + Reason: RestartNodes + Status: True + Type: RestartNodes + Last Transition Time: 2025-07-15T08:41:57Z + Message: get pod; ConditionStatus:True; PodName:druid-quickstart-historicals-0 + Observed Generation: 1 + Status: True + Type: GetPod--druid-quickstart-historicals-0 + Last Transition Time: 2025-07-15T08:41:57Z + Message: evict pod; ConditionStatus:True; PodName:druid-quickstart-historicals-0 + Observed Generation: 1 + Status: True + Type: EvictPod--druid-quickstart-historicals-0 + Last Transition Time: 2025-07-15T08:42:02Z + Message: check pod running; ConditionStatus:True; PodName:druid-quickstart-historicals-0 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--druid-quickstart-historicals-0 + Last Transition Time: 2025-07-15T08:42:07Z + Message: get pod; ConditionStatus:True; PodName:druid-quickstart-middlemanagers-0 + Observed Generation: 1 + Status: True + Type: GetPod--druid-quickstart-middlemanagers-0 + Last Transition Time: 2025-07-15T08:42:07Z + Message: evict pod; ConditionStatus:True; PodName:druid-quickstart-middlemanagers-0 + Observed Generation: 1 + Status: True + Type: EvictPod--druid-quickstart-middlemanagers-0 + Last Transition Time: 2025-07-15T08:42:12Z + Message: check pod running; ConditionStatus:True; PodName:druid-quickstart-middlemanagers-0 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--druid-quickstart-middlemanagers-0 + Last Transition Time: 2025-07-15T08:42:17Z + Message: get pod; ConditionStatus:True; PodName:druid-quickstart-brokers-0 + Observed Generation: 1 + Status: True + Type: GetPod--druid-quickstart-brokers-0 + Last Transition Time: 2025-07-15T08:42:17Z + Message: evict pod; ConditionStatus:True; PodName:druid-quickstart-brokers-0 + Observed Generation: 1 + Status: True + Type: EvictPod--druid-quickstart-brokers-0 + Last Transition Time: 2025-07-15T08:42:22Z + Message: check pod running; ConditionStatus:True; PodName:druid-quickstart-brokers-0 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--druid-quickstart-brokers-0 + Last Transition Time: 2025-07-15T08:42:27Z + Message: get pod; ConditionStatus:True; PodName:druid-quickstart-routers-0 + Observed Generation: 1 + Status: True + Type: GetPod--druid-quickstart-routers-0 + Last Transition Time: 2025-07-15T08:42:27Z + Message: evict pod; ConditionStatus:True; PodName:druid-quickstart-routers-0 + Observed Generation: 1 + Status: True + Type: EvictPod--druid-quickstart-routers-0 + Last Transition Time: 2025-07-15T08:42:32Z + Message: check pod running; ConditionStatus:True; PodName:druid-quickstart-routers-0 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--druid-quickstart-routers-0 + Last Transition Time: 2025-07-15T08:42:37Z + Message: get pod; ConditionStatus:True; PodName:druid-quickstart-coordinators-0 + Observed Generation: 1 + Status: True + Type: GetPod--druid-quickstart-coordinators-0 + Last Transition Time: 2025-07-15T08:42:37Z + Message: evict pod; ConditionStatus:True; PodName:druid-quickstart-coordinators-0 + Observed Generation: 1 + Status: True + Type: EvictPod--druid-quickstart-coordinators-0 + Last Transition Time: 2025-07-15T08:42:42Z + Message: check pod running; ConditionStatus:True; PodName:druid-quickstart-coordinators-0 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--druid-quickstart-coordinators-0 + Last Transition Time: 2025-07-15T08:42:47Z + Message: Successfully completed rotate auth opsRequest + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Starting 52m KubeDB Ops-manager Operator Start processing for DruidOpsRequest: demo/druidops-rotate-auth-generated + Normal Starting 52m KubeDB Ops-manager Operator Pausing Druid databse: demo/druid-quickstart + Normal Successful 52m KubeDB Ops-manager Operator Successfully paused Druid database: demo/druid-quickstart for DruidOpsRequest: druidops-rotate-auth-generated + Normal UpdatePetSets 52m KubeDB Ops-manager Operator successfully reconciled the Druid with new configure + Warning get pod; ConditionStatus:True; PodName:druid-quickstart-historicals-0 52m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:druid-quickstart-historicals-0 + Warning evict pod; ConditionStatus:True; PodName:druid-quickstart-historicals-0 52m KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:druid-quickstart-historicals-0 + Warning check pod running; ConditionStatus:True; PodName:druid-quickstart-historicals-0 52m KubeDB Ops-manager Operator check pod running; ConditionStatus:True; PodName:druid-quickstart-historicals-0 + Warning get pod; ConditionStatus:True; PodName:druid-quickstart-middlemanagers-0 52m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:druid-quickstart-middlemanagers-0 + Warning evict pod; ConditionStatus:True; PodName:druid-quickstart-middlemanagers-0 52m KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:druid-quickstart-middlemanagers-0 + Warning check pod running; ConditionStatus:True; PodName:druid-quickstart-middlemanagers-0 52m KubeDB Ops-manager Operator check pod running; ConditionStatus:True; PodName:druid-quickstart-middlemanagers-0 + Warning get pod; ConditionStatus:True; PodName:druid-quickstart-brokers-0 52m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:druid-quickstart-brokers-0 + Warning evict pod; ConditionStatus:True; PodName:druid-quickstart-brokers-0 52m KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:druid-quickstart-brokers-0 + Warning check pod running; ConditionStatus:True; PodName:druid-quickstart-brokers-0 52m KubeDB Ops-manager Operator check pod running; ConditionStatus:True; PodName:druid-quickstart-brokers-0 + Warning get pod; ConditionStatus:True; PodName:druid-quickstart-routers-0 51m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:druid-quickstart-routers-0 + Warning evict pod; ConditionStatus:True; PodName:druid-quickstart-routers-0 51m KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:druid-quickstart-routers-0 + Warning check pod running; ConditionStatus:True; PodName:druid-quickstart-routers-0 51m KubeDB Ops-manager Operator check pod running; ConditionStatus:True; PodName:druid-quickstart-routers-0 + Warning get pod; ConditionStatus:True; PodName:druid-quickstart-coordinators-0 51m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:druid-quickstart-coordinators-0 + Warning evict pod; ConditionStatus:True; PodName:druid-quickstart-coordinators-0 51m KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:druid-quickstart-coordinators-0 + Warning check pod running; ConditionStatus:True; PodName:druid-quickstart-coordinators-0 51m KubeDB Ops-manager Operator check pod running; ConditionStatus:True; PodName:druid-quickstart-coordinators-0 + Normal RestartNodes 51m KubeDB Ops-manager Operator Successfully restarted all nodes + Normal Starting 51m KubeDB Ops-manager Operator Resuming Druid database: demo/druid-quickstart + Normal Successful 51m KubeDB Ops-manager Operator Successfully resumed Druid database: demo/druid-quickstart for DruidOpsRequest: druidops-rotate-auth-generated + +``` +**Verify Auth is rotated** +```shell +$ kubectl get druid -n demo druid-quickstart -ojson | jq .spec.authSecret.name +"druid-quickstart-auth" +$ kubectl get secret -n demo druid-quickstart-auth -o=jsonpath='{.data.username}' | base64 -d +admin⏎ +$ kubectl get secret -n demo druid-quickstart-auth -o=jsonpath='{.data.password}' | base64 -d +gTJJMdgpKy9U(Eqi⏎ +``` +Also, there will be two more new keys in the secret that stores the previous credentials. The keys are `username.prev` and `password.prev`. You can find the secret and its data by running the following command: + +```shell +$ kubectl get secret -n demo druid-quickstart-auth -o go-template='{{ index .data "username.prev" }}' | base64 -d +admin⏎ +$ kubectl get secret -n demo druid-quickstart-auth -o go-template='{{ index .data "password.prev" }}' | base64 -d +e4qcqnS.tt_zFQDa⏎ +``` +The above output shows that the password has been changed successfully. The previous username & password is stored for rollback purpose. +#### 2. Using user created credentials + +At first, we need to create a secret with kubernetes.io/basic-auth type using custom username and password. Below is the command to create a secret with kubernetes.io/basic-auth type, + +> Note: The database `username` is fixed as `admin` and cannot be changed. However, you can update the `password` while keeping the same `username`. +```shell +$ kubectl create secret generic druid-quickstart-auth-user -n demo \ + --type=kubernetes.io/basic-auth \ + --from-literal=username=admin \ + --from-literal=password=testpassword +secret/druid-quickstart-auth-user created +``` +Now create a `DruidOpsRequest` with `RotateAuth` type. Below is the YAML of the `DruidOpsRequest` that we are going to create, + +```shell +apiVersion: ops.kubedb.com/v1alpha1 +kind: DruidOpsRequest +metadata: + name: drops-rotate-auth-user + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: druid-quickstart + authentication: + secretRef: + name: sample-druid-auth-user + timeout: 5m + apply: IfReady +``` +Here, + +- `spec.databaseRef.name` specifies that we are performing rotate authentication operation on `druid-quickstart`cluster. +- `spec.type` specifies that we are performing `RotateAuth` on Druid. +- `spec.authentication.secretRef.name` specifies that we are using `druid-quickstart-auth-user` as `spec.authSecret.name` for authentication. + +Let's create the `DruidOpsRequest` CR we have shown above, + +```shell +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/guides/druid/rotate-auth/yamls/Druid-rotate-auth-user.yaml +Druidopsrequest.ops.kubedb.com/drops-rotate-auth-user created +``` +Let’s wait for `DruidOpsRequest` to be Successful. Run the following command to watch `DruidOpsRequest` CRO: + +```shell +$ kubectl get drops -n demo +NAME TYPE STATUS AGE +drops-rotate-auth-user RotateAuth Successful 5m32s +druidops-rotate-auth-generated RotateAuth Successful 15m + +``` +We can see from the above output that the `DruidOpsRequest` has succeeded. If we describe the `DruidOpsRequest` we will get an overview of the steps that were followed. +```shell +$ kubectl describe Druidopsrequest -n demo drops-rotate-auth-user +Name: drops-rotate-auth-user +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: DruidOpsRequest +Metadata: + Creation Timestamp: 2025-07-15T08:51:11Z + Generation: 1 + Resource Version: 732405 + UID: 1276e361-6585-4502-a744-d9e21c66b86e +Spec: + Apply: IfReady + Authentication: + Secret Ref: + Name: sample-druid-auth-user + Database Ref: + Name: druid-quickstart + Timeout: 5m + Type: RotateAuth +Status: + Conditions: + Last Transition Time: 2025-07-15T08:51:11Z + Message: Druid ops-request has started to rotate auth for druid nodes + Observed Generation: 1 + Reason: RotateAuth + Status: True + Type: RotateAuth + Last Transition Time: 2025-07-15T08:51:11Z + Message: Successfully referenced the user provided authSecret + Observed Generation: 1 + Reason: UpdateCredential + Status: True + Type: UpdateCredential + Last Transition Time: 2025-07-15T08:51:11Z + Message: Successfully updated druid credential dynamically + Observed Generation: 1 + Reason: UpdateCredentialDynamically + Status: True + Type: UpdateCredentialDynamically + Last Transition Time: 2025-07-15T08:51:27Z + Message: successfully reconciled the Druid with new configure + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2025-07-15T08:52:22Z + Message: Successfully restarted all nodes + Observed Generation: 1 + Reason: RestartNodes + Status: True + Type: RestartNodes + Last Transition Time: 2025-07-15T08:51:32Z + Message: get pod; ConditionStatus:True; PodName:druid-quickstart-historicals-0 + Observed Generation: 1 + Status: True + Type: GetPod--druid-quickstart-historicals-0 + Last Transition Time: 2025-07-15T08:51:32Z + Message: evict pod; ConditionStatus:True; PodName:druid-quickstart-historicals-0 + Observed Generation: 1 + Status: True + Type: EvictPod--druid-quickstart-historicals-0 + Last Transition Time: 2025-07-15T08:51:37Z + Message: check pod running; ConditionStatus:True; PodName:druid-quickstart-historicals-0 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--druid-quickstart-historicals-0 + Last Transition Time: 2025-07-15T08:51:42Z + Message: get pod; ConditionStatus:True; PodName:druid-quickstart-middlemanagers-0 + Observed Generation: 1 + Status: True + Type: GetPod--druid-quickstart-middlemanagers-0 + Last Transition Time: 2025-07-15T08:51:42Z + Message: evict pod; ConditionStatus:True; PodName:druid-quickstart-middlemanagers-0 + Observed Generation: 1 + Status: True + Type: EvictPod--druid-quickstart-middlemanagers-0 + Last Transition Time: 2025-07-15T08:51:47Z + Message: check pod running; ConditionStatus:True; PodName:druid-quickstart-middlemanagers-0 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--druid-quickstart-middlemanagers-0 + Last Transition Time: 2025-07-15T08:51:52Z + Message: get pod; ConditionStatus:True; PodName:druid-quickstart-brokers-0 + Observed Generation: 1 + Status: True + Type: GetPod--druid-quickstart-brokers-0 + Last Transition Time: 2025-07-15T08:51:52Z + Message: evict pod; ConditionStatus:True; PodName:druid-quickstart-brokers-0 + Observed Generation: 1 + Status: True + Type: EvictPod--druid-quickstart-brokers-0 + Last Transition Time: 2025-07-15T08:51:57Z + Message: check pod running; ConditionStatus:True; PodName:druid-quickstart-brokers-0 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--druid-quickstart-brokers-0 + Last Transition Time: 2025-07-15T08:52:02Z + Message: get pod; ConditionStatus:True; PodName:druid-quickstart-routers-0 + Observed Generation: 1 + Status: True + Type: GetPod--druid-quickstart-routers-0 + Last Transition Time: 2025-07-15T08:52:02Z + Message: evict pod; ConditionStatus:True; PodName:druid-quickstart-routers-0 + Observed Generation: 1 + Status: True + Type: EvictPod--druid-quickstart-routers-0 + Last Transition Time: 2025-07-15T08:52:07Z + Message: check pod running; ConditionStatus:True; PodName:druid-quickstart-routers-0 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--druid-quickstart-routers-0 + Last Transition Time: 2025-07-15T08:52:12Z + Message: get pod; ConditionStatus:True; PodName:druid-quickstart-coordinators-0 + Observed Generation: 1 + Status: True + Type: GetPod--druid-quickstart-coordinators-0 + Last Transition Time: 2025-07-15T08:52:12Z + Message: evict pod; ConditionStatus:True; PodName:druid-quickstart-coordinators-0 + Observed Generation: 1 + Status: True + Type: EvictPod--druid-quickstart-coordinators-0 + Last Transition Time: 2025-07-15T08:52:17Z + Message: check pod running; ConditionStatus:True; PodName:druid-quickstart-coordinators-0 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--druid-quickstart-coordinators-0 + Last Transition Time: 2025-07-15T08:52:22Z + Message: Successfully completed rotate auth opsRequest + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Starting 57m KubeDB Ops-manager Operator Start processing for DruidOpsRequest: demo/drops-rotate-auth-user + Normal UpdatePetSets 57m KubeDB Ops-manager Operator successfully reconciled the Druid with new configure + Warning get pod; ConditionStatus:True; PodName:druid-quickstart-historicals-0 57m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:druid-quickstart-historicals-0 + Warning evict pod; ConditionStatus:True; PodName:druid-quickstart-historicals-0 57m KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:druid-quickstart-historicals-0 + Warning check pod running; ConditionStatus:True; PodName:druid-quickstart-historicals-0 57m KubeDB Ops-manager Operator check pod running; ConditionStatus:True; PodName:druid-quickstart-historicals-0 + Warning get pod; ConditionStatus:True; PodName:druid-quickstart-middlemanagers-0 57m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:druid-quickstart-middlemanagers-0 + Warning evict pod; ConditionStatus:True; PodName:druid-quickstart-middlemanagers-0 57m KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:druid-quickstart-middlemanagers-0 + Warning check pod running; ConditionStatus:True; PodName:druid-quickstart-middlemanagers-0 57m KubeDB Ops-manager Operator check pod running; ConditionStatus:True; PodName:druid-quickstart-middlemanagers-0 + Warning get pod; ConditionStatus:True; PodName:druid-quickstart-brokers-0 57m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:druid-quickstart-brokers-0 + Warning evict pod; ConditionStatus:True; PodName:druid-quickstart-brokers-0 57m KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:druid-quickstart-brokers-0 + Warning check pod running; ConditionStatus:True; PodName:druid-quickstart-brokers-0 56m KubeDB Ops-manager Operator check pod running; ConditionStatus:True; PodName:druid-quickstart-brokers-0 + Warning get pod; ConditionStatus:True; PodName:druid-quickstart-routers-0 56m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:druid-quickstart-routers-0 + Warning evict pod; ConditionStatus:True; PodName:druid-quickstart-routers-0 56m KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:druid-quickstart-routers-0 + Warning check pod running; ConditionStatus:True; PodName:druid-quickstart-routers-0 56m KubeDB Ops-manager Operator check pod running; ConditionStatus:True; PodName:druid-quickstart-routers-0 + Warning get pod; ConditionStatus:True; PodName:druid-quickstart-coordinators-0 56m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:druid-quickstart-coordinators-0 + Warning evict pod; ConditionStatus:True; PodName:druid-quickstart-coordinators-0 56m KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:druid-quickstart-coordinators-0 + Warning check pod running; ConditionStatus:True; PodName:druid-quickstart-coordinators-0 56m KubeDB Ops-manager Operator check pod running; ConditionStatus:True; PodName:druid-quickstart-coordinators-0 + Normal RestartNodes 56m KubeDB Ops-manager Operator Successfully restarted all nodes + Normal Starting 56m KubeDB Ops-manager Operator Resuming Druid database: demo/druid-quickstart + Normal Successful 56m KubeDB Ops-manager Operator Successfully resumed Druid database: demo/druid-quickstart for DruidOpsRequest: drops-rotate-auth-user + +``` +**Verify auth is rotate** +```shell +$ kubectl get druid -n demo druid-quickstart -ojson | jq .spec.authSecret.name +"druid-quickstart-auth-user" +$ kubectl get secret -n demo druid-quickstart-auth-user -o=jsonpath='{.data.username}' | base64 -d +admin⏎ +$ kubectl get secret -n demo druid-quickstart-auth-user -o=jsonpath='{.data.password}' | base64 -d +testpassword⏎ +``` +Also, there will be two more new keys in the secret that stores the previous credentials. The keys are `username.prev` and `password.prev`. You can find the secret and its data by running the following command: +```shell +$ kubectl get secret -n demo druid-quickstart-auth-user -o go-template='{{ index .data "password.prev" }}' | base64 -d +admin⏎ +$ kubectl get secret -n demo druid-quickstart-auth-user -o go-template='{{ index .data "password.prev" }}' | base64 -d +gTJJMdgpKy9U(Eqi⏎ +``` + +The above output shows that the password has been changed successfully. The previous username & password is stored in the secret for rollback purpose. + +## Cleaning up + +To clean up the Kubernetes resources you can delete the CRD or namespace. +Or, you can delete one by one resource by their name by this tutorial, run: + +```shell +$ kubectl delete Druidopsrequest druidops-rotate-auth-generated drops-rotate-auth-user -n demo +Druidopsrequest.ops.kubedb.com "druidops-rotate-auth-generated" "drops-rotate-auth-user" deleted +$ kubectl delete secret -n demo druid-quickstart-auth-user +secret "druid-quickstart-auth-user" deleted +$ kubectl delete secret -n demo druid-quickstart-auth +secret "druid-quickstart-auth" deleted +``` + + +## Next Steps + +- Learn how to use KubeDB to run Apache Druid cluster [here](/docs/guides/druid/README.md). +- Deploy [dedicated topology cluster](/docs/guides/druid/clustering/guide/index.md) for Apache Druid +- Monitor your Druid cluster with KubeDB using [`out-of-the-box` Prometheus operator](/docs/guides/druid/monitoring/using-prometheus-operator.md). +- Detail concepts of [DruidVersion object](/docs/guides/druid/concepts/druidversion.md). + +[//]: # (- Learn to use KubeDB managed Druid objects using [CLIs](/docs/guides/druid/cli/cli.md).) +- Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md). \ No newline at end of file diff --git a/docs/guides/druid/rotate-auth/yamls/Druid-rotate-auth-generated.yaml b/docs/guides/druid/rotate-auth/yamls/Druid-rotate-auth-generated.yaml new file mode 100644 index 0000000000..d658cdb31a --- /dev/null +++ b/docs/guides/druid/rotate-auth/yamls/Druid-rotate-auth-generated.yaml @@ -0,0 +1,11 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: DruidOpsRequest +metadata: + name: druidops-rotate-auth-generated + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: druid-quickstart + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/guides/druid/rotate-auth/yamls/Druid-rotate-auth-user.yaml b/docs/guides/druid/rotate-auth/yamls/Druid-rotate-auth-user.yaml new file mode 100644 index 0000000000..c3f7275e2a --- /dev/null +++ b/docs/guides/druid/rotate-auth/yamls/Druid-rotate-auth-user.yaml @@ -0,0 +1,14 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: DruidOpsRequest +metadata: + name: drops-rotate-auth-user + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: druid-quickstart + authentication: + secretRef: + name: sample-druid-auth-user + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/guides/elasticsearch/backup/stash/kubedb/index.md b/docs/guides/elasticsearch/backup/stash/kubedb/index.md index d241cfbdf3..d12336a33a 100644 --- a/docs/guides/elasticsearch/backup/stash/kubedb/index.md +++ b/docs/guides/elasticsearch/backup/stash/kubedb/index.md @@ -92,7 +92,7 @@ spec: Let's create the above `Elasticsearch` object, ```console -$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/guides/elasticsearch/backup/kubedb/examples/elasticsearch/sample_es.yaml +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/guides/elasticsearch/backup/stash/kubedb/examples/elasticsearch/sample_es.yaml elasticsearch.kubedb.com/sample-es created ``` diff --git a/docs/guides/elasticsearch/rotateauth/_index.md b/docs/guides/elasticsearch/rotateauth/_index.md new file mode 100644 index 0000000000..608378e4d2 --- /dev/null +++ b/docs/guides/elasticsearch/rotateauth/_index.md @@ -0,0 +1,11 @@ +--- +title: Elasticsearch Rotateauth +menu: + docs_{{ .version }}: + identifier: es-rotateauth-elasticsearch + name: Rotate Authentication + parent: es-elasticsearch-guides + weight: 45 +menu_name: docs_{{ .version }} +--- + diff --git a/docs/guides/elasticsearch/rotateauth/rotateauth.md b/docs/guides/elasticsearch/rotateauth/rotateauth.md new file mode 100644 index 0000000000..33be98638e --- /dev/null +++ b/docs/guides/elasticsearch/rotateauth/rotateauth.md @@ -0,0 +1,639 @@ +--- +title: Elasticsearch Rotateauth Guide +description: Elasticsearch Rotateauth Guide +menu: + docs_{{ .version }}: + identifier: es-rotateauth-guide + name: Guide + parent: es-rotateauth-elasticsearch + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +# Rotate Authentication of Elasticsearch + +**Rotate Authentication** is a feature of the KubeDB Ops-Manager that allows you to rotate a `Elasticsearch` user's authentication credentials using a `ElasticsearchOpsRequest`. There are two ways to perform this rotation. + +1. **Operator Generated:** The KubeDB operator automatically generates a random credential and updates the existing secret with the new credential . +2. **User Defined:** The user can create their own credentials by defining a Secret of type `kubernetes.io/basic-auth` containing the desired `username` and `password` and then reference this secret in the `ElasticsearchOpsRequest`. + +## Before You Begin + +- You should be familiar with the following `KubeDB` concepts: + - [Elasticsearch](/docs/guides/elasticsearch/concepts/elasticsearch/index.md) + - [ElasticsearchOpsRequest](/docs/guides/elasticsearch/concepts/elasticsearch-ops-request/index.md) + +- At first, you need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Now, install KubeDB cli on your workstation and KubeDB operator in your cluster following the steps [here](/docs/setup/README.md). + +- To keep things isolated, this tutorial uses a separate namespace called `demo` throughout this tutorial. + + ```bash + $ kubectl create ns demo + namespace/demo created + ``` + +## Create a Elasticsearch database +The KubeDB operator implements an Elasticsearch CRD to define the specification of an Elasticsearch database. + +The Elasticsearch instance used for this tutorial: + +`Note`: If your `KubeDB version` is less or equal to `v2024.6.4`, You have to use `v1alpha2` apiVersion. + +```yaml +apiVersion: kubedb.com/v1 +kind: Elasticsearch +metadata: + name: sample-es + namespace: demo +spec: + version: xpack-8.11.1 + storageType: Durable + topology: + master: + suffix: master + replicas: 1 + storage: + storageClassName: "standard" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + data: + suffix: data + replicas: 2 + storage: + storageClassName: "standard" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + ingest: + suffix: client + replicas: 2 + storage: + storageClassName: "standard" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + +``` +Let's create the above `Elasticsearch` object, + +```console +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/guides/elasticsearch/backup/stash/kubedb/examples/elasticsearch/sample_es.yaml +elasticsearch.kubedb.com/sample-es created +``` + + +Now, wait until `sample-es` has status Ready. i.e, + +```shell +$ kubectl get Elasticsearch -n demo -w +NAME VERSION STATUS AGE +sample-es xpack-8.11.1 Ready 3m12s +``` +## Verify authentication +The user can verify whether they are authorized by executing a query directly in the database. To do this, the user needs `username` and `password` in order to connect to the database using the `kubectl exec` command. Below is an example showing how to retrieve the credentials from the Secret. + +````shell +$ kubectl get es -n demo sample-es -ojson | jq .spec.authSecret.name +"sample-es-auth" +$ kubectl get secret -n demo sample-es-auth -o jsonpath='{.data.username}' | base64 -d +elastic⏎ +$ kubectl get secret -n demo sample-es-auth -o jsonpath='{.data.password}' | base64 -d +l;)1knmenzgH0c2M⏎ +```` +Now, you can exec into the pod `sample-es` and connect to database using `username` and `password`. + +**Port-forward the Service** + +At first, let’s port-forward the `sample-es` Service. Run the following command into a separate terminal. +```shell +$ kubectl port-forward -n demo service/sample-es 9200 +Forwarding from 127.0.0.1:9200 -> 9200 +Forwarding from [::1]:9200 -> 9200 +``` + +**Insert database** + +```shell +$ curl -XPOST --user "elastic:l;)1knmenzgH0c2M" "http://localhost:9200/products/_doc?pretty" -H 'Content-Type: application/json' -d' + { + "name": "KubeDB", + "vendor": "AppsCode Inc.", + "description": "Database Operator for Kubernetes" + } + ' +``` +You'll see: +```shell +{ + "_index" : "products", + "_id" : "1tCNEpgBr20vA8aRT9BX", + "_version" : 1, + "result" : "created", + "_shards" : { + "total" : 2, + "successful" : 1, + "failed" : 0 + }, + "_seq_no" : 0, + "_primary_term" : 1 +} +``` +If you can access the data table and run queries, it means the secrets are working correctly. +## Create RotateAuth ElasticsearchOpsRequest + +#### 1. Using operator generated credentials: + +In order to rotate authentication to the Elasticsearch using operator generated, we have to create a `ElasticsearchOpsRequest` CRO with `RotateAuth` type. Below is the YAML of the `ElasticsearchOpsRequest` CRO that we are going to create, +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: ElasticsearchOpsRequest +metadata: + name: essops-rotate-auth-generated + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: sample-es + timeout: 5m + apply: IfReady +``` +Here, + +- `spec.databaseRef.name` specifies that we are performing rotate authentication operation on `sample-es` cluster. +- `spec.type` specifies that we are performing `RotateAuth` on Elasticsearch. + +Let's create the `ElasticsearchOpsRequest` CR we have shown above, +```shell + $ kubectl apply -f kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/guides/elasticsearch/rotate-auth/yamls/rotate-auth-generated.yaml + Elasticsearchopsrequest.ops.kubedb.com/essops-rotate-auth-generated created +``` +Let's wait for `ElasticsearchOpsrequest` to be `Successful`. Run the following command to watch `ElasticsearchOpsrequest` CRO +```shell +$ kubectl get esops -n demo +NAME TYPE STATUS AGE +essops-rotate-auth-generated RotateAuth Successful 7m12s +``` +If we describe the `ElasticsearchOpsRequest` we will get an overview of the steps that were followed. +```shell +$ kubectl describe Elasticsearchopsrequest -n demo essops-rotate-auth-generated +Name: essops-rotate-auth-generated +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: ElasticsearchOpsRequest +Metadata: + Creation Timestamp: 2025-07-16T09:35:47Z + Generation: 1 + Resource Version: 797065 + UID: 5c642055-67d9-47d8-ad55-119a33720723 +Spec: + Apply: IfReady + Database Ref: + Name: sample-es + Timeout: 5m + Type: RotateAuth +Status: + Conditions: + Last Transition Time: 2025-07-16T09:35:47Z + Message: Elasticsearch ops request is updating database version + Observed Generation: 1 + Reason: UpdateVersion + Status: True + Type: UpdateVersion + Last Transition Time: 2025-07-16T09:35:50Z + Message: Successfully generated new credentials + Observed Generation: 1 + Reason: UpdateCredential + Status: True + Type: UpdateCredential + Last Transition Time: 2025-07-16T09:36:02Z + Message: Successfully updated petSets + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2025-07-16T09:36:07Z + Message: pod exists; ConditionStatus:True; PodName:sample-es-client-0 + Observed Generation: 1 + Status: True + Type: PodExists--sample-es-client-0 + Last Transition Time: 2025-07-16T09:36:07Z + Message: create es client; ConditionStatus:True; PodName:sample-es-client-0 + Observed Generation: 1 + Status: True + Type: CreateEsClient--sample-es-client-0 + Last Transition Time: 2025-07-16T09:36:07Z + Message: evict pod; ConditionStatus:True; PodName:sample-es-client-0 + Observed Generation: 1 + Status: True + Type: EvictPod--sample-es-client-0 + Last Transition Time: 2025-07-16T09:39:47Z + Message: create es client; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: CreateEsClient + Last Transition Time: 2025-07-16T09:36:57Z + Message: pod exists; ConditionStatus:True; PodName:sample-es-client-1 + Observed Generation: 1 + Status: True + Type: PodExists--sample-es-client-1 + Last Transition Time: 2025-07-16T09:36:57Z + Message: create es client; ConditionStatus:True; PodName:sample-es-client-1 + Observed Generation: 1 + Status: True + Type: CreateEsClient--sample-es-client-1 + Last Transition Time: 2025-07-16T09:36:57Z + Message: evict pod; ConditionStatus:True; PodName:sample-es-client-1 + Observed Generation: 1 + Status: True + Type: EvictPod--sample-es-client-1 + Last Transition Time: 2025-07-16T09:37:47Z + Message: pod exists; ConditionStatus:True; PodName:sample-es-data-0 + Observed Generation: 1 + Status: True + Type: PodExists--sample-es-data-0 + Last Transition Time: 2025-07-16T09:37:47Z + Message: create es client; ConditionStatus:True; PodName:sample-es-data-0 + Observed Generation: 1 + Status: True + Type: CreateEsClient--sample-es-data-0 + Last Transition Time: 2025-07-16T09:37:47Z + Message: evict pod; ConditionStatus:True; PodName:sample-es-data-0 + Observed Generation: 1 + Status: True + Type: EvictPod--sample-es-data-0 + Last Transition Time: 2025-07-16T09:38:37Z + Message: pod exists; ConditionStatus:True; PodName:sample-es-data-1 + Observed Generation: 1 + Status: True + Type: PodExists--sample-es-data-1 + Last Transition Time: 2025-07-16T09:38:37Z + Message: create es client; ConditionStatus:True; PodName:sample-es-data-1 + Observed Generation: 1 + Status: True + Type: CreateEsClient--sample-es-data-1 + Last Transition Time: 2025-07-16T09:38:37Z + Message: evict pod; ConditionStatus:True; PodName:sample-es-data-1 + Observed Generation: 1 + Status: True + Type: EvictPod--sample-es-data-1 + Last Transition Time: 2025-07-16T09:39:02Z + Message: pod exists; ConditionStatus:True; PodName:sample-es-master-0 + Observed Generation: 1 + Status: True + Type: PodExists--sample-es-master-0 + Last Transition Time: 2025-07-16T09:39:02Z + Message: create es client; ConditionStatus:True; PodName:sample-es-master-0 + Observed Generation: 1 + Status: True + Type: CreateEsClient--sample-es-master-0 + Last Transition Time: 2025-07-16T09:39:02Z + Message: evict pod; ConditionStatus:True; PodName:sample-es-master-0 + Observed Generation: 1 + Status: True + Type: EvictPod--sample-es-master-0 + Last Transition Time: 2025-07-16T09:39:52Z + Message: Successfully restarted all nodes + Observed Generation: 1 + Reason: RestartNodes + Status: True + Type: RestartNodes + Last Transition Time: 2025-07-16T09:39:52Z + Message: Successfully completed the modification process. + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal PauseDatabase 9m19s KubeDB Ops-manager Operator Pausing Elasticsearch demo/sample-es + Warning pod exists; ConditionStatus:True; PodName:sample-es-client-0 8m59s KubeDB Ops-manager Operator pod exists; ConditionStatus:True; PodName:sample-es-client-0 + Warning create es client; ConditionStatus:True; PodName:sample-es-client-0 8m59s KubeDB Ops-manager Operator create es client; ConditionStatus:True; PodName:sample-es-client-0 + Warning evict pod; ConditionStatus:True; PodName:sample-es-client-0 8m59s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:sample-es-client-0 + Warning create es client; ConditionStatus:False 8m54s KubeDB Ops-manager Operator create es client; ConditionStatus:False + Warning create es client; ConditionStatus:True 8m14s KubeDB Ops-manager Operator create es client; ConditionStatus:True + Warning pod exists; ConditionStatus:True; PodName:sample-es-client-1 8m9s KubeDB Ops-manager Operator pod exists; ConditionStatus:True; PodName:sample-es-client-1 + Warning create es client; ConditionStatus:True; PodName:sample-es-client-1 8m9s KubeDB Ops-manager Operator create es client; ConditionStatus:True; PodName:sample-es-client-1 + Warning evict pod; ConditionStatus:True; PodName:sample-es-client-1 8m9s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:sample-es-client-1 + Warning create es client; ConditionStatus:False 8m4s KubeDB Ops-manager Operator create es client; ConditionStatus:False + Warning create es client; ConditionStatus:True 7m24s KubeDB Ops-manager Operator create es client; ConditionStatus:True + Warning pod exists; ConditionStatus:True; PodName:sample-es-data-0 7m19s KubeDB Ops-manager Operator pod exists; ConditionStatus:True; PodName:sample-es-data-0 + Warning create es client; ConditionStatus:True; PodName:sample-es-data-0 7m19s KubeDB Ops-manager Operator create es client; ConditionStatus:True; PodName:sample-es-data-0 + Warning evict pod; ConditionStatus:True; PodName:sample-es-data-0 7m19s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:sample-es-data-0 + Warning create es client; ConditionStatus:False 7m14s KubeDB Ops-manager Operator create es client; ConditionStatus:False + Warning create es client; ConditionStatus:True 6m34s KubeDB Ops-manager Operator create es client; ConditionStatus:True + Warning pod exists; ConditionStatus:True; PodName:sample-es-data-1 6m29s KubeDB Ops-manager Operator pod exists; ConditionStatus:True; PodName:sample-es-data-1 + Warning create es client; ConditionStatus:True; PodName:sample-es-data-1 6m29s KubeDB Ops-manager Operator create es client; ConditionStatus:True; PodName:sample-es-data-1 + Warning evict pod; ConditionStatus:True; PodName:sample-es-data-1 6m29s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:sample-es-data-1 + Warning create es client; ConditionStatus:False 6m24s KubeDB Ops-manager Operator create es client; ConditionStatus:False + Warning create es client; ConditionStatus:True 6m9s KubeDB Ops-manager Operator create es client; ConditionStatus:True + Warning pod exists; ConditionStatus:True; PodName:sample-es-master-0 6m4s KubeDB Ops-manager Operator pod exists; ConditionStatus:True; PodName:sample-es-master-0 + Warning create es client; ConditionStatus:True; PodName:sample-es-master-0 6m4s KubeDB Ops-manager Operator create es client; ConditionStatus:True; PodName:sample-es-master-0 + Warning evict pod; ConditionStatus:True; PodName:sample-es-master-0 6m4s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:sample-es-master-0 + Warning create es client; ConditionStatus:False 5m59s KubeDB Ops-manager Operator create es client; ConditionStatus:False + Warning create es client; ConditionStatus:True 5m19s KubeDB Ops-manager Operator create es client; ConditionStatus:True + Normal RestartNodes 5m14s KubeDB Ops-manager Operator Successfully restarted all nodes + Normal ResumeDatabase 5m14s KubeDB Ops-manager Operator Resuming Elasticsearch + Normal ResumeDatabase 5m14s KubeDB Ops-manager Operator Resuming Elasticsearch demo/sample-es + Normal ResumeDatabase 5m14s KubeDB Ops-manager Operator Successfully resumed Elasticsearch demo/sample-es + Normal Successful 5m14s KubeDB Ops-manager Operator Successfully updated authsecret. + +``` +**Verify Auth is rotated** + +```shell +$ kubectl get es -n demo sample-es -ojson | jq .spec.authSecret.name +"sample-es-auth" +$ kubectl get secret -n demo sample-es-auth -o jsonpath='{.data.username}' | base64 -d +elastic⏎ +$ kubectl get secret -n demo sample-es-auth -o jsonpath='{.data.password}' | base64 -d +k3pcRRtJi8iMhlVy⏎ +``` +Also, there will be two more new keys in the secret that stores the previous credentials. The keys are `username.prev` and `password.prev`. You can find the secret and its data by running the following command: + +```shell +$ kubectl get secret -n demo sample-es-auth -o go-template='{{ index .data "username.prev" }}' | base64 -d +elastic⏎ +$ kubectl get secret -n demo sample-es-auth -o go-template='{{ index .data "password.prev" }}' | base64 -d +l;)1knmenzgH0c2M⏎ +``` +The above output shows that the password has been changed successfully. The previous username & password is stored for rollback purpose. +#### 2. Using user created credentials + +At first, we need to create a secret with kubernetes.io/basic-auth type using custom username and password. Below is the command to create a secret with kubernetes.io/basic-auth type, + +> Note: `username` must be `elastic`. + +```shell +$ kubectl create secret generic sample-es-auth-user -n demo \ + --type=kubernetes.io/basic-auth \ + --from-literal=username=elastic \ + --from-literal=password=testpassword +secret/sample-es-auth-user created +``` +Now create a `ElasticsearchOpsRequest` with `RotateAuth` type. Below is the YAML of the `ElasticsearchOpsRequest` that we are going to create, + +```shell +apiVersion: ops.kubedb.com/v1alpha1 +kind: ElasticsearchOpsRequest +metadata: + name: esops-rotate-auth-user + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: sample-es + authentication: + secretRef: + name: sample-es-auth-user + timeout: 5m + apply: IfReady +``` +Here, + +- `spec.databaseRef.name` specifies that we are performing rotate authentication operation on `sample-es`cluster. +- `spec.type` specifies that we are performing `RotateAuth` on Elasticsearch. +- `spec.authentication.secretRef.name` specifies that we are using `sample-es-auth-user` as `spec.authSecret.name` for authentication. + +Let's create the `ElasticsearchOpsRequest` CR we have shown above, + +```shell +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/guides/elasticsearch/rotate-auth/yamls/rotate-auth-user.yaml +Elasticsearchopsrequest.ops.kubedb.com/esops-rotate-auth-user created +``` +Let’s wait for `ElasticsearchOpsRequest` to be Successful. Run the following command to watch `ElasticsearchOpsRequest` CRO: + +```shell +$ kubectl get Elasticsearchopsrequest -n demo +NAME TYPE STATUS AGE +essops-rotate-auth-generated RotateAuth Successful 100s +esops-rotate-auth-user RotateAuth Successful 62s +``` +We can see from the above output that the `ElasticsearchOpsRequest` has succeeded. If we describe the `ElasticsearchOpsRequest` we will get an overview of the steps that were followed. +```shell +$kubectl describe Elasticsearchopsrequest -n demo esops-rotate-auth-user +Name: esops-rotate-auth-user +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: ElasticsearchOpsRequest +Metadata: + Creation Timestamp: 2025-07-16T10:50:03Z + Generation: 1 + Resource Version: 804361 + UID: a7510ebe-b026-4070-ae29-e309be7781ad +Spec: + Apply: IfReady + Authentication: + Secret Ref: + Name: sample-es-auth-user + Database Ref: + Name: sample-es + Timeout: 5m + Type: RotateAuth +Status: + Conditions: + Last Transition Time: 2025-07-16T10:50:03Z + Message: Elasticsearch ops request is updating database version + Observed Generation: 1 + Reason: UpdateVersion + Status: True + Type: UpdateVersion + Last Transition Time: 2025-07-16T10:50:03Z + Message: Successfully referenced the user provided authSecret + Observed Generation: 1 + Reason: UpdateCredential + Status: True + Type: UpdateCredential + Last Transition Time: 2025-07-16T10:50:15Z + Message: Successfully updated petSets + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2025-07-16T10:50:20Z + Message: pod exists; ConditionStatus:True; PodName:sample-es-client-0 + Observed Generation: 1 + Status: True + Type: PodExists--sample-es-client-0 + Last Transition Time: 2025-07-16T10:50:20Z + Message: create es client; ConditionStatus:True; PodName:sample-es-client-0 + Observed Generation: 1 + Status: True + Type: CreateEsClient--sample-es-client-0 + Last Transition Time: 2025-07-16T10:50:20Z + Message: evict pod; ConditionStatus:True; PodName:sample-es-client-0 + Observed Generation: 1 + Status: True + Type: EvictPod--sample-es-client-0 + Last Transition Time: 2025-07-16T10:54:20Z + Message: create es client; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: CreateEsClient + Last Transition Time: 2025-07-16T10:51:05Z + Message: pod exists; ConditionStatus:True; PodName:sample-es-client-1 + Observed Generation: 1 + Status: True + Type: PodExists--sample-es-client-1 + Last Transition Time: 2025-07-16T10:51:05Z + Message: create es client; ConditionStatus:True; PodName:sample-es-client-1 + Observed Generation: 1 + Status: True + Type: CreateEsClient--sample-es-client-1 + Last Transition Time: 2025-07-16T10:51:05Z + Message: evict pod; ConditionStatus:True; PodName:sample-es-client-1 + Observed Generation: 1 + Status: True + Type: EvictPod--sample-es-client-1 + Last Transition Time: 2025-07-16T10:52:00Z + Message: pod exists; ConditionStatus:True; PodName:sample-es-data-0 + Observed Generation: 1 + Status: True + Type: PodExists--sample-es-data-0 + Last Transition Time: 2025-07-16T10:52:00Z + Message: create es client; ConditionStatus:True; PodName:sample-es-data-0 + Observed Generation: 1 + Status: True + Type: CreateEsClient--sample-es-data-0 + Last Transition Time: 2025-07-16T10:52:00Z + Message: evict pod; ConditionStatus:True; PodName:sample-es-data-0 + Observed Generation: 1 + Status: True + Type: EvictPod--sample-es-data-0 + Last Transition Time: 2025-07-16T10:52:50Z + Message: pod exists; ConditionStatus:True; PodName:sample-es-data-1 + Observed Generation: 1 + Status: True + Type: PodExists--sample-es-data-1 + Last Transition Time: 2025-07-16T10:52:50Z + Message: create es client; ConditionStatus:True; PodName:sample-es-data-1 + Observed Generation: 1 + Status: True + Type: CreateEsClient--sample-es-data-1 + Last Transition Time: 2025-07-16T10:52:50Z + Message: evict pod; ConditionStatus:True; PodName:sample-es-data-1 + Observed Generation: 1 + Status: True + Type: EvictPod--sample-es-data-1 + Last Transition Time: 2025-07-16T10:53:40Z + Message: pod exists; ConditionStatus:True; PodName:sample-es-master-0 + Observed Generation: 1 + Status: True + Type: PodExists--sample-es-master-0 + Last Transition Time: 2025-07-16T10:53:40Z + Message: create es client; ConditionStatus:True; PodName:sample-es-master-0 + Observed Generation: 1 + Status: True + Type: CreateEsClient--sample-es-master-0 + Last Transition Time: 2025-07-16T10:53:40Z + Message: evict pod; ConditionStatus:True; PodName:sample-es-master-0 + Observed Generation: 1 + Status: True + Type: EvictPod--sample-es-master-0 + Last Transition Time: 2025-07-16T10:54:25Z + Message: Successfully restarted all nodes + Observed Generation: 1 + Reason: RestartNodes + Status: True + Type: RestartNodes + Last Transition Time: 2025-07-16T10:54:25Z + Message: Successfully completed the modification process. + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Warning pod exists; ConditionStatus:True; PodName:sample-es-client-0 6m12s KubeDB Ops-manager Operator pod exists; ConditionStatus:True; PodName:sample-es-client-0 + Warning create es client; ConditionStatus:True; PodName:sample-es-client-0 6m12s KubeDB Ops-manager Operator create es client; ConditionStatus:True; PodName:sample-es-client-0 + Warning evict pod; ConditionStatus:True; PodName:sample-es-client-0 6m12s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:sample-es-client-0 + Warning create es client; ConditionStatus:False 6m7s KubeDB Ops-manager Operator create es client; ConditionStatus:False + Warning create es client; ConditionStatus:True 5m32s KubeDB Ops-manager Operator create es client; ConditionStatus:True + Warning pod exists; ConditionStatus:True; PodName:sample-es-client-1 5m27s KubeDB Ops-manager Operator pod exists; ConditionStatus:True; PodName:sample-es-client-1 + Warning create es client; ConditionStatus:True; PodName:sample-es-client-1 5m27s KubeDB Ops-manager Operator create es client; ConditionStatus:True; PodName:sample-es-client-1 + Warning evict pod; ConditionStatus:True; PodName:sample-es-client-1 5m27s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:sample-es-client-1 + Warning create es client; ConditionStatus:False 5m22s KubeDB Ops-manager Operator create es client; ConditionStatus:False + Warning create es client; ConditionStatus:True 4m37s KubeDB Ops-manager Operator create es client; ConditionStatus:True + Warning pod exists; ConditionStatus:True; PodName:sample-es-data-0 4m32s KubeDB Ops-manager Operator pod exists; ConditionStatus:True; PodName:sample-es-data-0 + Warning create es client; ConditionStatus:True; PodName:sample-es-data-0 4m32s KubeDB Ops-manager Operator create es client; ConditionStatus:True; PodName:sample-es-data-0 + Warning evict pod; ConditionStatus:True; PodName:sample-es-data-0 4m32s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:sample-es-data-0 + Warning create es client; ConditionStatus:False 4m27s KubeDB Ops-manager Operator create es client; ConditionStatus:False + Warning create es client; ConditionStatus:True 3m47s KubeDB Ops-manager Operator create es client; ConditionStatus:True + Warning pod exists; ConditionStatus:True; PodName:sample-es-data-1 3m42s KubeDB Ops-manager Operator pod exists; ConditionStatus:True; PodName:sample-es-data-1 + Warning create es client; ConditionStatus:True; PodName:sample-es-data-1 3m42s KubeDB Ops-manager Operator create es client; ConditionStatus:True; PodName:sample-es-data-1 + Warning evict pod; ConditionStatus:True; PodName:sample-es-data-1 3m42s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:sample-es-data-1 + Warning create es client; ConditionStatus:False 3m37s KubeDB Ops-manager Operator create es client; ConditionStatus:False + Warning create es client; ConditionStatus:True 2m57s KubeDB Ops-manager Operator create es client; ConditionStatus:True + Warning pod exists; ConditionStatus:True; PodName:sample-es-master-0 2m52s KubeDB Ops-manager Operator pod exists; ConditionStatus:True; PodName:sample-es-master-0 + Warning create es client; ConditionStatus:True; PodName:sample-es-master-0 2m52s KubeDB Ops-manager Operator create es client; ConditionStatus:True; PodName:sample-es-master-0 + Warning evict pod; ConditionStatus:True; PodName:sample-es-master-0 2m52s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:sample-es-master-0 + Warning create es client; ConditionStatus:False 2m47s KubeDB Ops-manager Operator create es client; ConditionStatus:False + Warning create es client; ConditionStatus:True 2m12s KubeDB Ops-manager Operator create es client; ConditionStatus:True + Normal RestartNodes 2m7s KubeDB Ops-manager Operator Successfully restarted all nodes + Normal ResumeDatabase 2m7s KubeDB Ops-manager Operator Resuming Elasticsearch + Normal ResumeDatabase 2m7s KubeDB Ops-manager Operator Resuming Elasticsearch demo/sample-es + Normal ResumeDatabase 2m7s KubeDB Ops-manager Operator Successfully resumed Elasticsearch demo/sample-es + Normal Successful 2m7s KubeDB Ops-manager Operator Successfully updated authsecret. +``` +**Verify auth is rotate** +```shell +$ kubectl get Elasticsearch -n demo sample-es -ojson | jq .spec.authSecret.name +"sample-es-auth-user" +$ kubectl get secret -n demo sample-es-auth-user -o jsonpath='{.data.username}' | base64 -d +elastic⏎ +$ kubectl get secret -n demo sample-es-auth-user -o jsonpath='{.data.password}' | base64 -d +testpassword⏎ +``` +Also, there will be two more new keys in the secret that stores the previous credentials. The keys are `username.prev` and `password.prev`. You can find the secret and its data by running the following command: +```shell +$ kubectl get secret -n demo sample-es-auth-user -o go-template='{{ index .data "username.prev" }}' | base64 -d +elastic +$ kubectl get secret -n demo sample-es-auth-user -o go-template='{{ index .data "password.prev" }}' | base64 -d +k3pcRRtJi8iMhlVy⏎ +``` + +The above output shows that the password has been changed successfully. The previous username & password is stored in the secret for rollback purpose. + +## Cleaning up + +To clean up the Kubernetes resources you can delete the CRD or namespace. +Or, you can delete one by one resource by their name by this tutorial, run: + +```shell +$ kubectl delete Elasticsearchopsrequest essps-rotate-auth-generated esops-rotate-auth-user -n demo +Elasticsearchopsrequest.ops.kubedb.com "essops-rotate-auth-generated" deleted +Elasticsearchopsrequest.ops.kubedb.com "esops-rotate-auth-user" deleted +$ kubectl delete secret -n demo sample-es-auth-user +secret "sample-es-auth-user" deleted +$ kubectl delete secret -n demo sample-es-auth +secret "sample-es-auth" deleted +``` +## Next Steps + +- [Quickstart Kibana](/docs/guides/elasticsearch/elasticsearch-dashboard/kibana/index.md) with KubeDB Operator. +- Learn how to configure [Elasticsearch Topology Cluster](/docs/guides/elasticsearch/clustering/topology-cluster/simple-dedicated-cluster/index.md). +- Learn about [backup & restore](/docs/guides/elasticsearch/backup/stash/overview/index.md) Elasticsearch database using Stash. +- Monitor your Elasticsearch database with KubeDB using [`out-of-the-box` builtin-Prometheus](/docs/guides/elasticsearch/monitoring/using-builtin-prometheus.md). +- Monitor your Elasticsearch database with KubeDB using [`out-of-the-box` Prometheus operator](/docs/guides/elasticsearch/monitoring/using-prometheus-operator.md). +- Detail concepts of [Elasticsearch object](/docs/guides/elasticsearch/concepts/elasticsearch/index.md). +- Use [private Docker registry](/docs/guides/elasticsearch/private-registry/using-private-registry.md) to deploy Elasticsearch with KubeDB. +- Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md). diff --git a/docs/guides/elasticsearch/rotateauth/yamls/rotate-auth-generated.yaml b/docs/guides/elasticsearch/rotateauth/yamls/rotate-auth-generated.yaml new file mode 100644 index 0000000000..8641850b8b --- /dev/null +++ b/docs/guides/elasticsearch/rotateauth/yamls/rotate-auth-generated.yaml @@ -0,0 +1,11 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: ElasticsearchOpsRequest +metadata: + name: essops-rotate-auth-generated + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: sample-es + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/guides/elasticsearch/rotateauth/yamls/rotate-auth-user.yaml b/docs/guides/elasticsearch/rotateauth/yamls/rotate-auth-user.yaml new file mode 100644 index 0000000000..60ef218e01 --- /dev/null +++ b/docs/guides/elasticsearch/rotateauth/yamls/rotate-auth-user.yaml @@ -0,0 +1,14 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: ElasticsearchOpsRequest +metadata: + name: esops-rotate-auth-user + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: sample-es + authentication: + secretRef: + name: sample-es-auth-user + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/guides/mariadb/failover/guide.md b/docs/guides/mariadb/failover/guide.md index 47e8eba7f3..74237b58e0 100644 --- a/docs/guides/mariadb/failover/guide.md +++ b/docs/guides/mariadb/failover/guide.md @@ -640,11 +640,8 @@ namespace "demo" deleted ## Next Steps - Learn about [backup and restore](/docs/guides/mariadb/backup/stash/overview/index.md) MariaDB database using Stash. -- Learn about initializing [MariaDB with Script](/docs/guides/mariadb/initialization/script_source.md). -- Learn about [custom MariaDBVersions](/docs/guides/mariadb/custom-versions/setup.md). -- Want to setup MariaDB cluster? Check how to [configure Highly Available MariaDB Cluster](/docs/guides/mariadb/clustering/ha_cluster.md) -- Monitor your MariaDB database with KubeDB using [built-in Prometheus](/docs/guides/mariadb/monitoring/using-builtin-prometheus.md). -- Monitor your MariaDB database with KubeDB using [Prometheus operator](/docs/guides/mariadb/monitoring/using-prometheus-operator.md). -- Detail concepts of [MariaDB object](/docs/guides/mariadb/concepts/mariadb.md). -- Use [private Docker registry](/docs/guides/mariadb/private-registry/using-private-registry.md) to deploy MariaDB with KubeDB. +- Want to setup MariaDB cluster? Check how to [configure Highly Available MariaDB Cluster](/docs/guides/mariadb/clustering/galera-cluster/index.md) +- Monitor your MariaDB database with KubeDB using [built-in Prometheus](/docs/guides/mariadb/monitoring/prometheus-operator/index.md). +- Detail concepts of [MariaDB object](/docs/guides/mariadb/concepts/mariadb/index.md). +- Use [private Docker registry](/docs/guides/mariadb/private-registry/quickstart/index.md) to deploy MariaDB with KubeDB. - Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md). \ No newline at end of file diff --git a/docs/guides/mariadb/rotate-auth/_index.md b/docs/guides/mariadb/rotate-auth/_index.md new file mode 100644 index 0000000000..2b1046acdb --- /dev/null +++ b/docs/guides/mariadb/rotate-auth/_index.md @@ -0,0 +1,10 @@ +--- +title: Rotate Authentication MariaDB +menu: + docs_{{ .version }}: + identifier: guides-mariadb-rotate-auth + name: Rotate Authentication + parent: guides-mariadb + weight: 46 +menu_name: docs_{{ .version }} +--- diff --git a/docs/guides/mariadb/rotate-auth/overview/examples/Mariadb-rotate-auth-generated.yaml b/docs/guides/mariadb/rotate-auth/overview/examples/Mariadb-rotate-auth-generated.yaml new file mode 100644 index 0000000000..b5178548f2 --- /dev/null +++ b/docs/guides/mariadb/rotate-auth/overview/examples/Mariadb-rotate-auth-generated.yaml @@ -0,0 +1,11 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: MariaDBOpsRequest +metadata: + name: mdops-rotate-auth-generated + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: sample-mariadb + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/guides/mariadb/rotate-auth/overview/examples/rotate-auth-user.yaml b/docs/guides/mariadb/rotate-auth/overview/examples/rotate-auth-user.yaml new file mode 100644 index 0000000000..7a43ce038d --- /dev/null +++ b/docs/guides/mariadb/rotate-auth/overview/examples/rotate-auth-user.yaml @@ -0,0 +1,14 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: MariaDBOpsRequest +metadata: + name: mdops-rotate-auth-user + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: sample-mariadb + authentication: + secretRef: + name: sample-mariadb-auth-user + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/guides/mariadb/rotate-auth/rotateauth.md b/docs/guides/mariadb/rotate-auth/rotateauth.md new file mode 100644 index 0000000000..4a49ee006e --- /dev/null +++ b/docs/guides/mariadb/rotate-auth/rotateauth.md @@ -0,0 +1,433 @@ +--- +title: Rotate Authentication MariaDB +menu: + docs_{{ .version }}: + identifier: guides-mariadb-rotate-authentication + name: Guide + parent: guides-mariadb-rotate-auth + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- +# Rotate Authentication of MariaDB + +**Rotate Authentication** is a feature of the KubeDB Ops-Manager that allows you to rotate a `MariaDB` user's authentication credentials using a `MariaDBOpsRequest`. There are two ways to perform this rotation. + +1. **Operator Generated:** The KubeDB operator automatically generates a random credential, updates the existing secret with the new credential The KubeDB operator automatically generates a random credential and updates the existing secret with the new credential.. +2. **User Defined:** The user can create their own credentials by defining a Secret of type `kubernetes.io/basic-auth` containing the desired `password` and then reference this secret in the `MariaDBOpsRequest`. + +## Before You Begin + +- You should be familiar with the following `KubeDB` concepts: + - [MariaDB](/docs/guides/mariadb/concepts/mariadb/index.md) + - [MariaDBOpsRequest](/docs/guides/mariadb/concepts/mariadb/index.md) + +- At first, you need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Now, install KubeDB cli on your workstation and KubeDB operator in your cluster following the steps [here](/docs/setup/README.md). + +- To keep things isolated, this tutorial uses a separate namespace called `demo` throughout this tutorial. + + ```bash + $ kubectl create ns demo + namespace/demo created + ``` + +## Create a MariaDB database + +KubeDB implements a `MariaDB` CRD to define the specification of a MariaDB database. Below is the `MariaDB` object created in this tutorial. + +`Note`: If your `KubeDB version` is less or equal to `v2024.6.4`, You have to use `v1alpha2` apiVersion. + +```yaml +apiVersion: kubedb.com/v1 +kind: MariaDB +metadata: + name: sample-mariadb + namespace: demo +spec: + version: "10.5.23" + storageType: Durable + storage: + storageClassName: "standard" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: Delete +``` + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/guides/mariadb/quickstart/overview/examples/sample-mariadb-v1.yaml +mariadb.kubedb.com/sample-mariadb created +``` + +Now, wait until sample-mariadb has status Ready. i.e, + +```shell +$ kubectl get mariadb -n demo -w +NAME VERSION STATUS AGE +sample-mariadb 10.5.23 Ready 30m +``` +## Verify authentication +The user can verify whether they are authorized by executing a query directly in the database. To do this, the user needs `username` and `password` in order to connect to the database using the `kubectl exec` command. Below is an example showing how to retrieve the credentials from the Secret. + +````shell +$ kubectl get mariadb -n demo sample-mariadb -ojson | jq .spec.authSecret.name +"sample-mariadb-auth" +$ kubectl get secret -n demo sample-mariadb-auth -o=jsonpath='{.data.username}' | base64 -d +root⏎ +$ kubectl get secret -n demo sample-mariadb-auth -o=jsonpath='{.data.password}' | base64 -d +s)cJQ*iL8wHySpvT⏎ +```` +Now, you can exec into the pod `sample-mariadb` and connect to database using `username` and `password` +```shell +$ kubectl exec -it -n demo sample-mariadb-0 -- mariadb -u root --password='s)cJQ*iL8wHySpvT' +Defaulted container "mariadb" out of: mariadb, mariadb-init (init) +Welcome to the MariaDB monitor. Commands end with ; or \g. +Your MariaDB connection id is 207 +Server version: 10.5.23-MariaDB-1:10.5.23+maria~ubu2004 mariadb.org binary distribution + +Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others. + +Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. + +MariaDB [(none)]> show databases; ++--------------------+ +| Database | ++--------------------+ +| information_schema | +| kubedb_system | +| mysql | +| performance_schema | ++--------------------+ +4 rows in set (0.000 sec) + +MariaDB [(none)]> CREATE DATABASE Bharatnaityam; +Query OK, 1 row affected (0.000 sec) + +MariaDB [(none)]> show databases; ++--------------------+ +| Database | ++--------------------+ +| Bharatnaityam | +| information_schema | +| kubedb_system | +| mysql | +| performance_schema | ++--------------------+ +5 rows in set (0.000 sec) + + +``` +If you can access the data table and run queries, it means the secrets are working correctly. +## Create RotateAuth MariaDBOpsRequest + +#### 1. Using operator generated credentials: + +In order to rotate authentication to the `MariaDB` using operator generated, we have to create a +`MariaDBOpsRequest` CRO with `RotateAuth` type. Below is the YAML of the `MariaDBOpsRequest` CRO that we +are going to create, +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: MariaDBOpsRequest +metadata: + name: mdops-rotate-auth-generated + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: sample-mariadb + timeout: 5m + apply: IfReady +``` +Here, + +- `spec.databaseRef.name` specifies that we are performing rotate authentication operation on +`sample-mariadb` database. +- `spec.type` specifies that we are performing `RotateAuth` on MariaDB. + +Let's create the `MariaDBOpsRequest` CR we have shown above, +```shell + $ kubectl apply -f kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/guides/mariadb/rotate-auth/overview/examples/Mariadb-rotate-auth-generated.yaml + mariadbopsrequest.ops.kubedb.com/mdops-rotate-auth-generated created +``` +Let's wait for `MariaDBOpsrequest` to be `Successful`. Run the following command to watch `MariaDBOpsrequest` CRO +```shell +$ kubectl get Mariadbopsrequest -n demo +NAME TYPE STATUS AGE +mdops-rotate-auth-generated RotateAuth Successful 6m28s +``` +If we describe the `MariaDBOpsRequest` we will get an overview of the steps that were followed. +```shell +$ kubectl describe Mariadbopsrequest -n demo mdops-rotate-auth-generated +Name: mdops-rotate-auth-generated +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: MariaDBOpsRequest +Metadata: + Creation Timestamp: 2025-07-11T06:43:21Z + Generation: 1 + Resource Version: 635526 + UID: fdf5a041-9403-4c0b-a788-2adad326dd88 +Spec: + Apply: IfReady + Database Ref: + Name: sample-mariadb + Timeout: 5m + Type: RotateAuth +Status: + Conditions: + Last Transition Time: 2025-07-11T06:43:21Z + Message: Controller has started to Progress the MariaDBOpsRequest: demo/mdops-rotate-auth-generated + Observed Generation: 1 + Reason: Running + Status: True + Type: Running + Last Transition Time: 2025-07-11T06:43:24Z + Message: Successfully generated new credentials + Observed Generation: 1 + Reason: patchedSecret + Status: True + Type: UpdateCredential + Last Transition Time: 2025-07-11T06:43:32Z + Message: evict pod; ConditionStatus:True; PodName:sample-mariadb-0 + Observed Generation: 1 + Status: True + Type: EvictPod--sample-mariadb-0 + Last Transition Time: 2025-07-11T06:43:32Z + Message: get pod; ConditionStatus:True; PodName:sample-mariadb-0 + Observed Generation: 1 + Status: True + Type: GetPod--sample-mariadb-0 + Last Transition Time: 2025-07-11T06:44:07Z + Message: Successfully restarted MariaDB pods for MariaDBOpsRequest: demo/mdops-rotate-auth-generated + Observed Generation: 1 + Reason: UpdatePetSetsSucceeded + Status: True + Type: UpdatePetSets + Last Transition Time: 2025-07-11T06:44:12Z + Message: Successfully rotate MariaDB auth for MariaDBOpsRequest: demo/mdops-rotate-auth-generated + Observed Generation: 1 + Reason: UpdateCredential + Status: True + Type: RotateAuth + Last Transition Time: 2025-07-11T06:44:12Z + Message: Controller has successfully rotate MariaDB auth secret demo/mdops-rotate-auth-generated + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Starting 9m17s KubeDB Ops-manager Operator Start processing for MariaDBOpsRequest: demo/mdops-rotate-auth-generated + Normal Starting 9m17s KubeDB Ops-manager Operator Pausing MariaDB databse: demo/sample-mariadb + Normal Successful 9m17s KubeDB Ops-manager Operator Successfully paused MariaDB database: demo/sample-mariadb for MariaDBOpsRequest: mdops-rotate-auth-generated + Normal Starting 9m6s KubeDB Ops-manager Operator Restarting Pod: demo/sample-mariadb-0 + Warning evict pod; ConditionStatus:True; PodName:sample-mariadb-0 9m6s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:sample-mariadb-0 + Warning get pod; ConditionStatus:True; PodName:sample-mariadb-0 9m6s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-mariadb-0 + Warning get pod; ConditionStatus:True; PodName:sample-mariadb-0 9m1s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-mariadb-0 + Warning get pod; ConditionStatus:True; PodName:sample-mariadb-0 8m31s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-mariadb-0 + Normal Successful 8m31s KubeDB Ops-manager Operator Successfully restarted MariaDB pods for MariaDBOpsRequest: demo/mdops-rotate-auth-generated + Normal Successful 8m26s KubeDB Ops-manager Operator Successfully rotate MariaDB auth for MariaDBOpsRequest: demo/mdops-rotate-auth-generated + Normal Starting 8m26s KubeDB Ops-manager Operator Resuming MariaDB database: demo/sample-mariadb + Normal Successful 8m26s KubeDB Ops-manager Operator Successfully resumed MariaDB database: demo/sample-mariadb + Normal Successful 8m26s KubeDB Ops-manager Operator Controller has successfully rotate MariaDB auth secret + +``` +**Verify Auth is rotated** +```shell +$ kubectl get mariadb -n demo sample-mariadb -ojson | jq .spec.authSecret.name +"sample-mariadb-auth" +$ kubectl get secret -n demo sample-mariadb-auth -o=jsonpath='{.data.username}' | base64 -d +root⏎ +$ kubectl get secret -n demo sample-mariadb-auth -o=jsonpath='{.data.password}' | base64 -d +gTJJMdgpKy9U(Eqi⏎ +``` +Also, there will be two more new keys in the secret that stores the previous credentials. The keys are `username.prev` and `password.prev`. You can find the secret and its data by running the following command: + +```shell +$ kubectl get secret -n demo sample-mariadb-auth -o go-template='{{ index .data "username.prev" }}' | base64 -d +root⏎ +$ kubectl get secret -n demo sample-mariadb-auth -o go-template='{{ index .data "password.prev" }}' | base64 -d +s)cJQ*iL8wHySpvT⏎ +``` +The above output shows that the password has been changed successfully. The previous username & password is stored for rollback purpose. +#### 2. Using user created credentials + +At first, we need to create a secret with kubernetes.io/basic-auth type using custom username and password. Below is the command to create a secret with kubernetes.io/basic-auth type, + +> Note: You cannot change the database `username`, but you can update the `password` while keeping the existing `username`. + +```shell +$ kubectl create secret generic sample-mariadb-auth-user -n demo \ + --type=kubernetes.io/basic-auth \ + --from-literal=username=root \ + --from-literal=password=testpassword +secret/sample-mariadb-auth-user created +``` +Now create a `MariaDBOpsRequest` with `RotateAuth` type. Below is the YAML of the `MariaDBOpsRequest` that we are going to create, + +```shell +apiVersion: ops.kubedb.com/v1alpha1 +kind: MariaDBOpsRequest +metadata: + name: mdops-rotate-auth-user + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: sample-mariadb + authentication: + secretRef: + name: sample-mariadb-auth-user + timeout: 5m + apply: IfReady +``` +Here, + +- `spec.databaseRef.name` specifies that we are performing rotate authentication operation on `sample-mariadb`cluster. +- `spec.type` specifies that we are performing `RotateAuth` on `MariaDB`. +- `spec.authentication.secretRef.name` specifies that we are using `sample-mariadb-auth-user` as `spec.authSecret.name` for authentication. + +Let's create the `MariaDBOpsRequest` CR we have shown above, + +```shell +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/guides/mariadb/rotate-auth/overview/examples/rotate-auth-user.yaml +mariadbopsrequest.ops.kubedb.com/mdops-rotate-auth-user created +``` +Let’s wait for `MariaDBOpsRequest` to be Successful. Run the following command to watch `MariaDBOpsRequest` CRO: + +```shell +$ kubectl get Mariadbopsrequest -n demo +NAME TYPE STATUS AGE +mdops-rotate-auth-generated RotateAuth Successful 100s +mdops-rotate-auth-user RotateAuth Successful 62s +``` +We can see from the above output that the `MariaDBOpsRequest` has succeeded. If we describe the `MariaDBOpsRequest` we will get an overview of the steps that were followed. +```shell +$ kubectl describe Mariadbopsrequest -n demo mdops-rotate-auth-user +Name: mdops-rotate-auth-user +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: MariaDBOpsRequest +Metadata: + Creation Timestamp: 2025-07-14T06:56:25Z + Generation: 1 + Resource Version: 665963 + UID: 6c30dc56-6ca9-4707-8b7c-5d4da6a1b585 +Spec: + Apply: IfReady + Authentication: + Secret Ref: + Name: sample-mariadb-auth-user + Database Ref: + Name: sample-mariadb + Timeout: 5m + Type: RotateAuth +Status: + Conditions: + Last Transition Time: 2025-07-14T06:56:25Z + Message: Controller has started to Progress the MariaDBOpsRequest: demo/mdops-rotate-auth-user + Observed Generation: 1 + Reason: Running + Status: True + Type: Running + Last Transition Time: 2025-07-14T06:56:28Z + Message: Successfully referenced the user provided authSecret + Observed Generation: 1 + Reason: patchedSecret + Status: True + Type: UpdateCredential + Last Transition Time: 2025-07-14T06:56:35Z + Message: evict pod; ConditionStatus:True; PodName:sample-mariadb-0 + Observed Generation: 1 + Status: True + Type: EvictPod--sample-mariadb-0 + Last Transition Time: 2025-07-14T06:56:35Z + Message: get pod; ConditionStatus:True; PodName:sample-mariadb-0 + Observed Generation: 1 + Status: True + Type: GetPod--sample-mariadb-0 + Last Transition Time: 2025-07-14T06:56:40Z + Message: Successfully restarted MariaDB pods for MariaDBOpsRequest: demo/mdops-rotate-auth-user + Observed Generation: 1 + Reason: UpdatePetSetsSucceeded + Status: True + Type: UpdatePetSets + Last Transition Time: 2025-07-14T06:56:45Z + Message: Successfully rotate MariaDB auth for MariaDBOpsRequest: demo/mdops-rotate-auth-user + Observed Generation: 1 + Reason: UpdateCredential + Status: True + Type: RotateAuth + Last Transition Time: 2025-07-14T06:56:45Z + Message: Controller has successfully rotate MariaDB auth secret demo/mdops-rotate-auth-user + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Starting 83s KubeDB Ops-manager Operator Start processing for MariaDBOpsRequest: demo/mdops-rotate-auth-user + Normal Starting 83s KubeDB Ops-manager Operator Pausing MariaDB databse: demo/sample-mariadb + Normal Successful 83s KubeDB Ops-manager Operator Successfully paused MariaDB database: demo/sample-mariadb for MariaDBOpsRequest: mdops-rotate-auth-user + Normal Starting 73s KubeDB Ops-manager Operator Restarting Pod: demo/sample-mariadb-0 + Warning evict pod; ConditionStatus:True; PodName:sample-mariadb-0 73s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:sample-mariadb-0 + Warning get pod; ConditionStatus:True; PodName:sample-mariadb-0 73s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-mariadb-0 + Warning get pod; ConditionStatus:True; PodName:sample-mariadb-0 68s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-mariadb-0 + Normal Successful 68s KubeDB Ops-manager Operator Successfully restarted MariaDB pods for MariaDBOpsRequest: demo/mdops-rotate-auth-user + Normal Successful 63s KubeDB Ops-manager Operator Successfully rotate MariaDB auth for MariaDBOpsRequest: demo/mdops-rotate-auth-user + Normal Starting 63s KubeDB Ops-manager Operator Resuming MariaDB database: demo/sample-mariadb + Normal Successful 63s KubeDB Ops-manager Operator Successfully resumed MariaDB database: demo/sample-mariadb + Normal Successful 63s KubeDB Ops-manager Operator Controller has successfully rotate MariaDB auth secret + +``` +**Verify auth is rotate** +```shell +$ kubectl get mariadb -n demo sample-mariadb -ojson | jq .spec.authSecret.name +"sample-mariadb-auth-user" +$ kubectl get secret -n demo sample-mariadb-auth-user -o=jsonpath='{.data.username}' | base64 -d +root⏎ +$ kubectl get secret -n demo sample-mariadb-auth-user -o=jsonpath='{.data.password}' | base64 -d +testpassword⏎ +``` +Also, there will be two more new keys in the secret that stores the previous credentials. The keys are `username.prev` and `password.prev`. You can find the secret and its data by running the following command: +```shell +$ kubectl get secret -n demo sample-mariadb-auth-user -o go-template='{{ index .data "username.prev" }}' | base64 -d +root⏎ +$ kubectl get secret -n demo sample-mariadb-auth-user -o go-template='{{ index .data "password.prev" }}' | base64 -d +gTJJMdgpKy9U(Eqi⏎ +``` + +The above output shows that the password has been changed successfully. The previous username & password is stored in the secret for rollback purpose. + +## Cleaning up + +To clean up the Kubernetes resources you can delete the CRD or namespace. +Or, you can delete one by one resource by their name by this tutorial, run: + +```shell +$ kubectl delete Mariadbopsrequest mdops-rotate-auth-generated mdops-rotate-auth-user -n demo +mariadbopsrequest.ops.kubedb.com "mdops-rotate-auth-generated" deleted +mariadbopsrequest.ops.kubedb.com "mdops-rotate-auth-user" deleted +$ kubectl delete secret -n demo sample-mariadb-auth-user +secret "sample-mariadb-auth-user" deleted +$ kubectl delete secret -n demo sample-mariadb-auth +secret "sample-mariadb-auth" deleted +``` + +## Next Steps + +- Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md). \ No newline at end of file diff --git a/docs/guides/memcached/rotate-auth/_index.md b/docs/guides/memcached/rotate-auth/_index.md new file mode 100644 index 0000000000..8a68a20e56 --- /dev/null +++ b/docs/guides/memcached/rotate-auth/_index.md @@ -0,0 +1,10 @@ +--- +title: Rotate Authentication Memcached +menu: + docs_{{ .version }}: + identifier: rotate-auth + name: Rotate Authentication + parent: mc-memcached-guides + weight: 101 +menu_name: docs_{{ .version }} +--- diff --git a/docs/guides/memcached/rotate-auth/rotateauth.md b/docs/guides/memcached/rotate-auth/rotateauth.md new file mode 100644 index 0000000000..539c773dfa --- /dev/null +++ b/docs/guides/memcached/rotate-auth/rotateauth.md @@ -0,0 +1,537 @@ +--- +title: Rotate Authentication guide +menu: + docs_{{ .version }}: + identifier: mc-rotate-auth-guide + name: guide + parent: rotate-auth + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +# Rotate Authentication of Memcached + +**Rotate Authentication** is a feature of the KubeDB Ops-Manager that allows you to rotate a `Memcached` +user's authentication credentials using a `MemcachedOpsRequest`. There are two ways to perform this +rotation. + +1. **Operator Generated:** The KubeDB operator automatically generates a random credential, updates the +existing secretwith the new credential, and does not provide the secretdetails directly to the user. +2. **User Defined:** The user can create their own credentials by defining a secretof type +`kubernetes.io/basic-auth` containing the desired `username` and `password` and then reference this secretin the `MemcachedOpsRequest`. + +## Before You Begin + +- At first, you need to have a Kubernetes cluster, and the `kubectl` command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Now, install KubeDB cli on your workstation and KubeDB operator in your cluster following the steps [here](/docs/setup/README.md). + +- To keep things isolated, this tutorial uses a separate namespace called `demo` throughout this tutorial. Run the following command to prepare your cluster for this tutorial: + +```bash +$ kubectl create ns demo +namespace/demo created + +$ kubectl get ns demo +NAME STATUS AGE +demo Active 1s +``` + +## Find Available MemcachedVersion + +When you have installed KubeDB, it has created `MemcachedVersion` crd for all supported Memcached versions. Check 0 + +```bash +$ kubectl get memcachedversions +NAME VERSION DB_IMAGE DEPRECATED AGE +1.5 1.5 ghcr.io/kubedb/memcached:1.5 true 5d19h +1.5-v1 1.5 ghcr.io/kubedb/memcached:1.5-v1 true 5d19h +1.5.22 1.5.22 ghcr.io/appscode-images/memcached:1.5.22-alpine 5d19h +1.5.4 1.5.4 ghcr.io/kubedb/memcached:1.5.4 true 5d19h +1.5.4-v1 1.5.4 ghcr.io/kubedb/memcached:1.5.4-v1 true 5d19h +1.6.22 1.6.22 ghcr.io/appscode-images/memcached:1.6.22-alpine 5d19h +1.6.29 1.6.29 ghcr.io/appscode-images/memcached:1.6.29-alpine 5d19h +1.6.33 1.6.33 ghcr.io/appscode-images/memcached:1.6.33-alpine 5d19h +``` + +> **Note:** YAML files used in this tutorial are stored in [docs/examples/memcached](/docs/examples/memcached/update-version) directory of [kubedb/docs](https://github.com/kube/docs) repository. + +## Create a Memcached Server + +KubeDB implements a `Memcached` CRD to define the specification of a Memcached server. Below is the `Memcached` object created in this tutorial. + +`Note`: If your `KubeDB version` is less or equal to `v2024.6.4`, You have to use `v1alpha2` apiVersion. + +```yaml +apiVersion: kubedb.com/v1 +kind: Memcached +metadata: + name: memcd-quickstart + namespace: demo +spec: + replicas: 1 + version: "1.6.22" + podTemplate: + spec: + containers: + - name: memcached + resources: + limits: + cpu: 500m + memory: 128Mi + requests: + cpu: 250m + memory: 64Mi + deletionPolicy: DoNotTerminate +``` + +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/memcached/quickstart/demo-v1.yaml +memcached.kubedb.com/memcd-quickstart created +``` + +Now, wait until memcd-quickstart has status Ready. i.e, + +```shell +$ kubectl get mc -n demo -w +NAME VERSION STATUS AGE +memcd-quickstart 1.6.22 Ready 17h +``` +## Verify Authentication +The user can verify whether they are authorized by executing a query directly in the database. To do this, the user needs `username` and `password` in order to connect to the database. Below is an example showing how to retrieve the credentials from the Secret. + +````shell +$ kubectl get memcached -n demo memcd-quickstart -ojson | jq .spec.authSecret.name +"memcd-quickstart-auth" +$ kubectl get secret-n demo memcd-quickstart-auth -o=jsonpath='{.data.authData}' | base64 -d +user:ikbkjbodeewenrgj +```` +Here, `username`is `user` and `password` is `ikbkjbodeewenrgj` + +### Connect With Memcached Database Using Credentials + +Here, we will connect to Memcached server from local-machine through port-forwarding. +We will connect to `memcd-quickstart-0` pod from local-machine using port-frowarding and it must be running in separate terminal. +```bash +$ kubectl port-forward -n demo memcd-quickstart-0 11211 +Forwarding from 127.0.0.1:11211 -> 11211 +Forwarding from [::1]:11211 -> 11211 +``` +Now, you can connect to this database using `telnet`.Connect to Memcached from local-machine through telnet. +```shell + +~ $ telnet 127.0.0.1 11211 +Trying 127.0.0.1... +Connected to 127.0.0.1. +Escape character is '^]'. + +version +CLIENT_ERROR unauthenticated # that means still you can not enter in DB + +# Save data Command: +set my_key 0 2592000 21 +# Meaning: +# 0 => no flags +# 2592000 => TTL (Time-To-Live) in [s] +# 21 => credential size in bytes + +user bvkwwqxekxouudbr # username password + +# Output: +STORED + +#now you can use DB +version +VERSION 1.6.22 + +# Exit +quit +``` +If you can access the data table and run queries, it means the secrets are working correctly. +## Create RotateAuth MemcachedOpsRequest + +#### 1. Using Operator Generated Credentials: + +In order to rotate authentication to the Memcached using operator generated, we have to create a `MemcachedOpsRequest` CRO with `RotateAuth` type. Below is the YAML of the `MemcachedOpsRequest` CRO that we are going to create, +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: MemcachedOpsRequest +metadata: + name: mcops-rotate-auth-generated + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: memcd-quickstart + timeout: 5m + apply: IfReady +``` +Here, + +- `spec.databaseRef.name` specifies that we are performing rotate authentication operation on `memcd-quickstart` cluster. +- `spec.type` specifies that we are performing `RotateAuth` on Memcached. + +Let's create the `MemcachedOpsRequest` CR we have shown above, +```shell + $ kubectl apply -f https://github.com/kubedb/docs/raw/{{ .version }}/docs/examples/memcached/rotate-auth/rotate-auth-generated.yaml + Memcachedopsrequest.ops.kubedb.com/mcops-rotate-auth-generated created +``` +Let's wait for `MemcachedOpsrequest` to be `Successful`. Run the following command to watch `MemcachedOpsrequest` CRO +```shell + $ kubectl get Memcachedopsrequest -n demo + NAME TYPE STATUS AGE + mcops-rotate-auth-generated RotateAuth Successful 7m47s +``` +If we describe the `MemcachedOpsRequest` we will get an overview of the steps that were followed. +```shell +$ kubectl describe MemcachedopsRequest -n demo mcops-rotate-auth-generated +Name: mcops-rotate-auth-generated +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: MemcachedOpsRequest +Metadata: + Creation Timestamp: 2025-08-21T10:08:37Z + Generation: 1 + Resource Version: 147775 + UID: 2466e827-fee0-4f58-89f5-2cd2265cf1a6 +Spec: + Apply: IfReady + Database Ref: + Name: memcd-quickstart + Timeout: 5m + Type: RotateAuth +Status: + Conditions: + Last Transition Time: 2025-08-21T10:08:37Z + Message: Memcached Ops Request has started to rotate auth for Memcached + Observed Generation: 1 + Reason: RotateAuth + Status: True + Type: RotateAuth + Last Transition Time: 2025-08-21T10:08:40Z + Message: Successfully generated new Credentials + Observed Generation: 1 + Reason: UpdateCredential + Status: True + Type: UpdateCredential + Last Transition Time: 2025-08-21T10:08:40Z + Message: Successfully Updated PetSets for rotate auth type + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2025-08-21T10:08:51Z + Message: Restarted pods after rotate auth + Observed Generation: 1 + Reason: RestartPods + Status: True + Type: RestartPods + Last Transition Time: 2025-08-21T10:08:46Z + Message: evict pod; ConditionStatus:True; PodName:memcd-quickstart-0 + Observed Generation: 1 + Status: True + Type: EvictPod--memcd-quickstart-0 + Last Transition Time: 2025-08-21T10:08:46Z + Message: is pod ready; ConditionStatus:False + Observed Generation: 1 + Status: False + Type: IsPodReady + Last Transition Time: 2025-08-21T10:08:51Z + Message: is pod ready; ConditionStatus:True; PodName:memcd-quickstart-0 + Observed Generation: 1 + Status: True + Type: IsPodReady--memcd-quickstart-0 + Last Transition Time: 2025-08-21T10:08:51Z + Message: Successfully Rotated Memcached Auth Secret + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal PauseDatabase 112s KubeDB Ops-manager Operator Pausing Memcached demo/memcd-quickstart + Normal VersionUpdate 109s KubeDB Ops-manager Operator Updating PetSets + Normal VersionUpdate 109s KubeDB Ops-manager Operator Successfully Updated PetSets + Warning evict pod; ConditionStatus:True; PodName:memcd-quickstart-0 103s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:memcd-quickstart-0 + Warning is pod ready; ConditionStatus:False 103s KubeDB Ops-manager Operator is pod ready; ConditionStatus:False + Warning is pod ready; ConditionStatus:True; PodName:memcd-quickstart-0 98s KubeDB Ops-manager Operator is pod ready; ConditionStatus:True; PodName:memcd-quickstart-0 + Normal RestartPods 98s KubeDB Ops-manager Operator Restarted pods after rotate auth + Normal ResumeDatabase 98s KubeDB Ops-manager Operator Resuming Memcached demo/memcd-quickstart + Normal ResumeDatabase 98s KubeDB Ops-manager Operator Successfully resumed Memcached demo/memcd-quickstart + Normal Successful 98s KubeDB Ops-manager Operator Successfully Rotated Memcached Auth secretfor demo/memcd-quickstart +``` + +**Verify Auth is rotated** +```shell +$ kubectl get mc -n demo memcd-quickstart -ojson | jq .spec.authSecret.name +"memcd-quickstart-auth" +$ kubectl get secret-n demo memcd-quickstart-auth -o=jsonpath='{.data.authData}' | base64 -d +user:yjf3Oc;ZlSs.iMVO +``` +**Let's verify whether the credential is working or not:** + +We will connect to `memcd-quickstart-0` pod from local-machine using port-frowarding and it must be running in separate terminal. +```bash +$ kubectl port-forward -n demo memcd-quickstart-0 11211 +Forwarding from 127.0.0.1:11211 -> 11211 +Forwarding from [::1]:11211 -> 11211 + +``` +Now, you can connect to this database using `telnet`.Connect to Memcached from local-machine through telnet. +```shell + +$ telnet 127.0.0.1 11211 +#Output +Trying 127.0.0.1... +Connected to 127.0.0.1. +Escape character is '^]'. + +# Save data Command: +set my_key 0 2592000 21 +# Meaning: +# 0 => no flags +# 2592000 => TTL (Time-To-Live) in [s] +# 21 => credential size in bytes +user yjf3Oc;ZlSs.iMVO +#ouput +STORED +#command +version +#output +VERSION 1.6.22 +#output +quit +Connection closed by foreign host. +``` +Your credentials have been rotated successfully, so everything’s working. +Also, there will be two more new keys in the secretthat stores the previous credentials. The key is `authData.prev`. You can find the secretand its data by running the following command: + +```shell +$ kubectl get secret-n demo memcd-quickstart-auth -o go-template='{{ index .data "authData.prev" }}' | base64 -d +user:ikbkjbodeewenrgj +``` +The above output shows that the password has been changed successfully. The previous username & password is stored for rollback purpose. +#### 2. Using User Created Credentials + +At first, we need to create a secretwith `kubernetes.io/basic-auth` type using custom username +and password. Below is the command to create a secretwith `kubernetes.io/basic-auth` type, +You can use the following yaml regarding changing the credentials + +```shell +apiVersion: v1 +data: + authData: dXNlcjpwYXNzCg== +kind: Secret +metadata: + name: mc-new-auth + namespace: demo +type: Opaque +``` +Here, +The `data.authdata` field stores user credentials in `Base64-encoded` format as **username:password**. +Now create a `MemcachedOpsRequest` with `RotateAuth` type. Below is the YAML of the +`MemcachedOpsRequest` that we are going to create, + +Let's create the secret +```shell +kubectl apply -f https://github.com/kubedb/docs/raw/{{ .version }}/docs/examples/memcached/rotate-auth/secret.yaml +secret/mc-new-auth created +``` +```shell +apiVersion: ops.kubedb.com/v1alpha1 +kind: MemcachedOpsRequest +metadata: + name: mcops-rotate-auth-user + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: memcached-quickstart + authentication: + secretRef: + name: mc-new-auth + timeout: 5m + apply: IfReady +``` +Here, + +- `spec.databaseRef.name` specifies that we are performing rotate authentication operation on `memcd-quickstart`cluster. +- `spec.type` specifies that we are performing `RotateAuth` on Memcached. +- `spec.authentication.secretRef.name` specifies that we are using `mc-new-auth` as `spec.authSecret.name` for authentication. + +Let's create the `MemcachedOpsRequest` CR we have shown above, + +```shell +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{ .version }}/docs/examples/memcached/rotate-auth/rotate-auth-user.yaml +Memcachedopsrequest.ops.kubedb.com/mcops-rotate-auth-user created +``` +Let’s wait for `MemcachedOpsRequest` to be Successful. Run the following command to watch `MemcachedOpsRequest` CRO: + +```shell +$ kubectl get Memcachedopsrequest -n demo +NAME TYPE STATUS AGE +mcops-rotate-auth-user RotateAuth Successful 7m44s +``` +We can see from the above output that the `MemcachedOpsRequest` has succeeded. If we describe the `MemcachedOpsRequest` we will get an overview of the steps that were followed. +```shell +$ kubectl describe Memcachedopsrequest -n demo mcops-rotate-auth-user +Name: mcops-rotate-auth-user +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: MemcachedOpsRequest +Metadata: + Creation Timestamp: 2025-08-21T11:39:01Z + Generation: 1 + Resource Version: 159639 + UID: 6d289952-fd05-4311-985e-9a7fa7845953 +Spec: + Apply: IfReady + Authentication: + secretRef: + Name: mc-new-auth + Database Ref: + Name: memcd-quickstart + Timeout: 5m + Type: RotateAuth +Status: + Conditions: + Last Transition Time: 2025-08-21T11:39:01Z + Message: Memcached Ops Request has started to rotate auth for Memcached + Observed Generation: 1 + Reason: RotateAuth + Status: True + Type: RotateAuth + Last Transition Time: 2025-08-21T11:39:01Z + Message: Successfully referenced the user provided authSecret + Observed Generation: 1 + Reason: UpdateCredential + Status: True + Type: UpdateCredential + Last Transition Time: 2025-08-21T11:39:01Z + Message: Successfully Updated PetSets for rotate auth type + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2025-08-21T11:39:11Z + Message: Restarted pods after rotate auth + Observed Generation: 1 + Reason: RestartPods + Status: True + Type: RestartPods + Last Transition Time: 2025-08-21T11:39:06Z + Message: evict pod; ConditionStatus:True; PodName:memcd-quickstart-0 + Observed Generation: 1 + Status: True + Type: EvictPod--memcd-quickstart-0 + Last Transition Time: 2025-08-21T11:39:06Z + Message: is pod ready; ConditionStatus:False + Observed Generation: 1 + Status: False + Type: IsPodReady + Last Transition Time: 2025-08-21T11:39:11Z + Message: is pod ready; ConditionStatus:True; PodName:memcd-quickstart-0 + Observed Generation: 1 + Status: True + Type: IsPodReady--memcd-quickstart-0 + Last Transition Time: 2025-08-21T11:39:11Z + Message: Successfully Rotated Memcached Auth Secret + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal VersionUpdate 13m KubeDB Ops-manager Operator Updating PetSets + Normal VersionUpdate 13m KubeDB Ops-manager Operator Successfully Updated PetSets + Warning evict pod; ConditionStatus:True; PodName:memcd-quickstart-0 13m KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:memcd-quickstart-0 + Warning is pod ready; ConditionStatus:False 13m KubeDB Ops-manager Operator is pod ready; ConditionStatus:False + Warning is pod ready; ConditionStatus:True; PodName:memcd-quickstart-0 13m KubeDB Ops-manager Operator is pod ready; ConditionStatus:True; PodName:memcd-quickstart-0 + Normal RestartPods 13m KubeDB Ops-manager Operator Restarted pods after rotate auth + Normal ResumeDatabase 13m KubeDB Ops-manager Operator Resuming Memcached demo/memcd-quickstart + Normal ResumeDatabase 13m KubeDB Ops-manager Operator Successfully resumed Memcached demo/memcd-quickstart + Normal Successful 13m KubeDB Ops-manager Operator Successfully Rotated Memcached Auth secretfor demo/memcd-quickstart + +``` +**Verify auth is rotate** +```shell +$ kubectl get mc -n demo memcd-quickstart -ojson | jq .spec.authSecret.name +"mc-new-auth" +$ kubectl get secret-n demo mc-new-auth -o=jsonpath='{.data.authData}' | base64 -d +user:pass +``` +**Let's verify whether the credential is working or not:** + +We will connect to `memcd-quickstart-0` pod from local-machine using port-frowarding and it must be running in separate terminal. +```bash +$ kubectl port-forward -n demo memcd-quickstart-0 11211 +Forwarding from 127.0.0.1:11211 -> 11211 +Forwarding from [::1]:11211 -> 11211 + +``` +Now, you can connect to this database using `telnet`.Connect to Memcached from local-machine through telnet. +```shell + +$ telnet 127.0.0.1 11211 +#Output +Trying 127.0.0.1... +Connected to 127.0.0.1. +Escape character is '^]'. + +# Save data Command: +set my_key 0 2592000 9 +# Meaning: +# 0 => no flags +# 2592000 => TTL (Time-To-Live) in [s] +# 9 => credential size in bytes +user pass +#ouput +STORED +#command +version +#output +VERSION 1.6.22 +#output +quit +Connection closed by foreign host. +``` +Your credentials have been rotated successfully, so everything’s working. + +Also, there will be two more new keys in the secretthat stores the previous credentials. The keys are `username.prev` and `password.prev`. You can find the secretand its data by running the following command: +```shell +$ kubectl get secret-n demo mc-new-auth -o go-template='{{ index .data "authData.prev" }}' | base64 -d +user:yjf3Oc;ZlSs.iMVO + +``` + +The above output shows that the password has been updated successfully. The previous username & password is stored in the secretfor rollback purpose. + +## Cleaning Up + +To clean up the Kubernetes resources you can delete the CRD or namespace. +Or, you can delete one by one resource by their name by this tutorial, run: + +```shell +$ kubectl delete Memcachedopsrequest mcops-rotate-auth-generated mcops-rotate-auth-user -n demo +Memcachedopsrequest.ops.kubedb.com "mcops-rotate-auth-generated" "mcops-rotate-auth-user" deleted +$ kubectl delete secret-n demo mc-new-auth +secret"mc-new-auth" deleted +$ kubectl delete secret-n demo memcd-quickstart-auth +secret"memcd-quickstart-auth" deleted +``` + +## Next Steps + +- Detail concepts of [Memcached object](/docs/guides/memcached/concepts/memcached.md). +- Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md). diff --git a/docs/guides/mongodb/rotate-auth/_index.md b/docs/guides/mongodb/rotate-auth/_index.md new file mode 100644 index 0000000000..e697c502ba --- /dev/null +++ b/docs/guides/mongodb/rotate-auth/_index.md @@ -0,0 +1,10 @@ +--- +title: Rotate Authentication MongoDB +menu: + docs_{{ .version }}: + identifier: mg-rotate-auth + name: Rotate Authentication + parent: mg-mongodb-guides + weight: 46 +menu_name: docs_{{ .version }} +--- diff --git a/docs/guides/mongodb/rotate-auth/rotateauth.md b/docs/guides/mongodb/rotate-auth/rotateauth.md new file mode 100644 index 0000000000..ce2e9522d2 --- /dev/null +++ b/docs/guides/mongodb/rotate-auth/rotateauth.md @@ -0,0 +1,549 @@ +--- +title: Rotate Authentication Guide +menu: + docs_{{ .version }}: + identifier: mg-rotate-auth-details + name: Guide + parent: mg-rotate-auth + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- +# Rotate Authentication of MongoDB + +**Rotate Authentication** is a feature of the KubeDB Ops-Manager that allows you to rotate a `MongoDB` user's authentication credentials using a `MongoDBOpsRequest`. There are two ways to perform this rotation. + +1. **Operator Generated:** The KubeDB operator automatically generates a random credential, updates the +existing secret with the new credential The KubeDB operator automatically generates a random credential and updates the existing secret with the new credential.. +2. **User Defined:** The user can create their own credentials by defining a secret of type +`kubernetes.io/basic-auth` containing the desired `password` and then reference this secret in the `MongoDBOpsRequest`. + +## Before You Begin + +- You should be familiar with the following `KubeDB` concepts: + - [MongoDB](/docs/guides/mongodb/concepts/mongodb.md) + - [MongoDBOpsRequest](/docs/guides/mongodb/concepts/opsrequest.md) + +- At first, you need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Now, install KubeDB cli on your workstation and KubeDB operator in your cluster following the steps [here](/docs/setup/README.md). + +- To keep things isolated, this tutorial uses a separate namespace called `demo` throughout this tutorial. + + ```bash + $ kubectl create ns demo + namespace/demo created + ``` + +## Create a MongoDB database +KubeDB implements a MongoDB CRD to define the specification of a MongoDB database. + +You can apply this yaml file: + +```yaml +apiVersion: kubedb.com/v1alpha2 +kind: MongoDB +metadata: + name: mgo-quickstart + namespace: demo +spec: + version: "4.4.26" + replicaSet: + name: "rs1" + replicas: 3 + storageType: Durable + storage: + storageClassName: "standard" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + terminationPolicy: WipeOut +``` + +Command: + +```shell +$ kubectl apply -f mongobd.yaml +mongodb.kubedb.com/mgo-quickstart created +``` + +Or, you can deploy by using command: + +```shell +$ kubectl create -f https://github.com/kubedb/docs/raw/{{ .version }}/docs/examples/mongodb/quickstart/replicaset-v1alpha2.yaml +mongodb.kubedb.com/mgo-quickstart created +``` + +Now, wait until mgo-quickstart has status Ready. i.e, + +```shell +$ kubectl get mg -n demo -w +NAME VERSION STATUS AGE +mgo-quickstart 4.4.26 Ready 8m1s +``` +## Verify authentication +The user can verify whether they are authorized by executing a query directly in the database. To do this, the user needs `username` and `password` in order to connect to the database using the `kubectl exec` command. Below is an example showing how to retrieve the credentials from the secret. + +````shell +$ kubectl get mg -n demo mgo-quickstart -ojson | jq .spec.authsecret.name +"mgo-quickstart-auth" +$ kubectl get secret -n demo mgo-quickstart-auth -o=jsonpath='{.data.username}' | base64 -d +root⏎ +$ kubectl get secret -n demo mgo-quickstart-auth -o=jsonpath='{.data.password}' | base64 -d +eR*W_mz6bjyZxeiG⏎ +```` +Now, you can exec into the pod `mgo-quickstart` and connect to database using `username` and `password` +```shell +$ kubectl exec -it -n demo mgo-quickstart-0 -- bash +Defaulted container "mongodb" out of: mongodb, replication-mode-detector, copy-config (init) +mongodb@mgo-quickstart-0:/$ mongo -u root -p $MONGO_INITDB_ROOT_PASSWORD +MongoDB shell version v4.4.26 +connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb +Implicit session: session { "id" : UUID("dcd7f912-93d0-4f24-843d-5e2cbecbb6e0") } +MongoDB server version: 4.4.26 +Welcome to the MongoDB shell. +For interactive help, type "help". +For more comprehensive documentation, see + https://docs.mongodb.com/ +Questions? Try the MongoDB Developer Community Forums + https://community.mongodb.com +--- +The server generated these startup warnings when booting: + 2025-07-10T08:40:43.374+00:00: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine. See http://dochub.mongodb.org/core/prodnotes-filesystem +--- +rs1:SECONDARY> use Mohiniyattam +switched to db Mohiniyattam + +``` +If you can access the data table and run queries, it means the secrets are working correctly. +## Create RotateAuth MongoDBOpsRequest + +#### 1. Using operator generated credentials: + +In order to rotate authentication to the MongoDB using operator generated, we have to create a `MongoDBOpsRequest` CRO with `RotateAuth` type. Below is the YAML of the `MongoDBOpsRequest` CRO that we are going to create, +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: MongoDBOpsRequest +metadata: + name: mgops-rotate-auth-generated + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: mgo-quickstart + timeout: 5m + apply: IfReady +``` +Here, + +- `spec.databaseRef.name` specifies that we are performing rotate authentication operation on `mgo-quickstart` cluster. +- `spec.type` specifies that we are performing `RotateAuth` on MongoDB. + +Let's create the `MongoDBOpsRequest` CR we have shown above, +```shell + $ kubectl apply -f https://github.com/kubedb/docs/raw/{{ .version }}/docs/examples/mongodb/rotate-auth/rotate-auth-generated.yaml + mongodbopsrequest.ops.kubedb.com/mgops-rotate-auth-generated created +``` +Let's wait for `MongoDBOpsrequest` to be `Successful`. Run the following command to watch `MongoDBOpsrequest` CRO +```shell + $kubectl get mongodbopsrequest -n demo +NAME TYPE STATUS AGE +mgops-rotate-auth-generated RotateAuth Successful 45m +``` +If we describe the `MongoDBOpsRequest` we will get an overview of the steps that were followed. +```shell +$ kubectl describe mongodbopsrequest -n demo mgops-rotate-auth-generated +Name: mgops-rotate-auth-generated +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: MongoDBOpsRequest +Metadata: + Creation Timestamp: 2025-07-10T08:39:47Z + Generation: 1 + Resource Version: 607260 + UID: 20c8ac77-20b8-45b0-b213-a3f8f06cc379 +Spec: + Apply: IfReady + Database Ref: + Name: mgo-quickstart + Timeout: 5m + Type: RotateAuth +Status: + Conditions: + Last Transition Time: 2025-07-10T08:39:47Z + Message: MongoDB ops request has started to rotate auth for mongodb + Observed Generation: 1 + Reason: RotateAuth + Status: True + Type: RotateAuth + Last Transition Time: 2025-07-10T08:39:50Z + Message: Successfully generated new credentials + Observed Generation: 1 + Reason: UpdateCredential + Status: True + Type: UpdateCredential + Last Transition Time: 2025-07-10T08:39:55Z + Message: Successfully updated petsets rotate auth type + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2025-07-10T08:40:00Z + Message: check is master; ConditionStatus:True; PodName:mgo-quickstart-1 + Observed Generation: 1 + Status: True + Type: CheckIsMaster--mgo-quickstart-1 + Last Transition Time: 2025-07-10T08:40:00Z + Message: evict pod; ConditionStatus:True; PodName:mgo-quickstart-1 + Observed Generation: 1 + Status: True + Type: EvictPod--mgo-quickstart-1 + Last Transition Time: 2025-07-10T08:40:15Z + Message: check pod ready; ConditionStatus:True; PodName:mgo-quickstart-1 + Observed Generation: 1 + Status: True + Type: CheckPodReady--mgo-quickstart-1 + Last Transition Time: 2025-07-10T08:40:15Z + Message: check is master; ConditionStatus:True; PodName:mgo-quickstart-2 + Observed Generation: 1 + Status: True + Type: CheckIsMaster--mgo-quickstart-2 + Last Transition Time: 2025-07-10T08:40:15Z + Message: evict pod; ConditionStatus:True; PodName:mgo-quickstart-2 + Observed Generation: 1 + Status: True + Type: EvictPod--mgo-quickstart-2 + Last Transition Time: 2025-07-10T08:40:40Z + Message: check pod ready; ConditionStatus:True; PodName:mgo-quickstart-2 + Observed Generation: 1 + Status: True + Type: CheckPodReady--mgo-quickstart-2 + Last Transition Time: 2025-07-10T08:40:40Z + Message: check is master; ConditionStatus:True; PodName:mgo-quickstart-0 + Observed Generation: 1 + Status: True + Type: CheckIsMaster--mgo-quickstart-0 + Last Transition Time: 2025-07-10T08:40:40Z + Message: step down; ConditionStatus:True; PodName:mgo-quickstart-0 + Observed Generation: 1 + Status: True + Type: StepDown--mgo-quickstart-0 + Last Transition Time: 2025-07-10T08:40:40Z + Message: evict pod; ConditionStatus:True; PodName:mgo-quickstart-0 + Observed Generation: 1 + Status: True + Type: EvictPod--mgo-quickstart-0 + Last Transition Time: 2025-07-10T08:40:55Z + Message: check pod ready; ConditionStatus:True; PodName:mgo-quickstart-0 + Observed Generation: 1 + Status: True + Type: CheckPodReady--mgo-quickstart-0 + Last Transition Time: 2025-07-10T08:40:55Z + Message: Successfully Restarted ReplicaSet nodes + Observed Generation: 1 + Reason: RestartReplicaSet + Status: True + Type: RestartReplicaSet + Last Transition Time: 2025-07-10T08:40:55Z + Message: Successfully Rotate Auth + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal PauseDatabase 44m KubeDB Ops-manager Operator Pausing MongoDB demo/mgo-quickstart + Normal PauseDatabase 44m KubeDB Ops-manager Operator Successfully paused MongoDB demo/mgo-quickstart + Normal VersionUpdate 44m KubeDB Ops-manager Operator Updating PetSets + Normal VersionUpdate 44m KubeDB Ops-manager Operator Successfully Updated PetSets + Warning check is master; ConditionStatus:True; PodName:mgo-quickstart-1 44m KubeDB Ops-manager Operator check is master; ConditionStatus:True; PodName:mgo-quickstart-1 + Warning evict pod; ConditionStatus:True; PodName:mgo-quickstart-1 44m KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:mgo-quickstart-1 + Warning check pod ready; ConditionStatus:False; PodName:mgo-quickstart-1 44m KubeDB Ops-manager Operator check pod ready; ConditionStatus:False; PodName:mgo-quickstart-1 + Warning check pod ready; ConditionStatus:True; PodName:mgo-quickstart-1 44m KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:mgo-quickstart-1 + Warning check is master; ConditionStatus:True; PodName:mgo-quickstart-2 44m KubeDB Ops-manager Operator check is master; ConditionStatus:True; PodName:mgo-quickstart-2 + Warning evict pod; ConditionStatus:True; PodName:mgo-quickstart-2 44m KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:mgo-quickstart-2 + Warning check pod ready; ConditionStatus:False; PodName:mgo-quickstart-2 44m KubeDB Ops-manager Operator check pod ready; ConditionStatus:False; PodName:mgo-quickstart-2 + Warning check pod ready; ConditionStatus:True; PodName:mgo-quickstart-1 43m KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:mgo-quickstart-1 + Warning check pod ready; ConditionStatus:True; PodName:mgo-quickstart-1 43m KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:mgo-quickstart-1 + Warning check pod ready; ConditionStatus:True; PodName:mgo-quickstart-1 43m KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:mgo-quickstart-1 + Warning check pod ready; ConditionStatus:True; PodName:mgo-quickstart-1 43m KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:mgo-quickstart-1 + Warning check pod ready; ConditionStatus:True; PodName:mgo-quickstart-1 43m KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:mgo-quickstart-1 + Warning check pod ready; ConditionStatus:True; PodName:mgo-quickstart-2 43m KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:mgo-quickstart-2 + Warning check is master; ConditionStatus:True; PodName:mgo-quickstart-0 43m KubeDB Ops-manager Operator check is master; ConditionStatus:True; PodName:mgo-quickstart-0 + Warning step down; ConditionStatus:True; PodName:mgo-quickstart-0 43m KubeDB Ops-manager Operator step down; ConditionStatus:True; PodName:mgo-quickstart-0 + Warning evict pod; ConditionStatus:True; PodName:mgo-quickstart-0 43m KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:mgo-quickstart-0 + Warning check pod ready; ConditionStatus:False; PodName:mgo-quickstart-0 43m KubeDB Ops-manager Operator check pod ready; ConditionStatus:False; PodName:mgo-quickstart-0 + Warning check pod ready; ConditionStatus:True; PodName:mgo-quickstart-1 43m KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:mgo-quickstart-1 + Warning check pod ready; ConditionStatus:True; PodName:mgo-quickstart-2 43m KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:mgo-quickstart-2 + Warning check pod ready; ConditionStatus:True; PodName:mgo-quickstart-1 43m KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:mgo-quickstart-1 + Warning check pod ready; ConditionStatus:True; PodName:mgo-quickstart-2 43m KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:mgo-quickstart-2 + Warning check pod ready; ConditionStatus:True; PodName:mgo-quickstart-1 43m KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:mgo-quickstart-1 + Warning check pod ready; ConditionStatus:True; PodName:mgo-quickstart-2 43m KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:mgo-quickstart-2 + Warning check pod ready; ConditionStatus:True; PodName:mgo-quickstart-0 43m KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:mgo-quickstart-0 + Normal RestartReplicaSet 43m KubeDB Ops-manager Operator Successfully Restarted ReplicaSet nodes + Normal ResumeDatabase 43m KubeDB Ops-manager Operator Resuming MongoDB demo/mgo-quickstart + Normal ResumeDatabase 43m KubeDB Ops-manager Operator Successfully resumed MongoDB demo/mgo-quickstart + Normal Successful 43m KubeDB Ops-manager Operator Successfully Rotate Auth + +``` +**Verify Auth is rotated** +```shell +$ kubectl get mg -n demo mgo-quickstart -ojson | jq .spec.authsecret.name +"mgo-quickstart-auth" +$ kubectl get secret -n demo mgo-quickstart-auth -o=jsonpath='{.data.username}' | base64 -d +root⏎ +$ kubectl get secret -n demo mgo-quickstart-auth -o=jsonpath='{.data.password}' | base64 -d +09wZM.)t8kpwKF5z⏎ +``` +Also, there will be two more new keys in the secret that stores the previous credentials. The keys are `username.prev` and `password.prev`. You can find the secret and its data by running the following command: + +```shell +$ kubectl get secret -n demo mgo-quickstart-auth -o go-template='{{ index .data "username.prev" }}' | base64 -d +root⏎ +$ kubectl get secret -n demo mgo-quickstart-auth -o go-template='{{ index .data "password.prev" }}' | base64 -d +eR*W_mz6bjyZxeiG⏎ +``` +The above output shows that the password has been changed successfully. The previous username & password is stored for rollback purpose. +#### 2. Using user created credentials + +At first, we need to create a secret with kubernetes.io/basic-auth type using custom username and password. Below is the command to create a secret with kubernetes.io/basic-auth type, +> Note: `Username` must be `root` +```shell +$ kubectl create secret generic quick-mg-user-auth -n demo \ + --type=kubernetes.io/basic-auth \ + --from-literal=username=root \ + --from-literal=password=mongodb-secret +secret/quick-mg-user-auth created +``` +Now create a `MongoDBOpsRequest` with `RotateAuth` type. Below is the YAML of the `MongoDBOpsRequest` that we are going to create, + +```shell +apiVersion: ops.kubedb.com/v1alpha1 +kind: MongoDBOpsRequest +metadata: + name: mgops-rotate-auth-user + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: mgo-quickstart + authentication: + secretRef: + name: quick-mg-user-auth + timeout: 5m + apply: IfReady +``` +Here, + +- `spec.databaseRef.name` specifies that we are performing rotate authentication operation on `mgo-quickstart`cluster. +- `spec.type` specifies that we are performing `RotateAuth` on MongoDB. +- `spec.authentication.secretRef.name` specifies that we are using `quick-mg-user-auth` as `spec.authsecret.name` for authentication. + +Let's create the `MongoDBOpsRequest` CR we have shown above, + +```shell +$ kubectl apply -f https://github.com/kubedb/docs/raw/v2025.6.30/docs/examples/mongodb/rotate-auth/rotate-auth-user.yaml +mongodbopsrequest.ops.kubedb.com/mgops-rotate-auth-user created +``` +Let’s wait for `MongoDBOpsRequest` to be Successful. Run the following command to watch `MongoDBOpsRequest` CRO: + +```shell +$ kubectl get mongodbopsrequest -n demo +NAME TYPE STATUS AGE +mgops-rotate-auth-generated RotateAuth Successful 153m +mgops-rotate-auth-user RotateAuth Successful 59m +``` +We can see from the above output that the `MongoDBOpsRequest` has succeeded. If we describe the `MongoDBOpsRequest` we will get an overview of the steps that were followed. +```shell +$ kubectl describe mgops -n demo mgops-rotate-auth-user +Name: mgops-rotate-auth-user +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: MongoDBOpsRequest +Metadata: + Creation Timestamp: 2025-07-16T11:46:29Z + Generation: 1 + Resource Version: 810101 + UID: eec4365a-cc3d-4e40-b603-7d41b9fbe781 +Spec: + Apply: IfReady + Authentication: + secret Ref: + Name: quick-mg-user-auth + Database Ref: + Name: mgo-quickstart + Timeout: 5m + Type: RotateAuth +Status: + Conditions: + Last Transition Time: 2025-07-16T11:46:29Z + Message: MongoDB ops request has started to rotate auth for mongodb + Observed Generation: 1 + Reason: RotateAuth + Status: True + Type: RotateAuth + Last Transition Time: 2025-07-16T11:46:33Z + Message: Successfully referenced the user provided authsecret + Observed Generation: 1 + Reason: UpdateCredential + Status: True + Type: UpdateCredential + Last Transition Time: 2025-07-16T11:46:38Z + Message: Successfully updated petsets rotate auth type + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2025-07-16T11:46:43Z + Message: check is master; ConditionStatus:True; PodName:mgo-quickstart-1 + Observed Generation: 1 + Status: True + Type: CheckIsMaster--mgo-quickstart-1 + Last Transition Time: 2025-07-16T11:46:43Z + Message: evict pod; ConditionStatus:True; PodName:mgo-quickstart-1 + Observed Generation: 1 + Status: True + Type: EvictPod--mgo-quickstart-1 + Last Transition Time: 2025-07-16T11:46:58Z + Message: check pod ready; ConditionStatus:True; PodName:mgo-quickstart-1 + Observed Generation: 1 + Status: True + Type: CheckPodReady--mgo-quickstart-1 + Last Transition Time: 2025-07-16T11:46:58Z + Message: check is master; ConditionStatus:True; PodName:mgo-quickstart-2 + Observed Generation: 1 + Status: True + Type: CheckIsMaster--mgo-quickstart-2 + Last Transition Time: 2025-07-16T11:46:58Z + Message: evict pod; ConditionStatus:True; PodName:mgo-quickstart-2 + Observed Generation: 1 + Status: True + Type: EvictPod--mgo-quickstart-2 + Last Transition Time: 2025-07-16T11:47:13Z + Message: check pod ready; ConditionStatus:True; PodName:mgo-quickstart-2 + Observed Generation: 1 + Status: True + Type: CheckPodReady--mgo-quickstart-2 + Last Transition Time: 2025-07-16T11:47:13Z + Message: check is master; ConditionStatus:True; PodName:mgo-quickstart-0 + Observed Generation: 1 + Status: True + Type: CheckIsMaster--mgo-quickstart-0 + Last Transition Time: 2025-07-16T11:47:13Z + Message: step down; ConditionStatus:True; PodName:mgo-quickstart-0 + Observed Generation: 1 + Status: True + Type: StepDown--mgo-quickstart-0 + Last Transition Time: 2025-07-16T11:47:13Z + Message: evict pod; ConditionStatus:True; PodName:mgo-quickstart-0 + Observed Generation: 1 + Status: True + Type: EvictPod--mgo-quickstart-0 + Last Transition Time: 2025-07-16T11:47:28Z + Message: check pod ready; ConditionStatus:True; PodName:mgo-quickstart-0 + Observed Generation: 1 + Status: True + Type: CheckPodReady--mgo-quickstart-0 + Last Transition Time: 2025-07-16T11:47:28Z + Message: Successfully Restarted ReplicaSet nodes + Observed Generation: 1 + Reason: RestartReplicaSet + Status: True + Type: RestartReplicaSet + Last Transition Time: 2025-07-16T11:47:28Z + Message: Successfully Rotate Auth + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal PauseDatabase 6m20s KubeDB Ops-manager Operator Pausing MongoDB demo/mgo-quickstart + Normal PauseDatabase 6m20s KubeDB Ops-manager Operator Successfully paused MongoDB demo/mgo-quickstart + Normal VersionUpdate 6m16s KubeDB Ops-manager Operator Updating PetSets + Normal VersionUpdate 6m11s KubeDB Ops-manager Operator Successfully Updated PetSets + Warning check is master; ConditionStatus:True; PodName:mgo-quickstart-1 6m6s KubeDB Ops-manager Operator check is master; ConditionStatus:True; PodName:mgo-quickstart-1 + Warning evict pod; ConditionStatus:True; PodName:mgo-quickstart-1 6m6s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:mgo-quickstart-1 + Warning check pod ready; ConditionStatus:False; PodName:mgo-quickstart-1 6m6s KubeDB Ops-manager Operator check pod ready; ConditionStatus:False; PodName:mgo-quickstart-1 + Warning check pod ready; ConditionStatus:True; PodName:mgo-quickstart-1 5m51s KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:mgo-quickstart-1 + Warning check is master; ConditionStatus:True; PodName:mgo-quickstart-2 5m51s KubeDB Ops-manager Operator check is master; ConditionStatus:True; PodName:mgo-quickstart-2 + Warning evict pod; ConditionStatus:True; PodName:mgo-quickstart-2 5m51s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:mgo-quickstart-2 + Warning check pod ready; ConditionStatus:False; PodName:mgo-quickstart-2 5m51s KubeDB Ops-manager Operator check pod ready; ConditionStatus:False; PodName:mgo-quickstart-2 + Warning check pod ready; ConditionStatus:True; PodName:mgo-quickstart-1 5m46s KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:mgo-quickstart-1 + Warning check pod ready; ConditionStatus:True; PodName:mgo-quickstart-1 5m41s KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:mgo-quickstart-1 + Warning check pod ready; ConditionStatus:True; PodName:mgo-quickstart-1 5m36s KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:mgo-quickstart-1 + Warning check pod ready; ConditionStatus:True; PodName:mgo-quickstart-2 5m36s KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:mgo-quickstart-2 + Warning check is master; ConditionStatus:True; PodName:mgo-quickstart-0 5m36s KubeDB Ops-manager Operator check is master; ConditionStatus:True; PodName:mgo-quickstart-0 + Warning step down; ConditionStatus:True; PodName:mgo-quickstart-0 5m36s KubeDB Ops-manager Operator step down; ConditionStatus:True; PodName:mgo-quickstart-0 + Warning evict pod; ConditionStatus:True; PodName:mgo-quickstart-0 5m36s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:mgo-quickstart-0 + Warning check pod ready; ConditionStatus:False; PodName:mgo-quickstart-0 5m36s KubeDB Ops-manager Operator check pod ready; ConditionStatus:False; PodName:mgo-quickstart-0 + Warning check pod ready; ConditionStatus:True; PodName:mgo-quickstart-1 5m31s KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:mgo-quickstart-1 + Warning check pod ready; ConditionStatus:True; PodName:mgo-quickstart-2 5m31s KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:mgo-quickstart-2 + Warning check pod ready; ConditionStatus:True; PodName:mgo-quickstart-1 5m26s KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:mgo-quickstart-1 + Warning check pod ready; ConditionStatus:True; PodName:mgo-quickstart-2 5m26s KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:mgo-quickstart-2 + Warning check pod ready; ConditionStatus:True; PodName:mgo-quickstart-1 5m21s KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:mgo-quickstart-1 + Warning check pod ready; ConditionStatus:True; PodName:mgo-quickstart-2 5m21s KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:mgo-quickstart-2 + Warning check pod ready; ConditionStatus:True; PodName:mgo-quickstart-0 5m21s KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:mgo-quickstart-0 + Normal RestartReplicaSet 5m21s KubeDB Ops-manager Operator Successfully Restarted ReplicaSet nodes + Normal ResumeDatabase 5m21s KubeDB Ops-manager Operator Resuming MongoDB demo/mgo-quickstart + Normal ResumeDatabase 5m21s KubeDB Ops-manager Operator Successfully resumed MongoDB demo/mgo-quickstart + Normal Successful 5m21s KubeDB Ops-manager Operator Successfully Rotate Auth + +``` +**Verify auth is rotate** +```shell +$ kubectl get mg -n demo mgo-quickstart -ojson | jq .spec.authsecret.name +"quick-mg-user-auth" +$ kubectl get secret -n demo quick-mg-user-auth -o=jsonpath='{.data.username}' | base64 -d +root⏎ +$ kubectl get secret -n demo quick-mg-user-auth -o=jsonpath='{.data.password}' | base64 -d +mongodb-secret⏎ +``` +Also, there will be two more new keys in the secret that stores the previous credentials. The keys are `username.prev` and `password.prev`. You can find the secret and its data by running the following command: +```shell +$ kubectl get secret -n demo quick-mg-user-auth -o go-template='{{ index .data "username.prev" }}' | base64 -d +root⏎ +$ kubectl get secret -n demo quick-mg-user-auth -o go-template='{{ index .data "password.prev" }}' | base64 -d +09wZM.)t8kpwKF5z⏎ +``` + +The above output shows that the password has been changed successfully. The previous username & password is stored in the secret for rollback purpose. + +## Cleaning up + +To clean up the Kubernetes resources you can delete the CRD or namespace. +Or, you can delete one by one resource by their name by this tutorial, run: + +```shell +$ kubectl delete mongodbopsrequest mgops-rotate-auth-generated mgops-rotate-auth-user -n demo +mongodbopsrequest.ops.kubedb.com "mgops-rotate-auth-generated" "mgops-rotate-auth-user" deleted +$ kubectl delete secret -n demo quick-mg-user-auth +secret "quick-mg-user-auth" deleted +$ kubectl delete secret -n demo mgo-quickstart-auth +secret "mgo-quickstart-auth" deleted +``` + + +## Next Steps + +- Detail concepts of [MongoDB object](/docs/guides/mongodb/concepts/mongodb.md). +- Initialize [MongoDB with Script](/docs/guides/mongodb/initialization/using-script.md). +- Monitor your MongoDB database with KubeDB using [out-of-the-box Prometheus operator](/docs/guides/mongodb/monitoring/using-prometheus-operator.md). +- Monitor your MongoDB database with KubeDB using [out-of-the-box builtin-Prometheus](/docs/guides/mongodb/monitoring/using-builtin-prometheus.md). +- Use [private Docker registry](/docs/guides/mongodb/private-registry/using-private-registry.md) to deploy MongoDB with KubeDB. +- Use [kubedb cli](/docs/guides/mongodb/cli/cli.md) to manage databases like kubectl for Kubernetes. +- Detail concepts of [MongoDB object](/docs/guides/mongodb/concepts/mongodb.md). +- Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md). + diff --git a/docs/guides/mongodb/scaling/_index.md b/docs/guides/mongodb/scaling/_index.md index f0c30b4197..1584310e3f 100644 --- a/docs/guides/mongodb/scaling/_index.md +++ b/docs/guides/mongodb/scaling/_index.md @@ -6,5 +6,5 @@ menu: name: Scaling parent: mg-mongodb-guides weight: 43 -menu_name: docs_{{ .version }} +menu_name: docs_{{ .version }}** --- \ No newline at end of file diff --git a/docs/guides/mssqlserver/rotate-auth/_index.md b/docs/guides/mssqlserver/rotate-auth/_index.md new file mode 100644 index 0000000000..2efb00a7f2 --- /dev/null +++ b/docs/guides/mssqlserver/rotate-auth/_index.md @@ -0,0 +1,10 @@ +--- +title: Rotate Authentication MSSQLServer +menu: + docs_{{ .version }}: + identifier: ms-rotate-auth + name: Rotate Authentication + parent: guides-mssqlserver + weight: 86 +menu_name: docs_{{ .version }} +--- diff --git a/docs/guides/mssqlserver/rotate-auth/rotateauth.md b/docs/guides/mssqlserver/rotate-auth/rotateauth.md new file mode 100644 index 0000000000..b576e8e9ea --- /dev/null +++ b/docs/guides/mssqlserver/rotate-auth/rotateauth.md @@ -0,0 +1,549 @@ +--- +title: Rotate Authentication Guide +menu: + docs_{{ .version }}: + identifier: ms-rotate-auth-guide + name: Guide + parent: ms-rotate-auth + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- +# Rotate Authentication of MSSQLServer + +**Rotate Authentication** is a feature of the KubeDB Ops-Manager that allows you to rotate a `MSSQLServer` user's authentication credentials using a `MSSQLServerOpsRequest`. There are two ways to perform this rotation. + +1. **Operator Generated:** The KubeDB operator automatically generates a random credential and updates the existing secret with the new credential. +2. **User Defined:** The user can create their own credentials by defining a secret of type +`kubernetes.io/basic-auth` containing the desired `password`, and then reference this secret in the +`MSSQLServerOpsRequest` CR. + +## Before You Begin + +- You need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Now, install KubeDB cli on your workstation and KubeDB operator in your cluster following the steps [here](/docs/setup/README.md). Make sure install with helm command including `--set global.featureGates.MSSQLServer=true` to ensure MSSQLServer CRD installation. + +- To configure TLS/SSL in `MSSQLServer`, `KubeDB` uses `cert-manager` to issue certificates. So first you have to make sure that the cluster has `cert-manager` installed. To install `cert-manager` in your cluster following steps [here](https://cert-manager.io/docs/installation/kubernetes/). + +- You should be familiar with the following `KubeDB` concepts: + - [MSSQLServer](/docs/guides/mssqlserver/concepts/mssqlserver.md) + - [MSSQLServerOpsRequest](/docs/guides/mssqlserver/concepts/opsrequest.md) + +To keep everything isolated, we are going to use a separate namespace called `demo` throughout this tutorial. + +```bash +$ kubectl create ns demo +namespace/demo created +``` + +> **Note:** YAML files used in this tutorial are stored in [docs/examples/mssqlserver](/docs/examples/mssqlserver/rotate-auth) directory of [kubedb/docs](https://github.com/kube/docs) repository. + +### Prepare MSSQLServer Standalone Database + +As pre-requisite, at first, we are going to create an Issuer/ClusterIssuer. This Issuer/ClusterIssuer is used to create certificates. Then we are going to deploy a SQL Server. + +### Create Issuer/ClusterIssuer + +Now, we are going to create an example `Issuer` that will be used throughout the duration of this tutorial. Alternatively, you can follow this [cert-manager tutorial](https://cert-manager.io/docs/configuration/ca/) to create your own `Issuer`. By following the below steps, we are going to create our desired issuer, + +- Start off by generating our ca-certificates using openssl, +```bash +openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./ca.key -out ./ca.crt -subj "/CN=MSSQLServer/O=kubedb" +``` +- +- Create a secret using the certificate files we have just generated, +```bash +$ kubectl create secret tls mssqlserver-ca --cert=ca.crt --key=ca.key --namespace=demo +secret/mssqlserver-ca created +``` +Now, we are going to create an `Issuer` using the `mssqlserver-ca` secret that contains the ca-certificate we have just created. Below is the YAML of the `Issuer` CR that we are going to create, + +```yaml +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: mssqlserver-ca-issuer + namespace: demo +spec: + ca: + secretName: mssqlserver-ca +``` + +Let’s create the `Issuer` CR we have shown above, +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/standalone/mssqlserver-ca-issuer.yaml +issuer.cert-manager.io/mssqlserver-ca-issuer created +``` + +### Deploy Standalone Microsoft SQL Server +KubeDB implements a `MSSQLServer` CRD to define the specification of a Microsoft SQL Server database. Below is the `MSSQLServer` object created in this tutorial. + +Here, our issuer `mssqlserver-ca-issuer` is ready to deploy a `MSSQLServer`. Below is the YAML of SQL Server that we are going to create, + + + +```yaml +apiVersion: kubedb.com/v1alpha2 +kind: MSSQLServer +metadata: + name: mssqlserver-quickstart + namespace: demo +spec: + version: "2022-cu12" + replicas: 1 + storageType: Durable + tls: + issuerRef: + name: mssqlserver-ca-issuer + kind: Issuer + apiGroup: "cert-manager.io" + clientTLS: false + podTemplate: + spec: + containers: + - name: mssql + env: + - name: ACCEPT_EULA + value: "Y" + - name: MSSQL_PID + value: Evaluation # Change it + storage: + storageClassName: "standard" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: WipeOut +``` + +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/mssqlserver/quickstart/mssqlserver-quickstart.yaml +mssqlserver.kubedb.com/mssqlserver-quickstart created +``` +Now, wait until mssqlserver-quickstart has status Ready. i.e, + +```shell +$ kubectl get ms -n demo -w +NAME VERSION STATUS AGE +mssqlserver-quickstart 2022-cu12 Ready 75m +``` +## Verify authentication +The user can verify whether they are authorized by executing a query directly in the database. To do this, the user needs `username` and `password` in order to connect to the database. Below is an example showing how to retrieve the credentials from the secret. + +````shell +$ kubectl get ms -n demo mssqlserver-quickstart -ojson | jq .spec.authsecret.name +"mssqlserver-quickstart-auth" +$ kubectl get secret -n demo mssqlserver-quickstart-auth -o jsonpath='{.data.username}' | base64 -d +sa⏎ +$ kubectl get secret -n demo mssqlserver-quickstart-auth -o jsonpath='{.data.password}' | base64 -d +9ycCSYznZpZRxs9U⏎ +```` +Now, you can exec into the pod `mssqlserver-quickstart-0` and connect to database using `username` and `password` +```bash +$ kubectl exec -it -n demo mssqlserver-quickstart-0 -c mssql -- bash +mssql@mssqlserver-quickstart-0:/$ /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P "9ycCSYznZpZRxs9U" +1> select name from sys.databases +2> go +name +---------------------------------------------------------------------------------- +master +tempdb +model +msdb +kubedb_system + +(5 rows affected) +1> +1> exit +mssql@mssqlserver-quickstart-0:/$ exit +exit +⏎ +``` + +If you can access the data table and run queries, it means the secrets are working correctly. +## Create RotateAuth MSSQLServerOpsRequest + +#### 1. Using operator generated credentials: + +In order to rotate authentication to the MSSQLServer using operator generated, we have to create a `MSSQLServerOpsRequest` CRO with `RotateAuth` type. Below is the YAML of the `MSSQLServerOpsRequest` CRO that we are going to create, +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: MSSQLServerOpsRequest +metadata: + name: msops-rotate-auth-generated + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: mssqlserver-quickstart + timeout: 5m + apply: IfReady +``` +Here, + +- `spec.databaseRef.name` specifies that we are performing rotate authentication operation on `mssqlserver-quickstart` cluster. +- `spec.type` specifies that we are performing `RotateAuth` on MSSQLServer. + +Let's create the `MSSQLServerOpsRequest` CR we have shown above, +```shell + $ kubectl apply -f https://github.com/kubedb/docs/raw/{{ .version }}/docs/examples/mssqlserver/rotate-auth/rotate-auth-generated.yaml + MSSQLServeropsrequest.ops.kubedb.com/msops-rotate-auth-generated created +``` +Let's wait for `MSSQLServerOpsrequest` to be `Successful`. Run the following command to watch `MSSQLServerOpsrequest` CRO +```shell + $ kubectl get MSSQLServeropsrequest -n demo + NAME TYPE STATUS AGE + msops-rotate-auth-generated RotateAuth Successful 7m47s +``` +If we describe the `MSSQLServerOpsRequest` we will get an overview of the steps that were followed. +```shell +$ kubectl describe MSSQLServeropsrequest -n demo msops-rotate-auth-generated +Name: msops-rotate-auth-generated +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: MSSQLServerOpsRequest +Metadata: + Creation Timestamp: 2025-07-15T10:59:19Z + Generation: 1 + Resource Version: 748399 + UID: 05d2adb0-9adb-497c-95ce-b278ca41dd70 +Spec: + Apply: IfReady + Database Ref: + Name: mssqlserver-quickstart + Timeout: 5m + Type: RotateAuth +Status: + Conditions: + Last Transition Time: 2025-07-15T10:59:19Z + Message: MSSQLServer ops-request has started to rotate auth for mssqlserver nodes + Observed Generation: 1 + Reason: RotateAuth + Status: True + Type: RotateAuth + Last Transition Time: 2025-07-15T10:59:22Z + Message: Successfully paused database + Observed Generation: 1 + Reason: DatabasePauseSucceeded + Status: True + Type: DatabasePauseSucceeded + Last Transition Time: 2025-07-15T10:59:22Z + Message: Successfully generated new credentials + Observed Generation: 1 + Reason: UpdateCredential + Status: True + Type: UpdateCredential + Last Transition Time: 2025-07-15T11:00:29Z + Message: successfully reconciled the MSSQLServer with updated credentials + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2025-07-15T11:01:15Z + Message: Successfully restarted all nodes + Observed Generation: 1 + Reason: RestartNodes + Status: True + Type: RestartNodes + Last Transition Time: 2025-07-15T11:00:35Z + Message: get pod; ConditionStatus:True; PodName:mssqlserver-quickstart-0 + Observed Generation: 1 + Status: True + Type: GetPod--mssqlserver-quickstart-0 + Last Transition Time: 2025-07-15T11:00:35Z + Message: evict pod; ConditionStatus:True; PodName:mssqlserver-quickstart-0 + Observed Generation: 1 + Status: True + Type: EvictPod--mssqlserver-quickstart-0 + Last Transition Time: 2025-07-15T11:01:10Z + Message: check pod running; ConditionStatus:True; PodName:mssqlserver-quickstart-0 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--mssqlserver-quickstart-0 + Last Transition Time: 2025-07-15T11:01:15Z + Message: Successfully completed mssqlserver auth rotate + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Starting 19m KubeDB Ops-manager Operator Start processing for MSSQLServerOpsRequest: demo/msops-rotate-auth-generated + Normal Starting 19m KubeDB Ops-manager Operator Pausing MSSQLServer database: demo/mssqlserver-quickstart + Normal Successful 19m KubeDB Ops-manager Operator Successfully paused MSSQLServer database: demo/mssqlserver-quickstart for MSSQLServerOpsRequest: msops-rotate-auth-generated + Normal UpdatePetSets 18m KubeDB Ops-manager Operator successfully reconciled the MSSQLServer with updated credentials + Warning get pod; ConditionStatus:True; PodName:mssqlserver-quickstart-0 18m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:mssqlserver-quickstart-0 + Warning evict pod; ConditionStatus:True; PodName:mssqlserver-quickstart-0 18m KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:mssqlserver-quickstart-0 + Warning check pod running; ConditionStatus:False; PodName:mssqlserver-quickstart-0 18m KubeDB Ops-manager Operator check pod running; ConditionStatus:False; PodName:mssqlserver-quickstart-0 + Warning check pod running; ConditionStatus:True; PodName:mssqlserver-quickstart-0 17m KubeDB Ops-manager Operator check pod running; ConditionStatus:True; PodName:mssqlserver-quickstart-0 + Normal RestartNodes 17m KubeDB Ops-manager Operator Successfully restarted all nodes + Normal Starting 17m KubeDB Ops-manager Operator Resuming MSSQLServer database: demo/mssqlserver-quickstart + Normal Successful 17m KubeDB Ops-manager Operator Successfully resumed MSSQLServer database: demo/mssqlserver-quickstart for MSSQLServerOpsRequest: msops-rotate-auth-generated + Normal UpdatePetSets 17m KubeDB Ops-manager Operator successfully reconciled the MSSQLServer with updated credentials + +``` +**Verify Auth is rotated** +```shell +$ kubectl get ms -n demo mssqlserver-quickstart -ojson | jq .spec.authsecret.name +"mssqlserver-quickstart-auth" +$ kubectl get secret -n demo mssqlserver-quickstart-auth -o jsonpath='{.data.username}' | base64 -d +sa⏎ +$ kubectl get secret -n demo mssqlserver-quickstart-auth -o jsonpath='{.data.password}' | base64 -d +zTBVvzgoEb2qUe3X⏎ +``` +Let's verify if we can connect to the database using the new credentials. + +```shell +$ kubectl exec -it -n demo mssqlserver-quickstart-0 -c mssql -- bash +mssql@mssqlserver-quickstart-0:/$ /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P "zTBVvzgoEb2qUe3X" +1> select name from sys.databases +2> go +name +-------------------------------------------------------------------------------------------------------------------------------- +master +tempdb +model +msdb +kubedb_system + +(5 rows affected) +1> exit +mssql@mssqlserver-quickstart-0:/$ exit +exit +⏎ +``` + +Also, there will be two more new keys in the secret that stores the previous credentials. The keys are `username.prev` and `password.prev`. You can find the secret and its data by running the following command: + +```shell +$ kubectl get secret -n demo mssqlserver-quickstart-auth -o go-template='{{ index .data "username.prev" }}' | base64 -d +sa⏎ +$ kubectl get secret -n demo mssqlserver-quickstart-auth -o go-template='{{ index .data "password.prev" }}' | base64 -d +9ycCSYznZpZRxs9U⏎ +``` +Let's confirm that the previous credentials no longer work. +```shell +kubectl exec -it -n demo mssqlserver-quickstart-0 -c mssql -- bash +mssql@mssqlserver-quickstart-0:/$ /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P "9ycCSYznZpZRxs9U" +Sqlcmd: Error: Microsoft ODBC Driver 17 for SQL Server : Login failed for user 'sa'.. +mssql@mssqlserver-quickstart-0:/$ + +``` +The above output shows that the password has been changed successfully. The previous username & password is stored for rollback purpose. +#### 2. Using user created credentials + +At first, we need to create a secret with kubernetes.io/basic-auth type using custom username and password. Below is the command to create a secret with kubernetes.io/basic-auth type, +> Note: The `username` must be fixed as `sa`. The `password` must include uppercase letters, lowercase letters, and numbers +```shell +$ kubectl create secret generic mssqlserver-quickstart-auth-user -n demo \ + --type=kubernetes.io/basic-auth \ + --from-literal=username=sa \ + --from-literal=password=Mssqlserver2 +secret/mssqlserver-quickstart-auth-user created + +``` +Now create a `MSSQLServerOpsRequest` with `RotateAuth` type. Below is the YAML of the `MSSQLServerOpsRequest` that we are going to create, + +```shell +apiVersion: ops.kubedb.com/v1alpha1 +kind: MSSQLServerOpsRequest +metadata: + name: msops-rotate-auth-user + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: mssqlserver-quickstart + authentication: + secretRef: + name: mssqlserver-quickstart-auth-user + timeout: 5m + apply: IfReady +``` +Here, + +- `spec.databaseRef.name` specifies that we are performing rotate authentication operation on `mssqlserver-quickstart`cluster. +- `spec.type` specifies that we are performing `RotateAuth` on MSSQLServer. +- `spec.authentication.secretRef.name` specifies that we want to use `mssqlserver-quickstart-auth` for database authentication. + + +Let's create the `MSSQLServerOpsRequest` CR we have shown above, + +```shell +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{ .version }}/docs/examples/mssqlserver/rotate-auth/rotate-auth-user.yaml +MSSQLServeropsrequest.ops.kubedb.com/msops-rotate-auth-user created +``` +Let’s wait for `MSSQLServerOpsRequest` to be Successful. Run the following command to watch `MSSQLServerOpsRequest` CRO: + +```shell +$ kubectl get MSSQLServeropsrequest -n demo +NAME TYPE STATUS AGE +msops-rotate-auth-generated RotateAuth Successful 19h +msops-rotate-auth-user RotateAuth Successful 7m44s +``` +We can see from the above output that the `MSSQLServerOpsRequest` has succeeded. If we describe the `MSSQLServerOpsRequest` we will get an overview of the steps that were followed. +```shell +$ kubectl describe MSSQLServeropsrequest -n demo msops-rotate-auth-user +Name: msops-rotate-auth-user +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: MSSQLServerOpsRequest +Metadata: + Creation Timestamp: 2025-07-15T11:03:16Z + Generation: 1 + Resource Version: 748850 + UID: 9928916d-ba08-4d3a-a5a9-afa3cea4ee90 +Spec: + Apply: IfReady + Authentication: + secret Ref: + Name: mssqlserver-quickstart-auth + Database Ref: + Name: mssqlserver-quickstart + Timeout: 5m + Type: RotateAuth +Status: + Conditions: + Last Transition Time: 2025-07-15T11:03:16Z + Message: MSSQLServer ops-request has started to rotate auth for mssqlserver nodes + Observed Generation: 1 + Reason: RotateAuth + Status: True + Type: RotateAuth + Last Transition Time: 2025-07-15T11:03:19Z + Message: Successfully paused database + Observed Generation: 1 + Reason: DatabasePauseSucceeded + Status: True + Type: DatabasePauseSucceeded + Last Transition Time: 2025-07-15T11:03:19Z + Message: Successfully referenced the user provided authsecret + Observed Generation: 1 + Reason: UpdateCredential + Status: True + Type: UpdateCredential + Last Transition Time: 2025-07-15T11:04:26Z + Message: successfully reconciled the MSSQLServer with updated credentials + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2025-07-15T11:05:11Z + Message: Successfully restarted all nodes + Observed Generation: 1 + Reason: RestartNodes + Status: True + Type: RestartNodes + Last Transition Time: 2025-07-15T11:04:31Z + Message: get pod; ConditionStatus:True; PodName:mssqlserver-quickstart-0 + Observed Generation: 1 + Status: True + Type: GetPod--mssqlserver-quickstart-0 + Last Transition Time: 2025-07-15T11:04:31Z + Message: evict pod; ConditionStatus:True; PodName:mssqlserver-quickstart-0 + Observed Generation: 1 + Status: True + Type: EvictPod--mssqlserver-quickstart-0 + Last Transition Time: 2025-07-15T11:05:06Z + Message: check pod running; ConditionStatus:True; PodName:mssqlserver-quickstart-0 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--mssqlserver-quickstart-0 + Last Transition Time: 2025-07-15T11:05:11Z + Message: Successfully completed mssqlserver auth rotate + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Starting 16m KubeDB Ops-manager Operator Start processing for MSSQLServerOpsRequest: demo/msops-rotate-auth-user + Normal Starting 16m KubeDB Ops-manager Operator Pausing MSSQLServer database: demo/mssqlserver-quickstart + Normal Successful 16m KubeDB Ops-manager Operator Successfully paused MSSQLServer database: demo/mssqlserver-quickstart for MSSQLServerOpsRequest: msops-rotate-auth-user + Normal UpdatePetSets 15m KubeDB Ops-manager Operator successfully reconciled the MSSQLServer with updated credentials + Warning get pod; ConditionStatus:True; PodName:mssqlserver-quickstart-0 15m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:mssqlserver-quickstart-0 + Warning evict pod; ConditionStatus:True; PodName:mssqlserver-quickstart-0 15m KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:mssqlserver-quickstart-0 + Warning check pod running; ConditionStatus:False; PodName:mssqlserver-quickstart-0 15m KubeDB Ops-manager Operator check pod running; ConditionStatus:False; PodName:mssqlserver-quickstart-0 + Warning check pod running; ConditionStatus:True; PodName:mssqlserver-quickstart-0 14m KubeDB Ops-manager Operator check pod running; ConditionStatus:True; PodName:mssqlserver-quickstart-0 + Normal RestartNodes 14m KubeDB Ops-manager Operator Successfully restarted all nodes + Normal Starting 14m KubeDB Ops-manager Operator Resuming MSSQLServer database: demo/mssqlserver-quickstart + Normal Successful 14m KubeDB Ops-manager Operator Successfully resumed MSSQLServer database: demo/mssqlserver-quickstart for MSSQLServerOpsRequest: msops-rotate-auth-user + +``` +**Verify auth is rotate** +```shell +$ kubectl get ms -n demo mssqlserver-quickstart -ojson | jq .spec.authsecret.name +"mssqlserver-quickstart-auth " +$ kubectl get secret -n demo mssqlserver-quickstart-auth -o=jsonpath='{.data.username}' | base64 -d +sa⏎ +$ kubectl get secret -n demo mssqlserver-quickstart-auth -o jsonpath='{.data.password}' | base64 -d +Mssqlserver2⏎ +``` + +Let's verify if we can connect to the database using the new credentials. +```shell +$ kubectl exec -it -n demo mssqlserver-quickstart-0 -c mssql -- bash +mssql@mssqlserver-quickstart-0:/$ /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P "Mssqlserver2" +1> SELECT name FROM sys.databases +2> go +name +-------------------------------------------------------------------------------------------------------------------------------- +master +tempdb +model +msdb +kubedb_system + +(5 rows affected) +1> +``` +Also, there will be two more new keys in the secret that stores the previous credentials. The keys are `username.prev` and `password.prev`. You can find the secret and its data by running the following command: +```shell +$ kubectl get secret -n demo mssqlserver-quickstart-auth -o go-template='{{ index .data "username.prev" }}' | base64 -d +sa⏎ +$ kubectl get secret -n demo quick-mssqlserver-user-auth -o go-template='{{ index .data "password.prev" }}' | base64 -d +zTBVvzgoEb2qUe3X⏎ +``` +Let's confirm that the previous credentials no longer work. +```shell +kubectl exec -it -n demo mssqlserver-quickstart-0 -c mssql -- bash +mssql@mssqlserver-quickstart-0:/$ /opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P "zTBVvzgoEb2qUe3X" +Sqlcmd: Error: Microsoft ODBC Driver 17 for SQL Server : Login failed for user 'sa'.. +mssql@mssqlserver-quickstart-0:/$ + +``` +The above output shows that the password has been changed successfully. The previous username & password is stored in the secret for rollback purpose. + +## Cleaning up + +To clean up the Kubernetes resources you can delete the CRD or namespace. +Or, you can delete one by one resource by their name by this tutorial, run: + +```shell +$ kubectl delete MSSQLServeropsrequest msops-rotate-auth-generated msops-rotate-auth-user -n demo +MSSQLServeropsrequest.ops.kubedb.com "msops-rotate-auth-generated" "msops-rotate-auth-user" deleted +$ kubectl delete secret -n demoquick-mssqlserver-user-auth +secret "quick-mssqlserver-user-auth" deleted +$ kubectl delete secret -n demo mssqlserver-quickstart-auth +secret "mssqlserver-quickstart-auth " deleted + +``` + +## Next Steps + +- Learn about [backup and restore](/docs/guides/mssqlserver/backup/overview/index.md) SQL Server using KubeStash. +- Want to set up SQL Server Availability Group clusters? Check how to [Configure SQL Server Availability Gruop Cluster](/docs/guides/mssqlserver/clustering/ag_cluster.md) +- Detail concepts of [MSSQLServer object](/docs/guides/mssqlserver/concepts/mssqlserver.md). +- Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md). diff --git a/docs/guides/mysql/failure-and-disaster-recovery/overview.md b/docs/guides/mysql/failure-and-disaster-recovery/overview.md index 732c90fba8..2e44ce981f 100644 --- a/docs/guides/mysql/failure-and-disaster-recovery/overview.md +++ b/docs/guides/mysql/failure-and-disaster-recovery/overview.md @@ -34,11 +34,25 @@ But that is a bit rare though. ### Before You Start -To follow along with this tutorial, you will need: -1. A running Kubernetes cluster. -2. KubeDB [installed](https://kubedb.com/docs/{{}}/setup/install/kubedb/) in your cluster. -3. kubectl command-line tool configured to communicate with your cluster. +- At first, you need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Now, install KubeDB cli on your workstation and KubeDB operator in your cluster following the steps [here](/docs/setup/README.md). + +- [StorageClass](https://kubernetes.io/docs/concepts/storage/storage-classes/) is required to run KubeDB. Check the available StorageClass in cluster. + + ```bash + $ kubectl get storageclasses + NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE + standard (default) rancher.io/local-path Delete WaitForFirstConsumer false 6h22m + ``` + +- To keep things isolated, this tutorial uses a separate namespace called `demo` throughout this tutorial. + + ```bash + $ kubectl create ns demo + namespace/demo created + ``` ### Step 1: Create a High-Availability MySQL Cluster diff --git a/docs/guides/mysql/rotate-auth/_index.md b/docs/guides/mysql/rotate-auth/_index.md new file mode 100644 index 0000000000..a0708e5797 --- /dev/null +++ b/docs/guides/mysql/rotate-auth/_index.md @@ -0,0 +1,10 @@ +--- +title: Rotateauth MySQL +menu: + docs_{{ .version }}: + identifier: guides-mysql-rotate-auth + name: Rotate Authentication + parent: guides-mysql + weight: 43 +menu_name: docs_{{ .version }} +--- diff --git a/docs/guides/mysql/rotate-auth/guide.md b/docs/guides/mysql/rotate-auth/guide.md new file mode 100644 index 0000000000..0606587965 --- /dev/null +++ b/docs/guides/mysql/rotate-auth/guide.md @@ -0,0 +1,547 @@ +--- +title: MySQL Rotateauth Guide +menu: + docs_{{ .version }}: + identifier: guides-mysql-rotate-auth-guide + name: Guide + parent: guides-mysql-rotate-auth + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +# Rotate Authentication of MySQL + +**Rotate Authentication** is a feature of the KubeDB Ops-Manager that allows you to rotate a `MySQL` +user's authentication credentials using a `MySQLOpsrequest`. There are two ways to perform this +rotation. + +1. **Operator Generated:** The KubeDB operator automatically generates a random credential and +updates the existing secret with the new credential. +2. **User Defined:** The user can create their own credentials by defining a secret of type + `kubernetes.io/basic-auth` containing the desired `password` and then reference this secret in the + `MySQLOpsrequest` CR. + +## Before You Begin + +- At first, you need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Now, install KubeDB cli on your workstation and KubeDB operator in your cluster following the steps [here](/docs/setup/README.md). + +- [StorageClass](https://kubernetes.io/docs/concepts/storage/storage-classes/) is required to run KubeDB. Check the available StorageClass in cluster. + + ```bash + $ kubectl get storageclasses + NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE + standard (default) rancher.io/local-path Delete WaitForFirstConsumer false 6h22m + ``` + +- To keep things isolated, this tutorial uses a separate namespace called `demo` throughout this tutorial. + + ```bash + $ kubectl create ns demo + namespace/demo created + ``` + +## Find Available MySQLVersion + +When you have installed KubeDB, it has created `MySQLVersion` crd for all supported MySQL versions. Check it by using the following command, + +```bash +$ kubectl get mysqlversion +NAME VERSION DISTRIBUTION DB_IMAGE DEPRECATED AGE +5.7.42-debian 5.7.42 Official ghcr.io/appscode-images/mysql:5.7.42-debian 12d +5.7.44 5.7.44 Official ghcr.io/appscode-images/mysql:5.7.44-oracle 12d +8.0.31-innodb 8.0.31 MySQL ghcr.io/appscode-images/mysql:8.0.31-oracle 12d +8.0.35 8.0.35 Official ghcr.io/appscode-images/mysql:8.0.35-oracle 12d +8.0.36 8.0.36 Official ghcr.io/appscode-images/mysql:8.0.36-debian 12d +8.1.0 8.1.0 Official ghcr.io/appscode-images/mysql:8.1.0-oracle 12d +8.2.0 8.2.0 Official ghcr.io/appscode-images/mysql:8.2.0-oracle 12d +8.4.2 8.4.2 Official ghcr.io/appscode-images/mysql:8.4.2-oracle 12d +8.4.3 8.4.3 Official ghcr.io/appscode-images/mysql:8.4.3-oracle 12d +9.0.1 9.0.1 Official ghcr.io/appscode-images/mysql:9.0.1-oracle 12d +9.1.0 9.1.0 Official ghcr.io/appscode-images/mysql:9.1.0-oracle 12d +``` + +## Create a Mysql Database + +KubeDB implements a `MySQL` CRD to define the specification of a MySQL server. Below is the `MySQL` +object created in this tutorial. + +```yaml +apiVersion: kubedb.com/v1 +kind: MySQL +metadata: + name: mysql-quickstart + namespace: demo +spec: + version: "9.1.0" + storageType: Durable + storage: + storageClassName: "standard" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: Delete +``` + +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/guides/mysql/quickstart/yamls/quickstart-v1.yaml +mysql.kubedb.com/mysql-quickstart created +``` +Let's wait for `MySQL` status is `Ready`. Run the following command to watch `MySQL` CRO +```shell +$ kubectl get mysql -n demo -w +NAME VERSION STATUS AGE +mysql-quickstart 10.5.23 Ready 30m +``` +## Verify Authentication +The user can verify whether they are authorized by executing a query directly in the database. To +do this, the user needs `username` and `password` in order to connect to the database. Below is an +example showing how to retrieve the credentials from the secret. + +````shell +$ kubectl get mysql -n demo mysql-quickstart -ojson | jq .spec.authsecret.name +"mysql-quickstart-auth" +$ kubectl get secret -n demo mysql-quickstart-auth -o jsonpath='{.data.username}' | base64 -d +root⏎ +$ kubectl get secret -n demo mysql-quickstart-auth -o jsonpath='{.data.password}' | base64 -d +H04(Wn6AM_4r6)(k⏎ +```` +Now, you can exec into the pod `mysql-quickstart-0` and connect to database using `username` and `password` +```bash +$ kubectl exec -it -n demo mysql-quickstart-0 -c mysql -- bash + +bash-5.1$ mysql -uroot -p"H04(Wn6AM_4r6)(k" +mysql: [Warning] Using a password on the command line interface can be insecure. +Welcome to the MySQL monitor. Commands end with ; or \g. +Your MySQL connection id is 169 +Server version: 9.1.0 MySQL Community Server - GPL + +Copyright (c) 2000, 2024, Oracle and/or its affiliates. + +Oracle is a registered trademark of Oracle Corporation and/or its +affiliates. Other names may be trademarks of their respective +owners. + +Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. + +mysql> SHOW DATABASES; ++--------------------+ +| Database | ++--------------------+ +| information_schema | +| kubedb_system | +| mysql | +| performance_schema | +| sys | ++--------------------+ +5 rows in set (0.01 sec) + +``` + +If you can access the data table and run queries, it means the secrets are working correctly. +## Create RotateAuth MySQLOpsrequest + +#### 1. Using Operator Generated Credentials: + +In order to rotate authentication to the MySQL using operator generated, we have to create a +`MySQLOpsrequest` CR with `RotateAuth` type. Below is the YAML of the `MySQLOpsrequest` CRO that +we are going to create, +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: MySQLOpsrequest +metadata: + name: myops-rotate-auth-generated + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: mysql-quickstart + timeout: 5m + apply: IfReady +``` +Here, + +- `spec.databaseRef.name` specifies that we are performing rotate authentication operation on `mysql-quickstart` instance. +- `spec.type` specifies that we are performing `RotateAuth` on MySQL. + +Let's create the `MySQLOpsrequest` CR we have shown above, +```shell + $ kubectl apply -f https://github.com/kubedb/docs/raw/{{ .version }}/docs/examples/mysql/rotate-auth/rotate-auth-generated.yaml + MySQLOpsrequest.ops.kubedb.com/myops-rotate-auth-generated created +``` +Let's wait for `MySQLOpsrequest` to be `Successful`. Run the following command to watch `MySQLOpsrequest` CRO +```shell + $ kubectl get MySQLOpsrequest-n demo +NAME TYPE STATUS AGE +myops-rotate-auth-generated RotateAuth Successful 82s +``` +If we describe the `MySQLOpsrequest` we will get an overview of the steps that were followed. +```shell +$ kubectl describe MySQLOpsrequest-n demo myops-rotate-auth-generated +Name: myops-rotate-auth-generated +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: MySQLOpsrequest +Metadata: + Creation Timestamp: 2025-08-20T09:16:39Z + Generation: 1 + Resource Version: 69442 + UID: fded850f-d5a9-46d0-b082-9f789bb68ac2 +Spec: + Apply: IfReady + Database Ref: + Name: mysql-quickstart + Timeout: 5m + Type: RotateAuth +Status: + Conditions: + Last Transition Time: 2025-08-20T09:16:39Z + Message: Controller has started to Progress the MySQLOpsrequest: demo/myops-rotate-auth-generated + Observed Generation: 1 + Reason: Running + Status: True + Type: Running + Last Transition Time: 2025-08-20T09:16:42Z + Message: Successfully generated new credential + Observed Generation: 1 + Reason: patchedsecret + Status: True + Type: UpdateCredential + Last Transition Time: 2025-08-20T09:16:44Z + Message: Successfully updated MySQL petset + Observed Generation: 1 + Reason: UpdatePetSetsSucceeded + Status: True + Type: UpdatePetSets + Last Transition Time: 2025-08-20T09:16:49Z + Message: evict pod; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: EvictPod + Last Transition Time: 2025-08-20T09:16:59Z + Message: is pod ready; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: IsPodReady + Last Transition Time: 2025-08-20T09:16:59Z + Message: is join in cluster; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: IsJoinInCluster + Last Transition Time: 2025-08-20T09:16:59Z + Message: Successfully started MySQL pods for MySQLOpsrequest: demo/myops-rotate-auth-generated + Observed Generation: 1 + Reason: RestartPodsSucceeded + Status: True + Type: Restart + Last Transition Time: 2025-08-20T09:16:59Z + Message: Controller has successfully rotate MySQL auth secret demo/myops-rotate-auth-generated + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Starting 27m KubeDB Ops-manager Operator Start processing for MySQLOpsrequest: demo/myops-rotate-auth-generated + Normal Starting 27m KubeDB Ops-manager Operator Pausing MySQL databse: demo/mysql-quickstart + Normal Successful 27m KubeDB Ops-manager Operator Successfully paused MySQL database: demo/mysql-quickstart for MySQLOpsrequest: myops-rotate-auth-generated + Normal Starting 27m KubeDB Ops-manager Operator Restarting Pod: mysql-quickstart-0/demo + Warning evict pod; ConditionStatus:True 27m KubeDB Ops-manager Operator evict pod; ConditionStatus:True + Warning is pod ready; ConditionStatus:False 27m KubeDB Ops-manager Operator is pod ready; ConditionStatus:False + Warning is pod ready; ConditionStatus:True 26m KubeDB Ops-manager Operator is pod ready; ConditionStatus:True + Warning is join in cluster; ConditionStatus:True 26m KubeDB Ops-manager Operator is join in cluster; ConditionStatus:True + Normal Successful 26m KubeDB Ops-manager Operator Successfully started MySQL pods for MySQLOpsrequest: demo/myops-rotate-auth-generated + Normal Starting 26m KubeDB Ops-manager Operator Resuming MySQL database: demo/mysql-quickstart + Normal Successful 26m KubeDB Ops-manager Operator Successfully resumed MySQL database: demo/mysql-quickstart + Normal Successful 26m KubeDB Ops-manager Operator Controller has successfully rotate MySQL auth secret + +``` +**Verify Auth is rotated** +```shell +$ kubectl get mysql -n demo mysql-quickstart -ojson | jq .spec.authsecret.name +"mysql-quickstart-auth" +$ kubectl get secret -n demo mysql-quickstart-auth -o jsonpath='{.data.username}' | base64 -d +root⏎ +$ kubectl get secret -n demo mysql-quickstart-auth -o jsonpath='{.data.password}' | base64 -d +vYBjULhCEzPwe5xo⏎ +``` +Let's verify if we can connect to the database using the new credentials. + +```shell +$ kubectl exec -it -n demo mysql-quickstart-0 -c mysql -- bash + +bash-5.1$ mysql -uroot -p"vYBjULhCEzPwe5xo" +mysql: [Warning] Using a password on the command line interface can be insecure. +Welcome to the MySQL monitor. Commands end with ; or \g. +Your MySQL connection id is 49 +Server version: 9.1.0 MySQL Community Server - GPL + +Copyright (c) 2000, 2024, Oracle and/or its affiliates. + +Oracle is a registered trademark of Oracle Corporation and/or its +affiliates. Other names may be trademarks of their respective +owners. + +Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. + +mysql> SHOW DATABASES; ++--------------------+ +| Database | ++--------------------+ +| information_schema | +| kubedb_system | +| mysql | +| performance_schema | +| sys | ++--------------------+ +5 rows in set (0.00 sec) + +``` + +Also, there will be two more new keys in the secret that stores the previous credentials. The keys are `username.prev` and `password.prev`. You can find the secret and its data by running the following command: + +```shell +$ kubectl get secret -n demo mysql-quickstart-auth -o go-template='{{ index .data "username.prev" }}' | base64 -d +root⏎ +$ kubectl get secret -n demo mysql-quickstart-auth -o go-template='{{ index .data "password.prev" }}' | base64 -d +H04(Wn6AM_4r6)(k⏎ +``` +Let's confirm that the previous credentials no longer work. +```shell +kubectl exec -it -n demo mysql-quickstart-0 -c mysql -- bash +bash-5.1$ mysql -uroot -p"H04(Wn6AM_4r6)(k" +mysql: [Warning] Using a password on the command line interface can be insecure. +ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES) +bash-5.1$ + +``` +The above output shows that the password has been changed successfully. The previous username & password is stored for rollback purpose. +#### 2.Using User Created Credentials + +At first, we need to create a secret with `kubernetes.io/basic-auth` type using custom password. +Below is the command to create a secret with `kubernetes.io/basic-auth` type, +> Note: The `username` must be fixed as `root`. +```shell +$ kubectl create secret generic mysql-quickstart-auth-user -n demo \ + --type=kubernetes.io/basic-auth \ + --from-literal=username=root \ + --from-literal=password=Mysql2 +secret/mysql-quickstart-auth-user created +``` +Now create a `MySQLOpsrequest` with `RotateAuth` type. Below is the YAML of the `MySQLOpsrequest` that we are going to create, + +```shell +apiVersion: ops.kubedb.com/v1alpha1 +kind: MySQLOpsrequest +metadata: + name: myops-rotate-auth-user + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: mysql-quickstart + authentication: + secretRef: + name: mysql-quickstart-auth-user + timeout: 5m + apply: IfReady +``` +Here, + +- `spec.databaseRef.name` specifies that we are performing rotate authentication operation on `mysql-quickstart`cluster. +- `spec.type` specifies that we are performing `RotateAuth` on Mysql. +- `spec.authentication.secretRef.name` specifies that we use `mysql-quickstart-auth` for database authentication. + + +Let's create the `MySQLOpsrequest` CR we have shown above, + +```shell +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{ .version }}/docs/examples/mysql/rotate-auth/rotate-auth-user.yaml +MySQLOpsrequest.ops.kubedb.com/myops-rotate-auth-user created +``` +Let’s wait for `MySQLOpsrequest` to be Successful. Run the following command to watch `MySQLOpsrequest` CRO: + +```shell +$ kubectl get MySQLOpsrequest-n demo +NAME TYPE STATUS AGE +myops-rotate-auth-generated RotateAuth Successful 35m +myops-rotate-auth-user RotateAuth Successful 2m18s +``` +We can see from the above output that the `MySQLOpsrequest` has succeeded. If we describe the `MySQLOpsrequest` we will get an overview of the steps that were followed. +```shell +$ kubectl describe MySQLOpsrequest-n demo myops-rotate-auth-user +Name: myops-rotate-auth-user +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: MySQLOpsrequest +Metadata: + Creation Timestamp: 2025-08-20T09:49:56Z + Generation: 1 + Resource Version: 74129 + UID: 88dd5aed-cd12-43d7-95d6-e0b7e726076f +Spec: + Apply: IfReady + Authentication: + secret Ref: + Name: mysql-quickstart-auth-user + Database Ref: + Name: mysql-quickstart + Timeout: 5m + Type: RotateAuth +Status: + Conditions: + Last Transition Time: 2025-08-20T09:49:56Z + Message: Controller has started to Progress the MySQLOpsrequest: demo/myops-rotate-auth-user + Observed Generation: 1 + Reason: Running + Status: True + Type: Running + Last Transition Time: 2025-08-20T09:49:59Z + Message: Successfully referenced the user provided authsecret + Observed Generation: 1 + Reason: patchedsecret + Status: True + Type: UpdateCredential + Last Transition Time: 2025-08-20T09:50:01Z + Message: Successfully updated MySQL petset + Observed Generation: 1 + Reason: UpdatePetSetsSucceeded + Status: True + Type: UpdatePetSets + Last Transition Time: 2025-08-20T09:50:06Z + Message: evict pod; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: EvictPod + Last Transition Time: 2025-08-20T09:50:11Z + Message: is pod ready; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: IsPodReady + Last Transition Time: 2025-08-20T09:50:41Z + Message: is join in cluster; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: IsJoinInCluster + Last Transition Time: 2025-08-20T09:50:41Z + Message: Successfully started MySQL pods for MySQLOpsrequest: demo/myops-rotate-auth-user + Observed Generation: 1 + Reason: RestartPodsSucceeded + Status: True + Type: Restart + Last Transition Time: 2025-08-20T09:50:41Z + Message: Controller has successfully rotate MySQL auth secret demo/myops-rotate-auth-user + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Starting 2m54s KubeDB Ops-manager Operator Start processing for MySQLOpsrequest: demo/myops-rotate-auth-user + Normal Starting 2m54s KubeDB Ops-manager Operator Pausing MySQL databse: demo/mysql-quickstart + Normal Successful 2m54s KubeDB Ops-manager Operator Successfully paused MySQL database: demo/mysql-quickstart for MySQLOpsrequest: myops-rotate-auth-user + Normal Starting 2m44s KubeDB Ops-manager Operator Restarting Pod: mysql-quickstart-0/demo + Warning evict pod; ConditionStatus:True 2m44s KubeDB Ops-manager Operator evict pod; ConditionStatus:True + Warning is pod ready; ConditionStatus:False 2m44s KubeDB Ops-manager Operator is pod ready; ConditionStatus:False + Warning is pod ready; ConditionStatus:True 2m39s KubeDB Ops-manager Operator is pod ready; ConditionStatus:True + Warning is join in cluster; ConditionStatus:False 2m9s KubeDB Ops-manager Operator is join in cluster; ConditionStatus:False + Warning is pod ready; ConditionStatus:True 2m9s KubeDB Ops-manager Operator is pod ready; ConditionStatus:True + Warning is join in cluster; ConditionStatus:True 2m9s KubeDB Ops-manager Operator is join in cluster; ConditionStatus:True + Normal Successful 2m9s KubeDB Ops-manager Operator Successfully started MySQL pods for MySQLOpsrequest: demo/myops-rotate-auth-user + Normal Starting 2m9s KubeDB Ops-manager Operator Resuming MySQL database: demo/mysql-quickstart + Normal Successful 2m9s KubeDB Ops-manager Operator Successfully resumed MySQL database: demo/mysql-quickstart + Normal Successful 2m9s KubeDB Ops-manager Operator Controller has successfully rotate MySQL auth secret + +``` +**Verify auth is rotate** +```shell +$ kubectl get my -n demo mysql-quickstart -ojson | jq .spec.authsecret.name +"mysql-quickstart-auth-user" +$ kubectl get secret -n demo mysql-quickstart-auth-user -o=jsonpath='{.data.username}' | base64 -d +root⏎ +$ kubectl get secret -n demo mysql-quickstart-auth-user -o=jsonpath='{.data.password}' | base64 -d +Mysql2⏎ +``` + +Let's verify if we can connect to the database using the new credentials. +```shell +$ kubectl exec -it -n demo mysql-quickstart-0 -c mysql -- bash +bash-5.1$ mysql -uroot -p"Mysql2" +mysql: [Warning] Using a password on the command line interface can be insecure. +Welcome to the MySQL monitor. Commands end with ; or \g. +Your MySQL connection id is 132 +Server version: 9.1.0 MySQL Community Server - GPL + +Copyright (c) 2000, 2024, Oracle and/or its affiliates. + +Oracle is a registered trademark of Oracle Corporation and/or its +affiliates. Other names may be trademarks of their respective +owners. + +Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. + +mysql> SHOW DATABASES; ++--------------------+ +| Database | ++--------------------+ +| information_schema | +| kubedb_system | +| mysql | +| performance_schema | +| sys | ++--------------------+ +5 rows in set (0.02 sec) + +``` +Also, there will be two more new keys in the secret that stores the previous credentials. The keys are `username.prev` and `password.prev`. You can find the secret and its data by running the following command: +```shell +$ kubectl get secret -n demo mysql-quickstart-auth-user -o go-template='{{ index .data "username.prev" }}' | base64 -d +root⏎ +$ kubectl get secret -n demo mysql-quickstart-auth-user -o go-template='{{ index .data "password.prev" }}' | base64 -d +vYBjULhCEzPwe5xo⏎ +``` +Let's confirm that the previous credentials no longer work. +```shell +$ kubectl exec -it -n demo mysql-quickstart-0 -c mysql -- bash +bash-5.1$ mysql -uroot -p"vYBjULhCEzPwe5xo" +mysql: [Warning] Using a password on the command line interface can be insecure. +ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES) +bash-5.1$ +``` +The above output shows that the password has been changed successfully. The previous username & password is stored in the secret for rollback purpose. + +## Cleaning up + +To clean up the Kubernetes resources you can delete the CRD or namespace. +Alternatively, you can delete individual resources by name. To do so, run: + +```shell +$ kubectl delete MySQLOpsrequestmyops-rotate-auth-generated myops-rotate-auth-user -n demo +MySQLOpsrequest.ops.kubedb.com "myops-rotate-auth-generated" "myops-rotate-auth-user" deleted +$ kubectl delete secret -n demo mysql-quickstart-auth-user +secret "mysql-quickstart-auth-user" deleted +$ kubectl delete secret -n demo mysql-quickstart-auth +secret "mysql-quickstart-auth " deleted + +``` + +## Next Steps + +- Learn about [backup and restore](/docs/guides/mysql/backup/overview/index.md) SQL Server using KubeStash. +- Want to set up SQL Server Availability Group clusters? Check how to [Configure SQL Server Availability Gruop Cluster](/docs/guides/mysql/clustering/ag_cluster.md) +- Detail concepts of [Mysql object](/docs/guides/mysql/concepts/mysql.md). +- Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md). diff --git a/docs/guides/percona-xtradb/rotateauth/_index.md b/docs/guides/percona-xtradb/rotateauth/_index.md new file mode 100644 index 0000000000..7701ae043d --- /dev/null +++ b/docs/guides/percona-xtradb/rotateauth/_index.md @@ -0,0 +1,10 @@ +--- +title: PerconaXtraDB Rotate Authentication +menu: + docs_{{ .version }}: + identifier: guides-perconaxtradb-rotate-auth + name: Rotate Authentication + parent: guides-perconaxtradb + weight: 40 +menu_name: docs_{{ .version }} +--- diff --git a/docs/guides/percona-xtradb/rotateauth/rotateauth.md b/docs/guides/percona-xtradb/rotateauth/rotateauth.md new file mode 100644 index 0000000000..2cae4f3970 --- /dev/null +++ b/docs/guides/percona-xtradb/rotateauth/rotateauth.md @@ -0,0 +1,534 @@ +--- +title: Rotate Authentication PerconaXtraDB +menu: + docs_{{ .version }}: + identifier: guides-perconaxtradb-rotateauthentiocation + name: Guide + parent: guides-perconaxtradb-rotate-auth + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +# Rotate Authentication of PerconaXtraDB + +**Rotate Authentication** is a feature of the KubeDB Ops-Manager that allows you to rotate a `PerconaXtraDB` user's authentication credentials using a `PerconaXtraDBOpsRequest`. There are two ways to perform this rotation. + +1. **Operator Generated:** The KubeDB operator automatically generates a random credential, updates the existing secret with the new credential The KubeDB operator automatically generates a random credential and updates the existing secret with the new credential.. +2. **User Defined:** The user can create their own credentials by defining a secret of type `kubernetes.io/basic-auth` containing the desired `username` and `password` and then reference this secret in the `PerconaXtraDBOpsRequest`. + +## Before You Begin + +- At first, you need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Now, install KubeDB cli on your workstation and KubeDB operator in your cluster following the steps [here](/docs/setup/README.md). + +- [StorageClass](https://kubernetes.io/docs/concepts/storage/storage-classes/) is required to run KubeDB. Check the available StorageClass in cluster. + +```bash +$ kubectl get storageclasses +NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE +standard (default) rancher.io/local-path Delete WaitForFirstConsumer false 6h22m +``` + +- To keep things isolated, this tutorial uses a separate namespace called `demo` throughout this tutorial. + +``` +$ kubectl create ns demo +namespace/demo created +``` + +## Create a PerconaXtraDB database + +KubeDB implements a `PerconaXtraDB` CRD to define the specification of a PerconaXtraDB database. Below is the `PerconaXtraDB` object created in this tutorial. + +`Note`: If your `KubeDB version` is less or equal to `v2024.6.4`, You have to use `v1alpha2` apiVersion. + +```yaml +apiVersion: kubedb.com/v1 +kind: PerconaXtraDB +metadata: + name: sample-pxc + namespace: demo +spec: + version: "8.0.40" + storageType: Durable + storage: + storageClassName: "standard" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: Delete +``` + +```bash +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/guides/percona-xtradb/quickstart/overview/examples/sample-pxc-v1.yaml +perconaxtradb.kubedb.com/sample-pxc created +``` + +Now, wait until sample-pxc has status Ready. i.e, + +```shell +$ kubectl get perconaxtradb -n demo +NAME VERSION STATUS AGE +sample-pxc 8.0.40 Ready 43m +``` +## Verify authentication +The user can verify whether they are authorized by executing a query directly in the database. To do this, the user needs `username` and `password` in order to connect to the database. Below is an example showing how to retrieve the credentials from the secret. + +````shell +$ kubectl get PerconaXtraDB -n demo sample-pxc -ojson | jq .spec.authsecret.name +"sample-pxc-auth" +$ kubectl get secrets -n demo sample-pxc-auth -o jsonpath='{.data.\username}' | base64 -d +root⏎ +$ kubectl get secrets -n demo sample-pxc-auth -o jsonpath='{.data.\password}' | base64 -d +Q!IsZ7.NXM.ZIxvT⏎ +```` + +### Connect with PerconaXtraDB database using credentials + +Now, you can connect to this database using `telnet`. +Here, we will connect to PerconaXtraDB server from local-machine through port-forwarding. +We will connect to `sample-pxc-0` pod from local-machine using port-frowarding and it must be running in separate terminal. +```bash +$ kubectl port-forward -n demo sample-pxc-0 11211 +Forwarding from 127.0.0.1:11211 -> 11211 +Forwarding from [::1]:11211 -> 11211 +``` +Now, you can exec into the pod `sample-pxc` and connect to database using `username` and `password` +```shell +kubectl exec -it -n demo sample-pxc-0 -- mysql -u root --password='Q!IsZ7.NXM.ZIxvT' +Defaulted container "perconaxtradb" out of: perconaxtradb, px-coordinator, px-init (init) +mysql: [Warning] Using a password on the command line interface can be insecure. +Welcome to the MySQL monitor. Commands end with ; or \g. +Your MySQL connection id is 970 +Server version: 8.0.40-31.1 Percona XtraDB Cluster (GPL), Release rel31, Revision 4b32153, WSREP version 26.1.4.3 + +Copyright (c) 2009-2024 Percona LLC and/or its affiliates +Copyright (c) 2000, 2024, Oracle and/or its affiliates. + +Oracle is a registered trademark of Oracle Corporation and/or its +affiliates. Other names may be trademarks of their respective +owners. + +Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. + +mysql> show databases; ++--------------------+ +| Database | ++--------------------+ +| information_schema | +| kubedb_system | +| mysql | +| performance_schema | +| sys | ++--------------------+ +5 rows in set (0.00 sec) +mysql> CREATE DATABASE odissi; +Query OK, 1 row affected (0.03 sec) + +mysql> EXIT +Bye + +``` +If you can access the data table and run queries, it means the secrets are working correctly. +## Create RotateAuth PerconaXtraDBOpsRequest + +#### 1. Using operator generated credentials: + +In order to rotate authentication to the PerconaXtraDB using operator generated, we have to create a `PerconaXtraDBOpsRequest` CRO with `RotateAuth` type. Below is the YAML of the `PerconaXtraDBOpsRequest` CRO that we are going to create, +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: PerconaXtraDBOpsRequest +metadata: + name: pxops-rotate-auth-generated + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: sample-pxc + timeout: 5m + apply: IfReady +``` +Here, + +- `spec.databaseRef.name` specifies that we are performing rotate authentication operation on `sample-pxc` cluster. +- `spec.type` specifies that we are performing `RotateAuth` on PerconaXtraDB. + +Let's create the `PerconaXtraDBOpsRequest` CR we have shown above, +```shell + $ kubectl apply -f https://github.com/kubedb/docs/raw/{{ .version }}/docs/examples/perconaXtraDB/rotate-auth/PerconaXtraDB-rotate-auth-generated.yaml + PerconaXtraDBopsrequest.ops.kubedb.com/pxops-rotate-auth-generated created +``` +Let's wait for `PerconaXtraDBOpsrequest` to be `Successful`. Run the following command to watch `PerconaXtraDBOpsrequest` CRO +```shell + $ kubectl get PerconaXtraDBopsrequest -n demo +NAME TYPE STATUS AGE +pxops-rotate-auth-generated RotateAuth Successful 6m44s +``` +If we describe the `PerconaXtraDBOpsRequest` we will get an overview of the steps that were followed. +```shell +$ kubectl describe PerconaXtraDBopsrequest -n demo pxops-rotate-auth-generated +Name: pxops-rotate-auth-generated +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: PerconaXtraDBOpsRequest +Metadata: + Creation Timestamp: 2025-07-21T09:26:47Z + Generation: 1 + Resource Version: 179861 + UID: 6a6f2d74-818f-462c-8998-03e3fd9b157e +Spec: + Apply: IfReady + Database Ref: + Name: sample-pxc + Timeout: 5m + Type: RotateAuth +Status: + Conditions: + Last Transition Time: 2025-07-21T09:26:47Z + Message: Controller has started to Progress the PerconaXtraDBOpsRequest: demo/pxops-rotate-auth-generated + Observed Generation: 1 + Reason: Running + Status: True + Type: Running + Last Transition Time: 2025-07-21T09:26:50Z + Message: Successfully generated new credentials + Observed Generation: 1 + Reason: patchedsecret + Status: True + Type: UpdateCredential + Last Transition Time: 2025-07-21T09:26:59Z + Message: evict pod; ConditionStatus:True; PodName:sample-pxc-0 + Observed Generation: 1 + Status: True + Type: EvictPod--sample-pxc-0 + Last Transition Time: 2025-07-21T09:26:59Z + Message: get pod; ConditionStatus:True; PodName:sample-pxc-0 + Observed Generation: 1 + Status: True + Type: GetPod--sample-pxc-0 + Last Transition Time: 2025-07-21T09:28:09Z + Message: evict pod; ConditionStatus:True; PodName:sample-pxc-1 + Observed Generation: 1 + Status: True + Type: EvictPod--sample-pxc-1 + Last Transition Time: 2025-07-21T09:28:09Z + Message: get pod; ConditionStatus:True; PodName:sample-pxc-1 + Observed Generation: 1 + Status: True + Type: GetPod--sample-pxc-1 + Last Transition Time: 2025-07-21T09:29:19Z + Message: evict pod; ConditionStatus:True; PodName:sample-pxc-2 + Observed Generation: 1 + Status: True + Type: EvictPod--sample-pxc-2 + Last Transition Time: 2025-07-21T09:29:19Z + Message: get pod; ConditionStatus:True; PodName:sample-pxc-2 + Observed Generation: 1 + Status: True + Type: GetPod--sample-pxc-2 + Last Transition Time: 2025-07-21T09:30:29Z + Message: Successfully restarted PerconaXtraDB pods for PerconaXtraDBOpsRequest: demo/pxops-rotate-auth-generated + Observed Generation: 1 + Reason: UpdatePetSetsSucceeded + Status: True + Type: UpdatePetSets + Last Transition Time: 2025-07-21T09:30:34Z + Message: Successfully rotate PerconaXtraDB auth for PerconaXtraDBOpsRequest: demo/pxops-rotate-auth-generated + Observed Generation: 1 + Reason: UpdateCredential + Status: True + Type: RotateAuth + Last Transition Time: 2025-07-21T09:30:34Z + Message: Controller has successfully rotate PerconaXtraDB auth secret demo/pxops-rotate-auth-generated + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + +``` + +**Verify Auth is rotated** +```shell +$ kubectl get perconaxtradb -n demo sample-pxc -ojson | jq .spec.authsecret.name +"sample-pxc-auth" +$ kubectl get secret -n demo sample-pxc-auth -o=jsonpath='{.data.username}' | base64 -d +root⏎ +$ kubectl get secrets -n demo sample-pxc-auth -o jsonpath='{.data.\password}' | base64 -d +0o~37yrZq(363vDz⏎ +``` +Also, there will be two more new keys in the secret that stores the previous credentials. The key is `authData.prev`. You can find the secret and its data by running the following command: + +```shell +$ kubectl get secret -n demo sample-pxc-auth -o go-template='{{ index .data "username.prev" }}' | base64 -d +root⏎ +$ kubectl get secret -n demo sample-pxc-auth -o go-template='{{ index .data "password.prev" }}' | base64 -d +Q!IsZ7.NXM.ZIxvT⏎ +``` +The above output shows that the password has been changed successfully. The previous username & password is stored for rollback purpose. +#### 2. Using user created credentials + +At first, we need to create a secret with kubernetes.io/basic-auth type using custom username and password. Below is the command to create a secret with kubernetes.io/basic-auth type, +> Note: The `username` must be fixed as `root`. +```shell +$ kubectl create secret generic quick-pcx-user-auth -n demo \ + --type=kubernetes.io/basic-auth \ + --from-literal=username=root \ + --from-literal=password=PerconaXtraDB2 +secret/quick-pcx-user-auth created +``` +Now create a `PerconaXtraDBOpsRequest` with `RotateAuth` type. Below is the YAML of the `PerconaXtraDBOpsRequest` that we are going to create, + +```shell +apiVersion: ops.kubedb.com/v1alpha1 +kind: PerconaXtraDBOpsRequest +metadata: + name: pxops-rotate-auth-user + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: sample-pxc + authentication: + secretRef: + name: quick-pcx-user-auth + timeout: 5m + apply: IfReady +``` +Here, + +- `spec.databaseRef.name` specifies that we are performing rotate authentication operation on `sample-pxc`cluster. +- `spec.type` specifies that we are performing `RotateAuth` on PerconaXtraDB. +- `spec.authentication.secretRef.name` specifies that we are using `quick-pcx-user-auth` as `spec.authsecret.name` for authentication. + +Let's create the `PerconaXtraDBOpsRequest` CR we have shown above, + +```shell +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{ .version }}/docs/examples/perconaXtraDB/rotate-auth/rotate-auth-user.yaml +PerconaXtraDBopsrequest.ops.kubedb.com/pxops-rotate-auth-user created +``` +Let’s wait for `PerconaXtraDBOpsRequest` to be Successful. Run the following command to watch `PerconaXtraDBOpsRequest` CRO: + +```shell +$ kubectl get PerconaXtraDBopsrequest -n demo +NAME TYPE STATUS AGE +pxops-rotate-auth-generated RotateAuth Successful 55m +pxops-rotate-auth-user RotateAuth Successful 3m44s + +``` +We can see from the above output that the `PerconaXtraDBOpsRequest` has succeeded. If we describe the `PerconaXtraDBOpsRequest` we will get an overview of the steps that were followed. +```shell +$ kubectl describe PerconaXtraDBopsrequest -n demo pxops-rotate-auth-user +Name: pxops-rotate-auth-user +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: PerconaXtraDBOpsRequest +Metadata: + Creation Timestamp: 2025-07-21T10:25:50Z + Generation: 1 + Resource Version: 184407 + UID: 612937ae-eb86-440f-859e-16db902159f1 +Spec: + Apply: IfReady + Authentication: + secret Ref: + Name: quick-pcx-user-auth + Database Ref: + Name: sample-pxc + Timeout: 5m + Type: RotateAuth +Status: + Conditions: + Last Transition Time: 2025-07-21T10:25:50Z + Message: Controller has started to Progress the PerconaXtraDBOpsRequest: demo/pxops-rotate-auth-user + Observed Generation: 1 + Reason: Running + Status: True + Type: Running + Last Transition Time: 2025-07-21T10:25:50Z + Message: Successfully referenced the user provided authsecret + Observed Generation: 1 + Reason: patchedsecret + Status: True + Type: UpdateCredential + Last Transition Time: 2025-07-21T10:25:59Z + Message: evict pod; ConditionStatus:True; PodName:sample-pxc-0 + Observed Generation: 1 + Status: True + Type: EvictPod--sample-pxc-0 + Last Transition Time: 2025-07-21T10:25:59Z + Message: get pod; ConditionStatus:True; PodName:sample-pxc-0 + Observed Generation: 1 + Status: True + Type: GetPod--sample-pxc-0 + Last Transition Time: 2025-07-21T10:27:09Z + Message: evict pod; ConditionStatus:True; PodName:sample-pxc-1 + Observed Generation: 1 + Status: True + Type: EvictPod--sample-pxc-1 + Last Transition Time: 2025-07-21T10:27:09Z + Message: get pod; ConditionStatus:True; PodName:sample-pxc-1 + Observed Generation: 1 + Status: True + Type: GetPod--sample-pxc-1 + Last Transition Time: 2025-07-21T10:28:19Z + Message: evict pod; ConditionStatus:True; PodName:sample-pxc-2 + Observed Generation: 1 + Status: True + Type: EvictPod--sample-pxc-2 + Last Transition Time: 2025-07-21T10:28:19Z + Message: get pod; ConditionStatus:True; PodName:sample-pxc-2 + Observed Generation: 1 + Status: True + Type: GetPod--sample-pxc-2 + Last Transition Time: 2025-07-21T10:29:29Z + Message: Successfully restarted PerconaXtraDB pods for PerconaXtraDBOpsRequest: demo/pxops-rotate-auth-user + Observed Generation: 1 + Reason: UpdatePetSetsSucceeded + Status: True + Type: UpdatePetSets + Last Transition Time: 2025-07-21T10:29:34Z + Message: Successfully rotate PerconaXtraDB auth for PerconaXtraDBOpsRequest: demo/pxops-rotate-auth-user + Observed Generation: 1 + Reason: UpdateCredential + Status: True + Type: RotateAuth + Last Transition Time: 2025-07-21T10:29:34Z + Message: Controller has successfully rotate PerconaXtraDB auth secret demo/pxops-rotate-auth-user + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Starting 39m KubeDB Ops-manager Operator Start processing for PerconaXtraDBOpsRequest: demo/pxops-rotate-auth-user + Normal Starting 39m KubeDB Ops-manager Operator Restarting Pod: demo/sample-pxc-0 + Warning evict pod; ConditionStatus:True; PodName:sample-pxc-0 39m KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:sample-pxc-0 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-0 39m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-0 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-0 39m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-0 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-0 39m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-0 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-0 39m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-0 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-0 39m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-0 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-0 39m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-0 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-0 39m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-0 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-0 39m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-0 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-0 38m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-0 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-0 38m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-0 + Normal Starting 38m KubeDB Ops-manager Operator Restarting Pod: demo/sample-pxc-1 + Warning evict pod; ConditionStatus:True; PodName:sample-pxc-1 38m KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:sample-pxc-1 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-1 38m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-1 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-0 38m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-0 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-1 38m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-1 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-0 38m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-0 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-1 38m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-1 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-0 38m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-0 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-1 38m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-1 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-0 38m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-0 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-1 38m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-1 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-0 38m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-0 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-1 38m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-1 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-0 38m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-0 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-1 38m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-1 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-0 38m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-0 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-1 38m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-1 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-0 37m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-0 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-1 37m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-1 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-0 37m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-0 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-1 37m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-1 + Normal Starting 37m KubeDB Ops-manager Operator Restarting Pod: demo/sample-pxc-2 + Warning evict pod; ConditionStatus:True; PodName:sample-pxc-2 37m KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:sample-pxc-2 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-2 37m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-2 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-0 37m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-0 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-1 37m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-1 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-2 37m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-2 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-0 37m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-0 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-1 37m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-1 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-2 37m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-2 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-0 37m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-0 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-1 37m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-1 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-2 37m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-2 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-0 37m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-0 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-1 37m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-1 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-2 37m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-2 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-0 37m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-0 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-1 37m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-1 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-2 37m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-2 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-0 37m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-0 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-1 37m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-1 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-2 37m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-2 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-0 36m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-0 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-1 36m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-1 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-2 36m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-2 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-0 36m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-0 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-1 36m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-1 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-2 36m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-2 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-0 36m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-0 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-1 36m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-1 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-2 36m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-2 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-0 36m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-0 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-1 36m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-1 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-2 36m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-2 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-0 36m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-0 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-1 36m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-1 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-2 36m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-2 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-0 36m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-0 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-1 36m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-1 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-2 36m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-2 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-0 36m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-0 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-1 36m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-1 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-2 36m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-2 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-0 36m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-0 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-1 36m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-1 + Warning get pod; ConditionStatus:True; PodName:sample-pxc-2 36m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:sample-pxc-2 + Normal Successful 36m KubeDB Ops-manager Operator Successfully restarted PerconaXtraDB pods for PerconaXtraDBOpsRequest: demo/pxops-rotate-auth-user + Normal Successful 36m KubeDB Ops-manager Operator Successfully rotate PerconaXtraDB auth for PerconaXtraDBOpsRequest: demo/pxops-rotate-auth-user + Normal Starting 36m KubeDB Ops-manager Operator Resuming PerconaXtraDB database: demo/sample-pxc + Normal Successful 36m KubeDB Ops-manager Operator Successfully resumed PerconaXtraDB database: demo/sample-pxc + Normal Successful 36m KubeDB Ops-manager Operator Controller has successfully rotate PerconaXtraDB auth secret + +``` +**Verify auth is rotate** +```shell +$ kubectl get perconaxtradb -n demo sample-pxc -ojson | jq .spec.authsecret.name +"quick-pcx-user-auth " +$ kubectl get secrets -n demo quick-pcx-user-auth -o jsonpath='{.data.\username}' | base64 -d +root⏎ +$ kubectl get secrets -n demo quick-pcx-user-auth -o jsonpath='{.data.\password}' | base64 -d +PerconaXtraDB2⏎ +``` +Also, there will be two more new keys in the secret that stores the previous credentials. The keys are `username.prev` and `password.prev`. You can find the secret and its data by running the following command: +```shell +$ kubectl get secret -n demo quick-pcx-user-auth -o go-template='{{ index .data "username.prev" }}' | base64 -d +root⏎ +$ kubectl get secret -n demo quick-pcx-user-auth -o go-template='{{ index .data "password.prev" }}' | base64 -d +0o~37yrZq(363vDz⏎ +``` + +The above output shows that the password has been changed successfully. The previous username & password is stored in the secret for rollback purpose. + +## Cleaning up + +To clean up the Kubernetes resources you can delete the CRD or namespace. +Or, you can delete one by one resource by their name by this tutorial, run: + +```shell +$ kubectl delete PerconaXtraDBopsrequest pxops-rotate-auth-generated pxops-rotate-auth-user -n demo +PerconaXtraDBopsrequest.ops.kubedb.com "pxops-rotate-auth-generated" "pxops-rotate-auth-user" deleted +$ kubectl delete secret -n sample-pxc-auth +secret "sample-pxc-auth" deleted +$ kubectl delete secret -n demo quick-pcx-user-auth +secret "quick-pcx-user-auth " deleted +``` diff --git a/docs/guides/percona-xtradb/rotateauth/yamls/PerconaXtraDB-rotate-auth-generated.yaml b/docs/guides/percona-xtradb/rotateauth/yamls/PerconaXtraDB-rotate-auth-generated.yaml new file mode 100644 index 0000000000..3626db2e86 --- /dev/null +++ b/docs/guides/percona-xtradb/rotateauth/yamls/PerconaXtraDB-rotate-auth-generated.yaml @@ -0,0 +1,11 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: PerconaXtraDBOpsRequest +metadata: + name: pxops-rotate-auth-generated + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: sample-pxc + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/guides/percona-xtradb/rotateauth/yamls/rotate-auth-user.yaml b/docs/guides/percona-xtradb/rotateauth/yamls/rotate-auth-user.yaml new file mode 100644 index 0000000000..f4158566dc --- /dev/null +++ b/docs/guides/percona-xtradb/rotateauth/yamls/rotate-auth-user.yaml @@ -0,0 +1,14 @@ +apiVersion: ops.kubedb.com/v1alpha1 +kind: PerconaXtraDBOpsRequest +metadata: + name: pxops-rotate-auth-user + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: sample-pxc + authentication: + secretRef: + name: quick-pcx-user-auth + timeout: 5m + apply: IfReady \ No newline at end of file diff --git a/docs/guides/pgbouncer/rotateauth/_index.md b/docs/guides/pgbouncer/rotateauth/_index.md new file mode 100644 index 0000000000..2d6211e595 --- /dev/null +++ b/docs/guides/pgbouncer/rotateauth/_index.md @@ -0,0 +1,10 @@ +--- +title: Rotate Authentication PgBouncer +menu: + docs_{{ .version }}: + identifier: pb-rotate-auth + name: Rotate Authentication + parent: pb-pgbouncer-guides + weight: 50 +menu_name: docs_{{ .version }} +--- diff --git a/docs/guides/pgbouncer/rotateauth/rotateauth.md b/docs/guides/pgbouncer/rotateauth/rotateauth.md new file mode 100644 index 0000000000..3bfecdc3d4 --- /dev/null +++ b/docs/guides/pgbouncer/rotateauth/rotateauth.md @@ -0,0 +1,430 @@ +--- +title: Rotate Authentication PgBouncer +menu: + docs_{{ .version }}: + identifier: pb-rotateauthentication + name: Guide + parent: pb-rotate-auth + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +# Rotate Authentication of PgBouncer + +**Rotate Authentication** is a feature of the KubeDB Ops-Manager that allows you to rotate a `PgBouncer` user's authentication credentials using a `PgBouncerOpsRequest`. There are two ways to perform this rotation. + +1. **Operator Generated:** The KubeDB operator automatically generates a random credential, updates the existing secret with the new credential The KubeDB operator automatically generates a random credential and updates the existing secret with the new credential.. +2. **User Defined:** The user can create their own credentials by defining a secret of type `kubernetes.io/basic-auth` containing the desired `username` and `password` and then reference this secret in the `PgBouncerOpsRequest`. + +## Before You Begin + +At first, you need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +Now, install KubeDB cli on your workstation and KubeDB operator in your cluster following the steps [here](/docs/setup/README.md). + +To keep things isolated, this tutorial uses a separate namespace called `demo` throughout this tutorial. + +```bash +$ kubectl create ns demo +namespace/demo created +``` + +> Note: YAML files used in this tutorial are stored in [docs/examples/pgbouncer](https://github.com/kubedb/docs/tree/{{< param "info.version" >}}/docs/examples/pgbouncer) folder in GitHub repository [kubedb/docs](https://github.com/kubedb/docs). + +**We have designed this tutorial to demonstrate a production setup of KubeDB managed PgBouncer.** +**If you just want to try out KubeDB, you can bypass some of the safety features following the tips [here](/docs/guides/pgbouncer/quickstart/quickstart.md#tips-for-testing).** + +> Note: Before you begin, you have to create `PgBouncer` CRD with the help of [this](/docs/guides/pgbouncer/quickstart/quickstart.md). + +## Verify authentication +The user can verify whether they are authorized by executing a query directly in the database. To do this, the user needs `username` and `password` in order to connect to the database. Below is an example showing how to retrieve the credentials from the secret. + +````shell +$ kubectl get pgbouncer -n demo pgbouncer-server -ojson | jq .spec.authsecret.name +"pgbouncer-server-auth" +$ kubectl get secrets -n demo pgbouncer-server-auth -o jsonpath='{.data.\username}' | base64 -d +pgbouncer⏎ +$ kubectl get secrets -n demo pgbouncer-server-auth -o jsonpath='{.data.\password}' | base64 -d +I*7SQB7)6~Kni8*X⏎ +```` + +### Connect with PgBouncer database using credentials + +Here, we will connect to PgBouncer server from local-machine through port-forwarding. +We will connect to `pgbouncer-server` pod from local-machine using port-frowarding and it must be running in separate terminal. +```bash +$ kubectl port-forward svc/pgbouncer-server -n demo 9999:5432 +Forwarding from 127.0.0.1:9999 -> 5432 +Forwarding from [::1]:9999 -> 5432 + +``` +Now, you can exec into the pod pgbouncer-server` and connect to database using `username` and `password` +```shell +$ kubectl exec -it -n demo pgbouncer-server-0 -- /bin/sh +/ $ cat /var/run/pgbouncer/secret/userlist +"pgbouncer" "md5f24d95a2a5c1ed1debe8c3e6f19ac7ec" +"postgres" "md5095f5936c7d03fbc4998320d3bf993c4" +/ $ exit +``` +First, you have to have `PostgreSQL` to run these commands. +```shell +$ export PGPASSWORD='I*7SQB7)6~Kni8*X' +$ psql --host=localhost --port=9999 --username=pgbouncer -d pgbouncer +psql (16.9 (Ubuntu 16.9-0ubuntu0.24.04.1), server 1.18.0/bouncer) +WARNING: psql major version 16, server major version 1.18. + Some psql features might not work. +Type "help" for help. +pgbouncer=# show databases; + name | host | port | database | force_user | pool_size | min_pool_size | reserve_pool | pool_mode | max_connections | current_connections | paused | disabled +-----------+-------------------------+------+-----------+------------+-----------+---------------+--------------+-----------+-----------------+---------------------+--------+---------- + pgbouncer | | 5432 | pgbouncer | pgbouncer | 2 | 0 | 0 | statement | 1 | 0 | 0 | 0 + postgres | quick-postgres.demo.svc | 5432 | postgres | | 20 | 1 | 5 | | 1 | 1 | 0 | 0 +(2 rows) + +``` + +If you can access the data table and run queries, it means the secrets are working correctly. +## Create RotateAuth PgBouncerOpsRequest + +#### 1. Using operator generated credentials: + +In order to rotate authentication to the PgBouncer using operator generated, we have to create a `PgBouncerOpsRequest` CRO with `RotateAuth` type. Below is the YAML of the `PgBouncerOpsRequest` CRO that we are going to create, +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: PgBouncerOpsRequest +metadata: + name: pbops-rotate-auth-generated + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: pgbouncer-server + timeout: 5m + apply: IfReady +``` +Here, + +- `spec.databaseRef.name` specifies that we are performing rotate authentication operation on `pgbouncer-server` cluster. +- `spec.type` specifies that we are performing `RotateAuth` on PgBouncer. + +Let's create the `PgBouncerOpsRequest` CR we have shown above, +```shell + $kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/pgbouncer/rotate-auth/rotate-auth.yaml + pgbounceropsrequest.ops.kubedb.com/pbops-rotate-auth-generated created +``` +Let's wait for `PgBouncerOpsrequest` to be `Successful`. Run the following command to watch `PgBouncerOpsrequest` CRO +```shell + $ kubectl get PgBouncerOpsRequest -n demo +NAME TYPE STATUS AGE +pbops-rotate-auth-generated RotateAuth Successful 4m34s +``` +If we describe the `PgBouncerOpsRequest` we will get an overview of the steps that were followed. +```shell +$ kubectl describe PgBounceropsrequest -n demo pbops-rotate-auth-generated +Name: pbops-rotate-auth-generated +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: PgBouncerOpsRequest +Metadata: + Creation Timestamp: 2025-07-18T04:25:48Z + Generation: 1 + Resource Version: 103172 + UID: 5c5ac3bb-ee72-4d1d-b10c-e2951b4560b9 +Spec: + Apply: IfReady + Database Ref: + Name: pgbouncer-server + Timeout: 5m + Type: RotateAuth +Status: + Conditions: + Last Transition Time: 2025-07-18T04:25:48Z + Message: PgBouncer ops request has started to rotate auth for pgbouncer + Observed Generation: 1 + Reason: RotateAuth + Status: True + Type: RotateAuth + Last Transition Time: 2025-07-18T04:25:51Z + Message: Successfully generated new credentials + Observed Generation: 1 + Reason: UpdateCredential + Status: True + Type: UpdateCredential + Last Transition Time: 2025-07-18T04:26:32Z + Message: Successfully updated petsets rotate auth type + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2025-07-18T04:26:37Z + Message: get pod; ConditionStatus:True; PodName:pgbouncer-server-0 + Observed Generation: 1 + Status: True + Type: GetPod--pgbouncer-server-0 + Last Transition Time: 2025-07-18T04:26:37Z + Message: evict pod; ConditionStatus:True; PodName:pgbouncer-server-0 + Observed Generation: 1 + Status: True + Type: EvictPod--pgbouncer-server-0 + Last Transition Time: 2025-07-18T04:26:42Z + Message: check replica func; ConditionStatus:True; PodName:pgbouncer-server-0 + Observed Generation: 1 + Status: True + Type: CheckReplicaFunc--pgbouncer-server-0 + Last Transition Time: 2025-07-18T04:26:42Z + Message: check pod ready; ConditionStatus:True; PodName:pgbouncer-server-0 + Observed Generation: 1 + Status: True + Type: CheckPodReady--pgbouncer-server-0 + Last Transition Time: 2025-07-18T04:27:02Z + Message: check pg bouncer running; ConditionStatus:True; PodName:pgbouncer-server-0 + Observed Generation: 1 + Status: True + Type: CheckPgBouncerRunning--pgbouncer-server-0 + Last Transition Time: 2025-07-18T04:27:07Z + Message: Restart performed successfully in PgBouncer: demo/pgbouncer-server for PgBouncerOpsRequest: pbops-rotate-auth-generated + Observed Generation: 1 + Reason: RestartPodsSucceeded + Status: True + Type: RestartPods + Last Transition Time: 2025-07-18T04:27:07Z + Message: Controller has successfully completed with RotateAuth of PgBouncerOpsRequest: demo/pbops-rotate-auth-generated + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Starting 5m51s KubeDB Ops-manager Operator Pausing PgBouncer databse: demo/pgbouncer-server + Normal Successful 5m51s KubeDB Ops-manager Operator Successfully paused PgBouncer database: demo/pgbouncer-server for PgBouncerOpsRequest: pbops-rotate-auth-generated + Normal VersionUpdate 5m48s KubeDB Ops-manager Operator Updating PetSets + Warning Failed 5m28s KubeDB Ops-manager Operator Operation cannot be fulfilled on pgbouncers.kubedb.com "pgbouncer-server": the object has been modified; please apply your changes to the latest version and try again + Normal VersionUpdate 5m28s KubeDB Ops-manager Operator Updating PetSets + Normal VersionUpdate 5m7s KubeDB Ops-manager Operator Successfully Updated PetSets + Warning get pod; ConditionStatus:True; PodName:pgbouncer-server-0 5m2s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:pgbouncer-server-0 + Warning evict pod; ConditionStatus:True; PodName:pgbouncer-server-0 5m2s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:pgbouncer-server-0 + Warning check replica func; ConditionStatus:True; PodName:pgbouncer-server-0 4m57s KubeDB Ops-manager Operator check replica func; ConditionStatus:True; PodName:pgbouncer-server-0 + Warning check pod ready; ConditionStatus:True; PodName:pgbouncer-server-0 4m57s KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:pgbouncer-server-0 + Warning check pg bouncer running; ConditionStatus:False; PodName:pgbouncer-server-0 4m47s KubeDB Ops-manager Operator check pg bouncer running; ConditionStatus:False; PodName:pgbouncer-server-0 + Warning check replica func; ConditionStatus:True; PodName:pgbouncer-server-0 4m47s KubeDB Ops-manager Operator check replica func; ConditionStatus:True; PodName:pgbouncer-server-0 + Warning check pod ready; ConditionStatus:True; PodName:pgbouncer-server-0 4m47s KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:pgbouncer-server-0 + Warning check replica func; ConditionStatus:True; PodName:pgbouncer-server-0 4m37s KubeDB Ops-manager Operator check replica func; ConditionStatus:True; PodName:pgbouncer-server-0 + Warning check pod ready; ConditionStatus:True; PodName:pgbouncer-server-0 4m37s KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:pgbouncer-server-0 + Warning check pg bouncer running; ConditionStatus:True; PodName:pgbouncer-server-0 4m37s KubeDB Ops-manager Operator check pg bouncer running; ConditionStatus:True; PodName:pgbouncer-server-0 + Normal Successful 4m32s KubeDB Ops-manager Operator Restart performed successfully in PgBouncer: demo/pgbouncer-server for PgBouncerOpsRequest: pbops-rotate-auth-generated +``` + +**Verify Auth is rotated** +```shell +$ kubectl get PgBouncer -n demo pgbouncer-server -ojson | jq .spec.authsecret.name +"pgbouncer-server-auth" +$ kubectl get secret -n demo pgbouncer-server-auth -o=jsonpath='{.data.username}' | base64 -d +pgbouncer⏎ +$ kubectl get secrets -n demo pgbouncer-server-auth -o jsonpath='{.data.\password}' | base64 -d +Hc5nXhC403rvDGPf⏎ +``` +Also, there will be two more new keys in the secret that stores the previous credentials. The key is `authData.prev`. You can find the secret and its data by running the following command: + +```shell +$ kubectl get secret -n demo pgbouncer-server-auth -o go-template='{{ index .data "username.prev" }}' | base64 -d +pgbouncer⏎ +$ kubectl get secret -n demo pgbouncer-server-auth -o go-template='{{ index .data "password.prev" }}' | base64 -d +I*7SQB7)6~Kni8*X⏎ +``` +The above output shows that the password has been changed successfully. The previous username & password is stored for rollback purpose. +#### 2. Using user created credentials + +At first, we need to create a secret with kubernetes.io/basic-auth type using custom username and password. Below is the command to create a secret with kubernetes.io/basic-auth type, + +```shell +$ kubectl create secret generic quick-pb-user-auth -n demo \ + --type=kubernetes.io/basic-auth \ + --from-literal=username=user \ + --from-literal=password=PgBouncer2 +secret/quick-pb-user-auth created +``` +Now create a `PgBouncerOpsRequest` with `RotateAuth` type. Below is the YAML of the `PgBouncerOpsRequest` that we are going to create, + +```shell +apiVersion: ops.kubedb.com/v1alpha1 +kind: PgBouncerOpsRequest +metadata: + name: pbops-rotate-auth-user + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: pgbouncer-server + authentication: + secretRef: + name: quick-pb-user-auth + timeout: 5m + apply: IfReady +``` +Here, + +- `spec.databaseRef.name` specifies that we are performing rotate authentication operation on `pgbouncer-server`cluster. +- `spec.type` specifies that we are performing `RotateAuth` on PgBouncer. +- `spec.authentication.secretRef.name` specifies that we are using `quick-pb-user-auth` as `spec.authsecret.name` for authentication. + +Let's create the `PgBouncerOpsRequest` CR we have shown above, + +```shell +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/pgbouncer/rotate-auth/rotateauthuser.yaml +pgbounceropsrequest.ops.kubedb.com/pbops-rotate-auth-user created +``` +Let’s wait for `PgBouncerOpsRequest` to be Successful. Run the following command to watch `PgBouncerOpsRequest` CRO: + +```shell +$ kubectl get PgBouncerOpsRequest -n demo +NAME TYPE STATUS AGE +pbops-rotate-auth-generated RotateAuth Successful 20m +pbops-rotate-auth-user RotateAuth Successful 6m16s +``` +We can see from the above output that the `PgBouncerOpsRequest` has succeeded. If we describe the `PgBouncerOpsRequest` we will get an overview of the steps that were followed. +```shell +$ kubectl describe PgBounceropsrequest -n demo pbops-rotate-auth-user +Name: pbops-rotate-auth-user +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: PgBouncerOpsRequest +Metadata: + Creation Timestamp: 2025-07-18T04:39:59Z + Generation: 1 + Resource Version: 104227 + UID: 7a02957e-0144-4d6e-826b-8e27e04a6074 +Spec: + Apply: IfReady + Authentication: + secret Ref: + Name: quick-pb-user-auth + Database Ref: + Name: pgbouncer-server + Timeout: 5m + Type: RotateAuth +Status: + Conditions: + Last Transition Time: 2025-07-18T04:39:59Z + Message: PgBouncer ops request has started to rotate auth for pgbouncer + Observed Generation: 1 + Reason: RotateAuth + Status: True + Type: RotateAuth + Last Transition Time: 2025-07-18T04:39:59Z + Message: Successfully referenced the user provided authsecret + Observed Generation: 1 + Reason: UpdateCredential + Status: True + Type: UpdateCredential + Last Transition Time: 2025-07-18T04:40:00Z + Message: Successfully updated petsets rotate auth type + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2025-07-18T04:40:05Z + Message: get pod; ConditionStatus:True; PodName:pgbouncer-server-0 + Observed Generation: 1 + Status: True + Type: GetPod--pgbouncer-server-0 + Last Transition Time: 2025-07-18T04:40:05Z + Message: evict pod; ConditionStatus:True; PodName:pgbouncer-server-0 + Observed Generation: 1 + Status: True + Type: EvictPod--pgbouncer-server-0 + Last Transition Time: 2025-07-18T04:40:10Z + Message: check replica func; ConditionStatus:True; PodName:pgbouncer-server-0 + Observed Generation: 1 + Status: True + Type: CheckReplicaFunc--pgbouncer-server-0 + Last Transition Time: 2025-07-18T04:40:10Z + Message: check pod ready; ConditionStatus:True; PodName:pgbouncer-server-0 + Observed Generation: 1 + Status: True + Type: CheckPodReady--pgbouncer-server-0 + Last Transition Time: 2025-07-18T04:40:30Z + Message: check pg bouncer running; ConditionStatus:True; PodName:pgbouncer-server-0 + Observed Generation: 1 + Status: True + Type: CheckPgBouncerRunning--pgbouncer-server-0 + Last Transition Time: 2025-07-18T04:40:35Z + Message: Restart performed successfully in PgBouncer: demo/pgbouncer-server for PgBouncerOpsRequest: pbops-rotate-auth-user + Observed Generation: 1 + Reason: RestartPodsSucceeded + Status: True + Type: RestartPods + Last Transition Time: 2025-07-18T04:40:45Z + Message: Controller has successfully completed with RotateAuth of PgBouncerOpsRequest: demo/pbops-rotate-auth-user + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal VersionUpdate 6m54s KubeDB Ops-manager Operator Updating PetSets + Normal VersionUpdate 6m53s KubeDB Ops-manager Operator Successfully Updated PetSets + Normal VersionUpdate 6m53s KubeDB Ops-manager Operator Updating PetSets + Normal VersionUpdate 6m52s KubeDB Ops-manager Operator Successfully Updated PetSets + Warning get pod; ConditionStatus:True; PodName:pgbouncer-server-0 6m48s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:pgbouncer-server-0 + Warning evict pod; ConditionStatus:True; PodName:pgbouncer-server-0 6m48s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:pgbouncer-server-0 + Warning check replica func; ConditionStatus:True; PodName:pgbouncer-server-0 6m43s KubeDB Ops-manager Operator check replica func; ConditionStatus:True; PodName:pgbouncer-server-0 + Warning check pod ready; ConditionStatus:True; PodName:pgbouncer-server-0 6m43s KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:pgbouncer-server-0 + Warning check pg bouncer running; ConditionStatus:False; PodName:pgbouncer-server-0 6m33s KubeDB Ops-manager Operator check pg bouncer running; ConditionStatus:False; PodName:pgbouncer-server-0 + Warning check replica func; ConditionStatus:True; PodName:pgbouncer-server-0 6m33s KubeDB Ops-manager Operator check replica func; ConditionStatus:True; PodName:pgbouncer-server-0 + Warning check pod ready; ConditionStatus:True; PodName:pgbouncer-server-0 6m33s KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:pgbouncer-server-0 + Warning check replica func; ConditionStatus:True; PodName:pgbouncer-server-0 6m23s KubeDB Ops-manager Operator check replica func; ConditionStatus:True; PodName:pgbouncer-server-0 + Warning check pod ready; ConditionStatus:True; PodName:pgbouncer-server-0 6m23s KubeDB Ops-manager Operator check pod ready; ConditionStatus:True; PodName:pgbouncer-server-0 + Warning check pg bouncer running; ConditionStatus:True; PodName:pgbouncer-server-0 6m23s KubeDB Ops-manager Operator check pg bouncer running; ConditionStatus:True; PodName:pgbouncer-server-0 + Normal Successful 6m18s KubeDB Ops-manager Operator Restart performed successfully in PgBouncer: demo/pgbouncer-server for PgBouncerOpsRequest: pbops-rotate-auth-user + +``` +**Verify auth is rotate** +```shell +$ kubectl get PgBouncer -n demo pgbouncer-server -ojson | jq .spec.authsecret.name +"quick-pb-user-auth" +$ kubectl get secrets -n demo quick-pb-user-auth -o jsonpath='{.data.\username}' | base64 -d +user⏎ +$ kubectl get secrets -n demo quick-pb-user-auth -o jsonpath='{.data.\password}' | base64 -d +PgBouncer2⏎ +``` +Also, there will be two more new keys in the secret that stores the previous credentials. The keys are `username.prev` and `password.prev`. You can find the secret and its data by running the following command: +```shell +$ kubectl get secret -n demo quick-pb-user-auth -o go-template='{{ index .data "username.prev" }}' | base64 -d +pgbouncer⏎ +$ kubectl get secret -n demo quick-pb-user-auth -o go-template='{{ index .data "password.prev" }}' | base64 -d +Hc5nXhC403rvDGPf⏎ +``` + +The above output shows that the password has been changed successfully. The previous username & password is stored in the secret for rollback purpose. + +## Cleaning up + +To clean up the Kubernetes resources you can delete the CRD or namespace. +Or, you can delete one by one resource by their name by this tutorial, run: + +```shell +$ kubectl delete PgBounceropsrequest pbops-rotate-auth-generated pbops-rotate-auth-user -n demo +PgBounceropsrequest.ops.kubedb.com "pbops-rotate-auth-generated" "pbops-rotate-auth-user" deleted +$ kubectl delete secret -n demoquick-pb-user-auth +secret "quick-pb-user-auth" deleted +$ kubectl delete secret -n demo pgbouncer-server-auth +secret "pgbouncer-server-auth " deleted +``` + + +## Next Steps + +- Learn how to use KubeDB to run a PostgreSQL database [here](/docs/guides/postgres/README.md). +- Learn how to how to get started with PgBouncer [here](/docs/guides/pgbouncer/quickstart/quickstart.md). +- Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md). diff --git a/docs/guides/pgpool/rotateauth/_index.md b/docs/guides/pgpool/rotateauth/_index.md new file mode 100644 index 0000000000..c25914ca07 --- /dev/null +++ b/docs/guides/pgpool/rotateauth/_index.md @@ -0,0 +1,10 @@ +--- +title: Rotate Authentication Pgpool +menu: + docs_{{ .version }}: + identifier: pp-rotate-auth + name: Rotate Authentication + parent: pp-pgpool-guides + weight: 46 +menu_name: docs_{{ .version }} +--- diff --git a/docs/guides/pgpool/rotateauth/rotateauth.md b/docs/guides/pgpool/rotateauth/rotateauth.md new file mode 100644 index 0000000000..bde63cdcb9 --- /dev/null +++ b/docs/guides/pgpool/rotateauth/rotateauth.md @@ -0,0 +1,362 @@ +--- +title: Rotate Authentication Pgpool +menu: + docs_{{ .version }}: + identifier: pp-rotate-auth-details + name: Guide + parent: pp-rotate-auth + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + + +# Rotate Authentication of Pgpool + +**Rotate Authentication** is a feature of the KubeDB Ops-Manager that allows you to rotate a `Pgpool` user's authentication credentials using a `PgpoolOpsRequest`. There are two ways to perform this rotation. + +1. **Operator Generated:** The KubeDB operator automatically generates a random credential, updates the existing secret with the new credential The KubeDB operator automatically generates a random credential and updates the existing secret with the new credential.. +2. **User Defined:** The user can create their own credentials by defining a secret of type `kubernetes.io/basic-auth` containing the desired `username` and `password` and then reference this secret in the `PgpoolOpsRequest`. + +> Note: Before you begin, you have to create `Pgpool` CRD with the help of [this](/docs/guides/pgpool/quickstart/quickstart.md). +## Verify authentication +The user can verify whether they are authorized by executing a query directly in the database. To do this, the user needs `username` and `password` in order to connect to the database. Below is an example showing how to retrieve the credentials from the secret. + +````shell +$ kubectl get Pgpool -n pool quick-pgpool -ojson | jq .spec.authsecret.name +"quick-pgpool-auth" +$ kubectl get secrets -n pool quick-pgpool-auth -o jsonpath='{.data.\username}' | base64 -d +pcp⏎ +$ kubectl get secrets -n pool quick-pgpool-auth -o jsonpath='{.data.\password}' | base64 -d +gZoAOjr0iUkH07ku⏎ +```` + +## Create RotateAuth PgpoolOpsRequest + + +#### 1. Using operator generated credentials: + +In order to rotate authentication to the Pgpool using operator generated, we have to create a `PgpoolOpsRequest` CR with `RotateAuth` type. Below is the YAML of the `PgpoolOpsRequest` CR that we are going to create, +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: PgpoolOpsRequest +metadata: + name: pgpops-rotate-auth-generated + namespace: pool +spec: + type: RotateAuth + databaseRef: + name: quick-pgpool + timeout: 5m + apply: IfReady +``` +Here, + +- `spec.databaseRef.name` specifies that we are performing rotate authentication operation on `quick-pgpool` cluster. +- `spec.type` specifies that we are performing `RotateAuth` on Pgpool. + +Let's create the `PgpoolOpsRequest` CR we have shown above, +```shell + $kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/pgpool/rotate-auth/rotate-auth.yaml + pgpoolopsrequest.ops.kubedb.com/pgpops-rotate-auth-generated created +``` +Let's wait for `PgpoolOpsrequest` to be `Successful`. Run the following command to watch `PgpoolOpsrequest` CR +```shell + $ kubectl get PgpoolOpsRequest -n pool +NAME TYPE STATUS AGE +pgpops-rotate-auth-generated RotateAuth Successful 52s +``` +If we describe the `PgpoolOpsRequest` we will get an overview of the steps that were followed. +```shell +$ kubectl describe pgpoolopsrequest -n pool pgpops-rotate-auth-generated +Name: pgpops-rotate-auth-generated +Namespace: pool +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: PgpoolOpsRequest +Metadata: + Creation Timestamp: 2025-08-01T08:48:44Z + Generation: 1 + Resource Version: 653764 + UID: 3822eb18-a4ab-497e-901a-1b7ddb76a516 +Spec: + Apply: IfReady + Database Ref: + Name: quick-pgpool + Timeout: 5m + Type: RotateAuth +Status: + Conditions: + Last Transition Time: 2025-08-01T08:48:44Z + Message: Pgpool ops request has started to rotate auth for pgpool + Observed Generation: 1 + Reason: RotateAuth + Status: True + Type: RotateAuth + Last Transition Time: 2025-08-01T08:48:47Z + Message: Successfully paused database + Observed Generation: 1 + Reason: DatabasePauseSucceeded + Status: True + Type: DatabasePauseSucceeded + Last Transition Time: 2025-08-01T08:48:47Z + Message: Successfully generated new credentials + Observed Generation: 1 + Reason: UpdateCredential + Status: True + Type: UpdateCredential + Last Transition Time: 2025-08-01T08:48:48Z + Message: Successfully updated petsets rotate auth type + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2025-08-01T08:49:33Z + Message: Successfully Restarted Pods With New User + Observed Generation: 1 + Reason: RestartPods + Status: True + Type: RestartPods + Last Transition Time: 2025-08-01T08:48:53Z + Message: get pod; ConditionStatus:True; PodName:quick-pgpool-0 + Observed Generation: 1 + Status: True + Type: GetPod--quick-pgpool-0 + Last Transition Time: 2025-08-01T08:48:53Z + Message: evict pod; ConditionStatus:True; PodName:quick-pgpool-0 + Observed Generation: 1 + Status: True + Type: EvictPod--quick-pgpool-0 + Last Transition Time: 2025-08-01T08:49:28Z + Message: check pod running; ConditionStatus:True; PodName:quick-pgpool-0 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--quick-pgpool-0 + Last Transition Time: 2025-08-01T08:49:33Z + Message: Successfully completed the reconfigure for Pgpool + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Starting 3m21s KubeDB Ops-manager Operator Start processing for PgpoolOpsRequest: pool/pgpops-rotate-auth-generated + Normal Starting 3m21s KubeDB Ops-manager Operator Pausing Pgpool databse: pool/quick-pgpool + Normal Successful 3m21s KubeDB Ops-manager Operator Successfully paused Pgpool database: pool/quick-pgpool for PgpoolOpsRequest: pgpops-rotate-auth-generated + Normal VersionUpdate 3m18s KubeDB Ops-manager Operator Updating PetSets + Normal VersionUpdate 3m17s KubeDB Ops-manager Operator Successfully Updated PetSets + Warning get pod; ConditionStatus:True; PodName:quick-pgpool-0 3m12s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:quick-pgpool-0 + Warning evict pod; ConditionStatus:True; PodName:quick-pgpool-0 3m12s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:quick-pgpool-0 + Warning check pod running; ConditionStatus:False; PodName:quick-pgpool-0 3m7s KubeDB Ops-manager Operator check pod running; ConditionStatus:False; PodName:quick-pgpool-0 + Warning check pod running; ConditionStatus:True; PodName:quick-pgpool-0 2m37s KubeDB Ops-manager Operator check pod running; ConditionStatus:True; PodName:quick-pgpool-0 + Normal RestartPods 2m32s KubeDB Ops-manager Operator Successfully Restarted Pods With New User + Normal Starting 2m32s KubeDB Ops-manager Operator Resuming Pgpool database: pool/quick-pgpool + Normal Successful 2m32s KubeDB Ops-manager Operator Successfully resumed Pgpool database: pool/quick-pgpool for PgpoolOpsRequest: pgpops-rotate-auth-generated +``` + +**Verify Auth is rotated** +```shell +$ kubectl get Pgpool -n pool quick-pgpool -ojson | jq .spec.authsecret.name +"quick-pgpool-auth" +$ kubectl get secrets -n pool quick-pgpool-auth -o jsonpath='{.data.\username}' | base64 -d +pcp⏎ +$ kubectl get secrets -n pool quick-pgpool-auth -o jsonpath='{.data.\password}' | base64 -d +h1yPX0CjgGXNjpKY⏎ +``` +Also, there will be two more new keys in the secret that stores the previous credentials. The key is `authData.prev`. You can find the secret and its data by running the following command: + +```shell +$ kubectl get secret -n pool quick-pgpool-auth -o go-template='{{ index .data "username.prev" }}' | base64 -d +pcp⏎ +$ kubectl get secret -n pool quick-pgpool-auth -o go-template='{{ index .data "password.prev" }}' | base64 -d +gZoAOjr0iUkH07ku⏎ +``` +The above output shows that the password has been changed successfully. The previous username & password is stored for rollback purpose. +#### 2. Using user created credentials + +At first, we need to create a secret with kubernetes.io/basic-auth type using custom username and password. Below is the command to create a secret with kubernetes.io/basic-auth type, + +```shell +$ kubectl create secret generic quick-pp-user-auth -n pool \ + --type=kubernetes.io/basic-auth \ + --from-literal=username=user \ + --from-literal=password=Pgpool2 +secret/quick-pp-user-auth created +``` +Now create a `PgpoolOpsRequest` with `RotateAuth` type. Below is the YAML of the `PgpoolOpsRequest` that we are going to create, + +```shell +apiVersion: ops.kubedb.com/v1alpha1 +kind: PgpoolOpsRequest +metadata: + name: ppops-rotate-auth-user + namespace: pool +spec: + type: RotateAuth + databaseRef: + name: quick-pgpool + authentication: + secretRef: + name: quick-pp-user-auth + timeout: 5m + apply: IfReady +``` +Here, + +- `spec.databaseRef.name` specifies that we are performing rotate authentication operation on `quick-pgpool`cluster. +- `spec.type` specifies that we are performing `RotateAuth` on Pgpool. +- `spec.authentication.secretRef.name` specifies that we are using `quick-pp-user-auth` as `spec.authsecret.name` for authentication. + +Let's create the `PgpoolOpsRequest` CR we have shown above, + +```shell +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/pgpool/rotate-auth/rotateauthuser.yaml +Pgpoolopsrequest.ops.kubedb.com/pbops-rotate-auth-user created +``` +Let’s wait for `PgpoolOpsRequest` to be Successful. Run the following command to watch `PgpoolOpsRequest` CR: + +```shell +$ kubectl get PgpoolOpsRequest -n pool +NAME TYPE STATUS AGE +pgpops-rotate-auth-generated RotateAuth Successful 56m +ppops-rotate-auth-user RotateAuth Successful 44m +``` +We can see from the above output that the `PgpoolOpsRequest` has succeeded. If we describe the `PgpoolOpsRequest` we will get an overview of the steps that were followed. +```shell +$ kubectl describe Pgpoolopsrequest -n pool ppops-rotate-auth-user +Name: ppops-rotate-auth-user +Namespace: pool +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: PgpoolOpsRequest +Metadata: + Creation Timestamp: 2025-08-01T08:55:40Z + Generation: 1 + Resource Version: 654393 + UID: 5bba7694-a979-4ce0-9fcd-4e8b11287277 +Spec: + Apply: IfReady + Authentication: + secret Ref: + Name: quick-pp-user-auth + Database Ref: + Name: quick-pgpool + Timeout: 5m + Type: RotateAuth +Status: + Conditions: + Last Transition Time: 2025-08-01T08:55:40Z + Message: Pgpool ops request has started to rotate auth for pgpool + Observed Generation: 1 + Reason: RotateAuth + Status: True + Type: RotateAuth + Last Transition Time: 2025-08-01T08:55:43Z + Message: Successfully paused database + Observed Generation: 1 + Reason: DatabasePauseSucceeded + Status: True + Type: DatabasePauseSucceeded + Last Transition Time: 2025-08-01T08:55:43Z + Message: Successfully referenced the user provided authsecret + Observed Generation: 1 + Reason: UpdateCredential + Status: True + Type: UpdateCredential + Last Transition Time: 2025-08-01T08:55:44Z + Message: Successfully updated petsets rotate auth type + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2025-08-01T08:56:29Z + Message: Successfully Restarted Pods With New User + Observed Generation: 1 + Reason: RestartPods + Status: True + Type: RestartPods + Last Transition Time: 2025-08-01T08:55:49Z + Message: get pod; ConditionStatus:True; PodName:quick-pgpool-0 + Observed Generation: 1 + Status: True + Type: GetPod--quick-pgpool-0 + Last Transition Time: 2025-08-01T08:55:49Z + Message: evict pod; ConditionStatus:True; PodName:quick-pgpool-0 + Observed Generation: 1 + Status: True + Type: EvictPod--quick-pgpool-0 + Last Transition Time: 2025-08-01T08:56:24Z + Message: check pod running; ConditionStatus:True; PodName:quick-pgpool-0 + Observed Generation: 1 + Status: True + Type: CheckPodRunning--quick-pgpool-0 + Last Transition Time: 2025-08-01T08:56:29Z + Message: Successfully completed the reconfigure for Pgpool + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Starting 5m5s KubeDB Ops-manager Operator Start processing for PgpoolOpsRequest: pool/ppops-rotate-auth-user + Normal Starting 5m5s KubeDB Ops-manager Operator Pausing Pgpool databse: pool/quick-pgpool + Normal Successful 5m5s KubeDB Ops-manager Operator Successfully paused Pgpool database: pool/quick-pgpool for PgpoolOpsRequest: ppops-rotate-auth-user + Normal VersionUpdate 5m2s KubeDB Ops-manager Operator Updating PetSets + Normal VersionUpdate 5m1s KubeDB Ops-manager Operator Successfully Updated PetSets + Warning get pod; ConditionStatus:True; PodName:quick-pgpool-0 4m56s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:quick-pgpool-0 + Warning evict pod; ConditionStatus:True; PodName:quick-pgpool-0 4m56s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:quick-pgpool-0 + Warning check pod running; ConditionStatus:False; PodName:quick-pgpool-0 4m51s KubeDB Ops-manager Operator check pod running; ConditionStatus:False; PodName:quick-pgpool-0 + Warning check pod running; ConditionStatus:True; PodName:quick-pgpool-0 4m21s KubeDB Ops-manager Operator check pod running; ConditionStatus:True; PodName:quick-pgpool-0 + Normal RestartPods 4m16s KubeDB Ops-manager Operator Successfully Restarted Pods With New User + Normal Starting 4m16s KubeDB Ops-manager Operator Resuming Pgpool database: pool/quick-pgpool + Normal Successful 4m16s KubeDB Ops-manager Operator Successfully resumed Pgpool database: pool/quick-pgpool for PgpoolOpsRequest: ppops-rotate-auth-user + +``` +**Verify auth is rotate** +```shell +$ kubectl get pgpool -n pool quick-pgpool -ojson | jq .spec.authsecret.name +"quick-pp-user-auth" +$ kubectl get secrets -n pool quick-pp-user-auth -o jsonpath='{.data.\username}' | base64 -d +user⏎ +$ kubectl get secrets -n pool quick-pp-user-auth -o jsonpath='{.data.\password}' | base64 -d +Pgpool2⏎ +``` +Also, there will be two more new keys in the secret that stores the previous credentials. The keys are `username.prev` and `password.prev`. You can find the secret and its data by running the following command: +```shell +$ kubectl get secret -n pool quick-pp-user-auth -o go-template='{{ index .data "username.prev" }}' | base64 -d +pcp⏎ +$ kubectl get secret -n pool quick-pp-user-auth -o go-template='{{ index .data "password.prev" }}' | base64 -d +gZoAOjr0iUkH07ku⏎ +``` + +The above output shows that the password has been changed successfully. The previous username & password is stored in the secret for rollback purpose. + +## Cleaning up + +To clean up the Kubernetes resources you can delete the CRD or namespace. +Or, you can delete one by one resource by their name by this tutorial, run: + +```shell +$ kubectl delete Pgpoolopsrequest pgpops-rotate-auth-generated ppops-rotate-auth-user -n pool +Pgpoolopsrequest.ops.kubedb.com "pgpops-rotate-auth-generated" "ppops-rotate-auth-user" deleted +$ kubectl delete secret -n pool quick-pp-user-auth +secret "quick-pp-user-auth" deleted +$ kubectl delete secret -n pool quick-pgpool-auth +secret "quick-pgpool-auth " deleted +``` + +## Next Steps + +- Detail concepts of [Pgpool object](/docs/guides/pgpool/concepts/pgpool.md). +- Monitor your Pgpool database with KubeDB using [out-of-the-box Prometheus operator](/docs/guides/pgpool/monitoring/using-prometheus-operator.md). +- Monitor your Pgpool database with KubeDB using [out-of-the-box builtin-Prometheus](/docs/guides/pgpool/monitoring/using-builtin-prometheus.md). +- Detail concepts of [Pgpool object](/docs/guides/pgpool/concepts/pgpool.md). +- Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md). diff --git a/docs/guides/postgres/configuration/using-config-file.md b/docs/guides/postgres/configuration/using-config-file.md index bda13136ed..1de596f696 100644 --- a/docs/guides/postgres/configuration/using-config-file.md +++ b/docs/guides/postgres/configuration/using-config-file.md @@ -54,7 +54,7 @@ shared_buffers=256MB Now, create a Secret with this configuration file. ```bash -$ kubectl create secret generic -n demo pg-configuration --from-literal=user.conf="$(curl -fsSL https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/postgres/configuration/user.conf)" +$ kubectl create secret generic -n demo pg-configuration --from-literal=user.conf="$(curl -fsSL https://raw.githubusercontent.com/kubedb/docs/v2025.6.30/docs/examples/postgres/custom-config/user.conf)" secret/pg-configuration created ``` diff --git a/docs/guides/postgres/rotate-authentication/_index.md b/docs/guides/postgres/rotate-authentication/_index.md new file mode 100644 index 0000000000..2195b4dcfe --- /dev/null +++ b/docs/guides/postgres/rotate-authentication/_index.md @@ -0,0 +1,10 @@ +--- +title: Rotate Authentication Postgres +menu: + docs_{{ .version }}: + identifier: pg-rotate-authentication + name: Rotate Authentication + parent: pg-postgres-guides + weight: 46 +menu_name: docs_{{ .version }} +--- diff --git a/docs/guides/postgres/rotate-authentication/rotateauth.md b/docs/guides/postgres/rotate-authentication/rotateauth.md new file mode 100644 index 0000000000..fa150f753e --- /dev/null +++ b/docs/guides/postgres/rotate-authentication/rotateauth.md @@ -0,0 +1,427 @@ +--- +title: Rotate Authentication Guide +menu: + docs_{{ .version }}: + identifier: pg-rotate-auth-details + name: Guide + parent: pg-rotate-authentication + weight: 30 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- +# Rotate Authentication of PostgerSQL + +**Rotate Authentication** is a feature of the KubeDB Ops-Manager that allows you to rotate a `Postgres` user's authentication credentials using a `PostgresOpsRequest`. There are two ways to perform this rotation. + +1. **Operator Generated:** The KubeDB operator automatically generates a random credential, updates the existing secret with the new credential The KubeDB operator automatically generates a random credential and updates the existing secret with the new credential.. +2. **User Defined:** The user can create their own credentials by defining a secret of type `kubernetes.io/basic-auth` containing the desired `username` and `password` and then reference this secret in the `PostgresOpsRequest`. + +## Before You Begin + +- You should be familiar with the following `KubeDB` concepts: + - [PostgreSQL](/docs/guides/postgres/concepts/postgres.md) + - [PostgresOpsRequest](/docs/guides/postgres/concepts/opsrequest.md) + +- At first, you need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Now, install KubeDB cli on your workstation and KubeDB operator in your cluster following the steps [here](/docs/setup/README.md). + +- To keep things isolated, this tutorial uses a separate namespace called `demo` throughout this tutorial. + + ```bash + $ kubectl create ns demo + namespace/demo created + ``` + +## Create a PostgreSQL database +KubeDB implements a Postgres CRD to define the specification of a PostgreSQL database. + +You can apply this yaml file: + +```yaml +apiVersion: kubedb.com/v1 +kind: Postgres +metadata: + name: quick-postgres + namespace: demo +spec: + version: "13.13" + storageType: Durable + storage: + storageClassName: "standard" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: DoNotTerminate +``` + +Command: + +```shell +$ kubectl apply -f postgres.yaml +postgres.kubedb.com/quick-postgres created +``` + +Or, you can deploy by using command: + +```shell +$ kubectl create -f https://github.com/kubedb/docs/raw/{{ .version }}/docs/examples/postgres/quickstart/quick-postgres-v1.yaml +postgres.kubedb.com/quick-postgres created +``` + +Now, wait until quick-postgres has status Ready. i.e, + +```shell +$ kubectl get pg -n demo -w +NAME VERSION STATUS AGE +quick-postgres 13.13 Ready 7m36s +``` +## Verify authentication +The user can verify whether they are authorized by executing a query directly in the database. To do this, the user needs `username` and `password` in order to connect to the database using the `kubectl exec` command. Below is an example showing how to retrieve the credentials from the secret. + +````shell +$ kubectl get pg -n demo quick-postgres -ojson | jq .spec.authsecret.name +"quick-postgres-auth" +$ kubectl get secret -n demo quick-postgres-auth -o jsonpath='{.data.username}' | base64 -d +postgres +$ kubectl get secret -n demo quick-postgres-auth -o jsonpath='{.data.password}' | base64 -d +yFj_WnVA9rxfQlLt +```` +Now, you can exec into the pod `quick-postgres-0` and connect to database using `username` and `password` +```shell +$ kubectl exec -it -n demo quick-postgres-0 -- bash +Defaulted container "postgres" out of: postgres, postgres-init-container (init) + +quick-postgres-0:/$ PGPASSWORD=yFj_WnVA9rxfQlLt psql -U postgres -d postgres -p 5432 -h quick-postgres.demo.svc +psql (13.13) +Type "help" for help. +postgres=# \dt + List of relations + Schema | Name | Type | Owner +--------+--------------------+-------+---------- + public | kubedb_write_check | table | postgres + (1 row) +``` +If you can access the data table and run queries, it means the secrets are working correctly. +## Create RotateAuth PostgresOpsRequest + +#### 1. Using operator generated credentials: + +In order to rotate authentication to the Postgres using operator generated, we have to create a `PostgresOpsRequest` CRO with `RotateAuth` type. Below is the YAML of the `PostgresOpsRequest` CRO that we are going to create, +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: PostgresOpsRequest +metadata: + name: pgops-rotate-auth-generated + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: quick-postgres + timeout: 5m + apply: IfReady +``` +Here, + +- `spec.databaseRef.name` specifies that we are performing rotate authentication operation on `quick-postgres` cluster. +- `spec.type` specifies that we are performing `RotateAuth` on Postgres. + +Let's create the `PostgresOpsRequest` CR we have shown above, +```shell + $ kubectl apply -f https://github.com/kubedb/docs/raw/{{ .version }}/docs/examples/postgres/rotate-auth/postgres-rotate-auth-generated.yaml + postgresopsrequest.ops.kubedb.com/pgops-rotate-auth-generated created +``` +Let's wait for `PostgresOpsrequest` to be `Successful`. Run the following command to watch `PostgresOpsrequest` CRO +```shell + $ kubectl get postgresopsrequest -n demo + NAME TYPE STATUS AGE + pgops-rotate-auth-generated RotateAuth Successful 7m47s +``` +If we describe the `PostgresOpsRequest` we will get an overview of the steps that were followed. +```shell +$ kubectl describe postgresopsrequest -n demo pgops-rotate-auth-generated + Name: pgops-rotate-auth-generated + Namespace: demo + Labels: + Annotations: + API Version: ops.kubedb.com/v1alpha1 + Kind: PostgresOpsRequest + Metadata: + Creation Timestamp: 2025-07-08T11:24:10Z + Generation: 1 + Resource Version: 546623 + UID: 97a07133-c98e-457c-9249-85c0c690a82e + Spec: + Apply: IfReady + Database Ref: + Name: quick-postgres + Timeout: 5m + Type: RotateAuth + Status: + Conditions: + Last Transition Time: 2025-07-08T11:24:10Z + Message: Postgres ops request has started to rotate auth for postgres + Observed Generation: 1 + Reason: RotateAuth + Status: True + Type: RotateAuth + Last Transition Time: 2025-07-08T11:24:13Z + Message: Successfully generated new credentials + Observed Generation: 1 + Reason: UpdateCredential + Status: True + Type: UpdateCredential + Last Transition Time: 2025-07-08T11:24:15Z + Message: Successfully updated petsets for rotate auth type + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2025-07-08T11:24:55Z + Message: Successfully restarted all the nodes + Observed Generation: 1 + Reason: RestartNodes + Status: True + Type: RestartNodes + Last Transition Time: 2025-07-08T11:24:20Z + Message: evict pod; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: EvictPod + Last Transition Time: 2025-07-08T11:24:20Z + Message: check pod ready; ConditionStatus:False; PodName:quick-postgres-0 + Observed Generation: 1 + Status: False + Type: CheckPodReady--quick-postgres-0 + Last Transition Time: 2025-07-08T11:24:55Z + Message: check pod ready; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: CheckPodReady + Last Transition Time: 2025-07-08T11:24:56Z + Message: Successfully Rotated Postgres Auth secret + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful + Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal PauseDatabase 20m KubeDB Ops-manager Operator Pausing Postgres demo/quick-postgres + Normal PauseDatabase 20m KubeDB Ops-manager Operator Successfully paused Postgres demo/quick-postgres + Normal VersionUpdate 20m KubeDB Ops-manager Operator Updating PetSets + Normal VersionUpdate 20m KubeDB Ops-manager Operator Successfully Updated PetSets + Warning evict pod; ConditionStatus:True 20m KubeDB Ops-manager Operator evict pod; ConditionStatus:True + Warning check pod ready; ConditionStatus:False; PodName:quick-postgres-0 20m KubeDB Ops-manager Operator check pod ready; ConditionStatus:False; PodName:quick-postgres-0 + Warning check pod ready; ConditionStatus:True 19m KubeDB Ops-manager Operator check pod ready; ConditionStatus:True + Normal RestartNodes 19m KubeDB Ops-manager Operator Successfully restarted all the nodes + Normal ResumeDatabase 19m KubeDB Ops-manager Operator Resuming PostgreSQL demo/quick-postgres + Normal ResumeDatabase 19m KubeDB Ops-manager Operator Successfully resumed PostgreSQL demo/quick-postgres + Normal Successful 19m KubeDB Ops-manager Operator Successfully Rotated Postgres Auth secret for demo/quick-postgres + +``` +**Verify Auth is rotated** +```shell +$ kubectl get pg -n demo quick-postgres -ojson | jq .spec.authsecret.name +"quick-postgres-auth" +$ kubectl get secret -n demo quick-postgres-auth -o=jsonpath='{.data.username}' | base64 -d + postgres +$ kubectl get secret -n demo quick-postgres-auth -o jsonpath='{.data.password}' | base64 -d + zGB9GF!NXwI.2HP9⏎ +``` +Also, there will be two more new keys in the secret that stores the previous credentials. The keys are `username.prev` and `password.prev`. You can find the secret and its data by running the following command: + +```shell +$ kubectl get secret -n demo quick-postgres-auth -o go-template='{{ index .data "username.prev" }}' | base64 -d +postgres +$ kubectl get secret -n demo quick-postgres-auth -o go-template='{{ index .data "password.prev" }}' | base64 -d +yFj_WnVA9rxfQlLt +``` +The above output shows that the password has been changed successfully. The previous username & password is stored for rollback purpose. +#### 2. Using user created credentials + +At first, we need to create a secret with kubernetes.io/basic-auth type using custom username and password. Below is the command to create a secret with kubernetes.io/basic-auth type, + +```shell +$ kubectl create secret generic quick-postgres-user-auth -n demo \ + --type=kubernetes.io/basic-auth \ + --from-literal=username=admin \ + --from-literal=password=postgres-secret + secret/quick-postgres-user-auth created +``` +Now create a `PostgresOpsRequest` with `RotateAuth` type. Below is the YAML of the `PostgresOpsRequest` +that we are going to create, + +```shell +apiVersion: ops.kubedb.com/v1alpha1 +kind: PostgresOpsRequest +metadata: + name: pgops-rotate-auth-user + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: quick-postgres + authentication: + secretRef: + name: quick-postgres-user-auth + timeout: 5m + apply: IfReady +``` +Here, + +- `spec.databaseRef.name` specifies that we are performing rotate authentication operation on `quick-postgres`cluster. +- `spec.type` specifies that we are performing `RotateAuth` on postgres. +- `spec.authentication.secretRef.name` specifies that we are using `quick-postgres-user-auth` as `spec.authsecret.name` for authentication. + +Let's create the `PostgresOpsRequest` CR we have shown above, + +```shell +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{ .version }}/docs/examples/postgres/rotate-auth/rotate-auth-user.yaml +postgresopsrequest.ops.kubedb.com/pgops-rotate-auth-user created +``` +Let’s wait for `PostgresOpsRequest` to be Successful. Run the following command to watch `PostgresOpsRequest` CRO: + +```shell +$ kubectl get postgresopsrequest -n demo +NAME TYPE STATUS AGE +pgops-rotate-auth-generated RotateAuth Successful 19h +pgops-rotate-auth-user RotateAuth Successful 7m44s +``` +We can see from the above output that the `PostgresOpsRequest` has succeeded. If we describe the `PostgresOpsRequest` we will get an overview of the steps that were followed. +```shell +$ kubectl describe postgresopsrequest -n demo pgops-rotate-auth-user +Name: pgops-rotate-auth-user +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: PostgresOpsRequest +Metadata: + Creation Timestamp: 2025-07-09T06:45:44Z + Generation: 1 + Resource Version: 562328 + UID: d25c3d36-cc15-4c82-8fe4-64e5ffc1467c +Spec: + Apply: IfReady + Authentication: + secret Ref: + Name: quick-postgres-user-auth + Database Ref: + Name: quick-postgres + Timeout: 5m + Type: RotateAuth +Status: + Conditions: + Last Transition Time: 2025-07-09T06:45:44Z + Message: Postgres ops request has started to rotate auth for postgres + Observed Generation: 1 + Reason: RotateAuth + Status: True + Type: RotateAuth + Last Transition Time: 2025-07-09T06:45:47Z + Message: Successfully referenced the user provided authsecret + Observed Generation: 1 + Reason: UpdateCredential + Status: True + Type: UpdateCredential + Last Transition Time: 2025-07-09T06:45:50Z + Message: Successfully updated petsets for rotate auth type + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2025-07-09T06:46:30Z + Message: Successfully restarted all the nodes + Observed Generation: 1 + Reason: RestartNodes + Status: True + Type: RestartNodes + Last Transition Time: 2025-07-09T06:45:55Z + Message: evict pod; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: EvictPod + Last Transition Time: 2025-07-09T06:45:55Z + Message: check pod ready; ConditionStatus:False; PodName:quick-postgres-0 + Observed Generation: 1 + Status: False + Type: CheckPodReady--quick-postgres-0 + Last Transition Time: 2025-07-09T06:46:30Z + Message: check pod ready; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: CheckPodReady + Last Transition Time: 2025-07-09T06:46:30Z + Message: Successfully Rotated Postgres Auth secret + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal PauseDatabase 10m KubeDB Ops-manager Operator Pausing Postgres demo/quick-postgres + Normal PauseDatabase 10m KubeDB Ops-manager Operator Successfully paused Postgres demo/quick-postgres + Normal VersionUpdate 10m KubeDB Ops-manager Operator Updating PetSets + Normal VersionUpdate 10m KubeDB Ops-manager Operator Successfully Updated PetSets + Warning evict pod; ConditionStatus:True 10m KubeDB Ops-manager Operator evict pod; ConditionStatus:True + Warning check pod ready; ConditionStatus:False; PodName:quick-postgres-0 10m KubeDB Ops-manager Operator check pod ready; ConditionStatus:False; PodName:quick-postgres-0 + Warning check pod ready; ConditionStatus:True 9m58s KubeDB Ops-manager Operator check pod ready; ConditionStatus:True + Normal RestartNodes 9m58s KubeDB Ops-manager Operator Successfully restarted all the nodes + Normal ResumeDatabase 9m58s KubeDB Ops-manager Operator Resuming PostgreSQL demo/quick-postgres + Normal ResumeDatabase 9m58s KubeDB Ops-manager Operator Successfully resumed PostgreSQL demo/quick-postgres + Normal Successful 9m58s KubeDB Ops-manager Operator Successfully Rotated Postgres Auth secret for demo/quick-postgres + +``` +**Verify auth is rotate** +```shell +$ kubectl get pg -n demo quick-postgres -ojson | jq .spec.authsecret.name +"quick-postgres-user-auth" +$ kubectl get secret -n demo quick-postgres-user-auth-new -o=jsonpath='{.data.username}' | base64 -d +admin +$ kubectl get secret -n demo quick-postgres-user-auth-new -o=jsonpath='{.data.password}' | base64 -d +postgres-secret +``` +Also, there will be two more new keys in the secret that stores the previous credentials. The keys are `username.prev` and `password.prev`. You can find the secret and its data by running the following command: +```shell +$ kubectl get secret -n demo quick-postgres-user-auth -o go-template='{{ index .data "username.prev" }}' | base64 -d +postgres +$ kubectl get secret -n demo quick-postgres-user-auth -o go-template='{{ index .data "password.prev" }}' | base64 -d +zGB9GF!NXwI.2HP9 +``` + +The above output shows that the password has been changed successfully. The previous username & password is stored in the secret for rollback purpose. + +## Cleaning up + +To clean up the Kubernetes resources you can delete the CRD or namespace. +Or, you can delete one by one resource by their name by this tutorial, run: + +```shell +$ kubectl delete postgresopsrequest pgops-rotate-auth-generated pgops-rotate-auth-user -n demo +postgresopsrequest.ops.kubedb.com "pgops-rotate-auth-generated" "pgops-rotate-auth-user" deleted +$ kubectl delete secret -n demo quick-postgres-user-auth +secret "quick-postgres-user-auth" deleted +$ kubectl delete secret -n demo quick-postgres-auth +secret "quick-postgres-auth" deleted +``` + + +## Next Steps + +- Learn about [backup and restore](/docs/guides/postgres/backup/stash/overview/index.md) PostgreSQL database using Stash. +- Learn about initializing [PostgreSQL with Script](/docs/guides/postgres/initialization/script_source.md). +- Learn about [custom PostgresVersions](/docs/guides/postgres/custom-versions/setup.md). +- Want to setup PostgreSQL cluster? Check how to [configure Highly Available PostgreSQL Cluster](/docs/guides/postgres/clustering/ha_cluster.md) +- Monitor your PostgreSQL database with KubeDB using [built-in Prometheus](/docs/guides/postgres/monitoring/using-builtin-prometheus.md). +- Monitor your PostgreSQL database with KubeDB using [Prometheus operator](/docs/guides/postgres/monitoring/using-prometheus-operator.md). +- Detail concepts of [Postgres object](/docs/guides/postgres/concepts/postgres.md). +- Use [private Docker registry](/docs/guides/postgres/private-registry/using-private-registry.md) to deploy PostgreSQL with KubeDB. +- Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md). diff --git a/docs/guides/rabbitmq/configuration/using-podtemplate.md b/docs/guides/rabbitmq/configuration/using-podtemplate.md index 42c414386e..fd348a0f22 100644 --- a/docs/guides/rabbitmq/configuration/using-podtemplate.md +++ b/docs/guides/rabbitmq/configuration/using-podtemplate.md @@ -429,7 +429,7 @@ Containers: memory: 1Gi Mounts: /config from rabbitmq-config (rw) - /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-69qx2 (ro) + /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-69qx2 (rotate-auth) Conditions: Type Status PodScheduled False diff --git a/docs/guides/rabbitmq/rotate-auth/_index.md b/docs/guides/rabbitmq/rotate-auth/_index.md new file mode 100644 index 0000000000..75f5f36522 --- /dev/null +++ b/docs/guides/rabbitmq/rotate-auth/_index.md @@ -0,0 +1,10 @@ +--- +title: Rotateauth RabbitMQ +menu: + docs_{{ .version }}: + identifier: rm-rotateauth + name: Rotate Authentication + parent: rm-guides + weight: 105 +menu_name: docs_{{ .version }} +--- diff --git a/docs/guides/rabbitmq/rotate-auth/guide.md b/docs/guides/rabbitmq/rotate-auth/guide.md new file mode 100644 index 0000000000..e4d078f5ce --- /dev/null +++ b/docs/guides/rabbitmq/rotate-auth/guide.md @@ -0,0 +1,583 @@ +--- +title: RabbitMQ Rotateauth Guide +menu: + docs_{{ .version }}: + identifier: rm-rotateauth-guide + name: Guide + parent: rm-rotateauth + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +# Rotate Authentication of RabbitMQ + +**Rotate Authentication** is a feature of the KubeDB Ops-Manager that allows you to rotate a +`RabbitMQ` user's authentication credentials using a `RabbitMQOpsRequest`. There are two ways to +perform this rotation. + +1. **Operator Generated:** The KubeDB operator automatically generates a random credential and +updates the existing secret with the new credential. +2. **User Defined:** The user can create their own credentials by defining a secret of type + `kubernetes.io/basic-auth` containing the desired `password` and then reference this secret in +the `RabbitMQOpsRequest` CR. + +## Before You Begin + +- At first, you need to have a Kubernetes cluster, and the kubectl command-line tool must be +configured to communicate with your cluster. If you do not already have a cluster, you can create +one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Now, install KubeDB in your cluster following the steps [here](/docs/setup/README.md) and make +sure install with helm command including `--set global.featureGates.RabbitMQ=true` to ensure +RabbitMQ CRDs. + +- [StorageClass](https://kubernetes.io/docs/concepts/storage/storage-classes/) is required to run +KubeDB. Check the available StorageClass in cluster. + + ```bash + $ kubectl get storageclasses + NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE + standard (default) rancher.io/local-path Delete WaitForFirstConsumer false 6h22m + ``` + +- To keep things isolated, this tutorial uses a separate namespace called `demo` throughout this +tutorial. + + ```bash + $ kubectl create ns demo + namespace/demo created + ``` + +## Find Available RabbitMQVersion + +When you have installed KubeDB, it has created `RabbitMQVersion` CR for all supported RabbitMQ versions. Check it by using the `kubectl get rabbitmqversions` command. You can also use `rmv` shorthand instead of `rabbitmqversions`. + +```bash +$ kubectl get rabbitmqversion +NAME VERSION DB_IMAGE DEPRECATED AGE +3.12.12 3.12.12 ghcr.io/appscode-images/rabbitmq:3.12.12-management-alpine 3h13m +3.13.2 3.13.2 ghcr.io/appscode-images/rabbitmq:3.13.2-management-alpine 3h13m +4.0.4 4.0.4 ghcr.io/appscode-images/rabbitmq:4.0.4-management-alpine 3h13m +``` + +## Create a RabbitMQ server + +KubeDB implements a `RabbitMQ` CRD to define the specification of a RabbitMQ server. Below is the `RabbitMQ` object created in this tutorial. + +```yaml +apiVersion: kubedb.com/v1alpha2 +kind: RabbitMQ +metadata: + name: rabbitmq + namespace: demo +spec: + deletionPolicy: Delete + replicas: 3 + storage: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + storageClassName: standard + storageType: Durable + version: 3.12.12 +``` + +```bash +$ kubectl apply -f rabbit.yaml +RabbitMQ.kubedb.com/rabbitmq created +``` + +## Verify authentication +The user can verify whether they are authorized by executing a query directly in the database. To do this, the user needs `username` and `password` in order to connect to the database. Below is an example showing how to retrieve the credentials from the secret. + +````shell +$ kubectl get rm -n demo rabbitmq -ojson | jq .spec.authsecret.name +"rabbitmq-auth" +$ kubectl get secret -n demo rabbitmq-auth -o jsonpath='{.data.username}' | base64 -d +admin⏎ +$ kubectl get secret -n demo rabbitmq-auth -o jsonpath='{.data.password}' | base64 -d +4TC.R7hXc1g;kA)P⏎ +```` +Now, you can exec into the pod `rabbitmq-0` and connect to database using `username` and `password` +```bash +$ kubectl exec -it -n demo rabbitmq-0 -c rabbitmq -- bash +rabbitmq-0:/$ rabbitmqadmin -u admin -p '4TC.R7hXc1g;kA)P' list queues ++---------------+----------+ +| name | messages | ++---------------+----------+ +| kubedb_system | 0 | ++---------------+----------+ +rabbitmq-0:/$ exit +exit +``` + +If you can access the data table and run queries, it means the secrets are working correctly. +## Create RotateAuth RabbitMQOpsRequest + +#### 1. Using operator generated credentials: + +In order to rotate authentication to the RabbitMQ using operator generated, we have to create a `RabbitMQOpsRequest` CR with `RotateAuth` type. Below is the YAML of the `RabbitMQOpsRequest` CR that we are going to create, +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: RabbitMQOpsRequest +metadata: + name: rm-rotate-auth-generated + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: rabbitmq + timeout: 5m + apply: IfReady +``` +Here, + +- `spec.databaseRef.name` specifies that we are performing rotate authentication operation on `rabbitmq` cluster. +- `spec.type` specifies that we are performing `RotateAuth` on RabbitMQ. + +Let's create the `RabbitMQOpsRequest` CR we have shown above, +```shell + $ kubectl apply -f https://github.com/kubedb/docs/raw/{{ .version }}/docs/examples/rabbitmq/rotate-auth/rotate-auth-generated.yaml + RabbitMQopsrequest.ops.kubedb.com/rm-rotate-auth-generated created +``` +Let's wait for `RabbitMQOpsrequest` to be `Successful`. Run the following command to watch `RabbitMQOpsrequest` CR +```shell + $ kubectl get RabbitMQopsrequest -n demo +NAME TYPE STATUS AGE +rm-rotate-auth-generated RotateAuth Successful 3m14s +``` +If we describe the `RabbitMQOpsRequest` we will get an overview of the steps that were followed. +```shell +$ kubectl describe RabbitMQopsrequest -n demo rm-rotate-auth-generated +Name: rm-rotate-auth-generated +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: RabbitMQOpsRequest +Metadata: + Creation Timestamp: 2025-08-15T14:52:14Z + Generation: 1 + Resource Version: 36322 + UID: 547ceec2-492e-4c11-a432-a15e849dbd8f +Spec: + Apply: IfReady + Database Ref: + Name: rabbitmq + Timeout: 5m + Type: RotateAuth +Status: + Conditions: + Last Transition Time: 2025-08-15T14:52:14Z + Message: rabbitmq ops request has started to rotate auth for rmq nodes + Observed Generation: 1 + Reason: RotateAuth + Status: True + Type: RotateAuth + Last Transition Time: 2025-08-15T14:52:22Z + Message: reconcile; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: Reconcile + Last Transition Time: 2025-08-15T14:52:22Z + Message: Successfully generated new credentials + Observed Generation: 1 + Reason: UpdateCredential + Status: True + Type: UpdateCredential + Last Transition Time: 2025-08-15T14:52:29Z + Message: successfully reconciled the rabbitmq with new auth credentials and configuration + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2025-08-15T14:52:34Z + Message: get pod; ConditionStatus:True; PodName:rabbitmq-0 + Observed Generation: 1 + Status: True + Type: GetPod--rabbitmq-0 + Last Transition Time: 2025-08-15T14:52:34Z + Message: evict pod; ConditionStatus:True; PodName:rabbitmq-0 + Observed Generation: 1 + Status: True + Type: EvictPod--rabbitmq-0 + Last Transition Time: 2025-08-15T14:52:39Z + Message: running pod; ConditionStatus:False + Observed Generation: 1 + Status: False + Type: RunningPod + Last Transition Time: 2025-08-15T14:52:44Z + Message: running pod; ConditionStatus:True; PodName:rabbitmq-0 + Observed Generation: 1 + Status: True + Type: RunningPod--rabbitmq-0 + Last Transition Time: 2025-08-15T14:52:49Z + Message: get pod; ConditionStatus:True; PodName:rabbitmq-1 + Observed Generation: 1 + Status: True + Type: GetPod--rabbitmq-1 + Last Transition Time: 2025-08-15T14:52:49Z + Message: evict pod; ConditionStatus:True; PodName:rabbitmq-1 + Observed Generation: 1 + Status: True + Type: EvictPod--rabbitmq-1 + Last Transition Time: 2025-08-15T14:52:59Z + Message: running pod; ConditionStatus:True; PodName:rabbitmq-1 + Observed Generation: 1 + Status: True + Type: RunningPod--rabbitmq-1 + Last Transition Time: 2025-08-15T14:53:04Z + Message: get pod; ConditionStatus:True; PodName:rabbitmq-2 + Observed Generation: 1 + Status: True + Type: GetPod--rabbitmq-2 + Last Transition Time: 2025-08-15T14:53:04Z + Message: evict pod; ConditionStatus:True; PodName:rabbitmq-2 + Observed Generation: 1 + Status: True + Type: EvictPod--rabbitmq-2 + Last Transition Time: 2025-08-15T14:53:14Z + Message: running pod; ConditionStatus:True; PodName:rabbitmq-2 + Observed Generation: 1 + Status: True + Type: RunningPod--rabbitmq-2 + Last Transition Time: 2025-08-15T14:53:19Z + Message: Successfully restarted all nodes + Observed Generation: 1 + Reason: RestartNodes + Status: True + Type: RestartNodes + Last Transition Time: 2025-08-15T14:53:19Z + Message: Successfuly completed reconfigure rmq + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Starting 3m50s KubeDB Ops-manager Operator Start processing for RabbitMQOpsRequest: demo/rm-rotate-auth-generated + Normal Starting 3m50s KubeDB Ops-manager Operator Pausing RabbitMQ databse: demo/rabbitmq + Normal Successful 3m50s KubeDB Ops-manager Operator Successfully paused RabbitMQ database: demo/rabbitmq for RabbitMQOpsRequest: rm-rotate-auth-generated + Warning reconcile; ConditionStatus:True 3m42s KubeDB Ops-manager Operator reconcile; ConditionStatus:True + Warning reconcile; ConditionStatus:True 3m42s KubeDB Ops-manager Operator reconcile; ConditionStatus:True + Warning reconcile; ConditionStatus:True 3m42s KubeDB Ops-manager Operator reconcile; ConditionStatus:True + Warning reconcile; ConditionStatus:True 3m42s KubeDB Ops-manager Operator reconcile; ConditionStatus:True + Normal UpdateCredential 3m42s KubeDB Ops-manager Operator Successfully generated new credentials + Warning reconcile; ConditionStatus:True 3m37s KubeDB Ops-manager Operator reconcile; ConditionStatus:True + Warning reconcile; ConditionStatus:True 3m37s KubeDB Ops-manager Operator reconcile; ConditionStatus:True + Warning reconcile; ConditionStatus:True 3m35s KubeDB Ops-manager Operator reconcile; ConditionStatus:True + Normal UpdatePetSets 3m35s KubeDB Ops-manager Operator successfully reconciled the rabbitmq with new auth credentials and configuration + Warning get pod; ConditionStatus:True; PodName:rabbitmq-0 3m30s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:rabbitmq-0 + Warning evict pod; ConditionStatus:True; PodName:rabbitmq-0 3m30s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:rabbitmq-0 + Warning running pod; ConditionStatus:False 3m25s KubeDB Ops-manager Operator running pod; ConditionStatus:False + Warning running pod; ConditionStatus:True; PodName:rabbitmq-0 3m20s KubeDB Ops-manager Operator running pod; ConditionStatus:True; PodName:rabbitmq-0 + Warning get pod; ConditionStatus:True; PodName:rabbitmq-1 3m15s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:rabbitmq-1 + Warning evict pod; ConditionStatus:True; PodName:rabbitmq-1 3m15s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:rabbitmq-1 + Warning running pod; ConditionStatus:False 3m10s KubeDB Ops-manager Operator running pod; ConditionStatus:False + Warning running pod; ConditionStatus:True; PodName:rabbitmq-1 3m5s KubeDB Ops-manager Operator running pod; ConditionStatus:True; PodName:rabbitmq-1 + Warning get pod; ConditionStatus:True; PodName:rabbitmq-2 3m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:rabbitmq-2 + Warning evict pod; ConditionStatus:True; PodName:rabbitmq-2 3m KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:rabbitmq-2 + Warning running pod; ConditionStatus:False 2m55s KubeDB Ops-manager Operator running pod; ConditionStatus:False + Warning running pod; ConditionStatus:True; PodName:rabbitmq-2 2m50s KubeDB Ops-manager Operator running pod; ConditionStatus:True; PodName:rabbitmq-2 + Normal RestartNodes 2m45s KubeDB Ops-manager Operator Successfully restarted all nodes + +``` +**Verify Auth is rotated** +```shell +$ kubectl get rm -n demo rabbitmq -ojson | jq .spec.authsecret.name +"rabbitmq-auth" +$ kubectl get secret -n demo rabbitmq-auth -o jsonpath='{.data.username}' | base64 -d +admin⏎ +$ kubectl get secret -n demo rabbitmq-auth -o jsonpath='{.data.password}' | base64 -d +tB7;0ATxvhxeau15⏎ +``` +Let's verify if we can connect to the database using the new credentials. + +```shell +$ kubectl exec -it -n demo rabbitmq-0 -c rabbitmq -- bash + +rabbitmq-0:/$ rabbitmqadmin -u admin -p 'tB7;0ATxvhxeau15' list queues ++---------------+----------+ +| name | messages | ++---------------+----------+ +| kubedb_system | 0 | ++---------------+----------+ +rabbitmq-0:/$ + +``` + +Also, there will be two more new keys in the secret that stores the previous credentials. The keys are `username.prev` and `password.prev`. You can find the secret and its data by running the following command: + +```shell +$ kubectl get secret -n demo rabbitmq-auth -o go-template='{{ index .data "username.prev" }}' | base64 -d +admin⏎ +$ kubectl get secret -n demo rabbitmq-auth -o go-template='{{ index .data "password.prev" }}' | base64 -d +4TC.R7hXc1g;kA)P⏎ +``` +Now verify whether the previous credential is workable or not + +```shell +$ kubectl exec -it -n demo rabbitmq-0 -c rabbitmq -- bash + +rabbitmq-0:/$ rabbitmqadmin -u admin -p '4TC.R7hXc1g;kA)P' list queues +*** Access refused: /api/queues?columns=name,messages +``` +The above output shows that the password has been changed successfully. The previous username & password is stored for rollback purpose. +#### 2. Using user created credentials + +At first, we need to create a secret with kubernetes.io/basic-auth type using custom username and password. Below is the command to create a secret with kubernetes.io/basic-auth type, + +```shell +$ kubectl create secret generic rm-auth-user -n demo \ + --type=kubernetes.io/basic-auth \ + --from-literal=username=rabbit \ + --from-literal=password=RabbitMQ2 +secret/rm-auth-user created + +``` +Now create a `RabbitMQOpsRequest` with `RotateAuth` type. Below is the YAML of the `RabbitMQOpsRequest` that we are going to create, + +```shell +apiVersion: ops.kubedb.com/v1alpha1 +kind: RabbitMQOpsRequest +metadata: + name: rmops-rotate-auth-user + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: rabbitmq + authentication: + secretRef: + name: rm-auth-user + timeout: 5m + apply: IfReady +``` +Here, + +- `spec.databaseRef.name` specifies that we are performing rotate authentication operation on `rabbitmq`cluster. +- `spec.type` specifies that we are performing `RotateAuth` on RabbitMQ. +- `spec.authentication.secretRef.name` specifies that we used `rm-auth-user` for database authentication. + + +Let's create the `RabbitMQOpsRequest` CR we have shown above, + +```shell +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{ .version }}/docs/examples/rabbitmq/rotate-auth/rotate-auth-user.yaml +RabbitMQopsrequest.ops.kubedb.com/rmops-rotate-auth-user created +``` +Let’s wait for `RabbitMQOpsRequest` to be Successful. Run the following command to watch `RabbitMQOpsRequest` CR: + +```shell +$ kubectl get RabbitMQopsrequest -n demo +NAME TYPE STATUS AGE +rm-rotate-auth-generated RotateAuth Successful 28m +rmops-rotate-auth-user RotateAuth Successful 80s +``` +We can see from the above output that the `RabbitMQOpsRequest` has succeeded. If we describe the `RabbitMQOpsRequest` we will get an overview of the steps that were followed. +```shell +$ kubectl describe RabbitMQopsrequest -n demo rmops-rotate-auth-user +Name: rmops-rotate-auth-user +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: RabbitMQOpsRequest +Metadata: + Creation Timestamp: 2025-08-15T15:19:14Z + Generation: 1 + Resource Version: 37048 + UID: 8bcf2459-3bc5-41f5-9ca4-7ccebdfd38bc +Spec: + Apply: IfReady + Authentication: + secret Ref: + Name: rm-auth-user + Database Ref: + Name: rabbitmq + Timeout: 5m + Type: RotateAuth +Status: + Conditions: + Last Transition Time: 2025-08-15T15:19:24Z + Message: rabbitmq ops request has started to rotate auth for rmq nodes + Observed Generation: 1 + Reason: RotateAuth + Status: True + Type: RotateAuth + Last Transition Time: 2025-08-15T15:19:29Z + Message: reconcile; ConditionStatus:True + Observed Generation: 1 + Status: True + Type: Reconcile + Last Transition Time: 2025-08-15T15:19:29Z + Message: Successfully referenced the user provided authsecret + Observed Generation: 1 + Reason: UpdateCredential + Status: True + Type: UpdateCredential + Last Transition Time: 2025-08-15T15:19:37Z + Message: successfully reconciled the rabbitmq with new auth credentials and configuration + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2025-08-15T15:19:42Z + Message: get pod; ConditionStatus:True; PodName:rabbitmq-0 + Observed Generation: 1 + Status: True + Type: GetPod--rabbitmq-0 + Last Transition Time: 2025-08-15T15:19:42Z + Message: evict pod; ConditionStatus:True; PodName:rabbitmq-0 + Observed Generation: 1 + Status: True + Type: EvictPod--rabbitmq-0 + Last Transition Time: 2025-08-15T15:19:47Z + Message: running pod; ConditionStatus:False + Observed Generation: 1 + Status: False + Type: RunningPod + Last Transition Time: 2025-08-15T15:19:52Z + Message: running pod; ConditionStatus:True; PodName:rabbitmq-0 + Observed Generation: 1 + Status: True + Type: RunningPod--rabbitmq-0 + Last Transition Time: 2025-08-15T15:19:57Z + Message: get pod; ConditionStatus:True; PodName:rabbitmq-1 + Observed Generation: 1 + Status: True + Type: GetPod--rabbitmq-1 + Last Transition Time: 2025-08-15T15:19:57Z + Message: evict pod; ConditionStatus:True; PodName:rabbitmq-1 + Observed Generation: 1 + Status: True + Type: EvictPod--rabbitmq-1 + Last Transition Time: 2025-08-15T15:20:07Z + Message: running pod; ConditionStatus:True; PodName:rabbitmq-1 + Observed Generation: 1 + Status: True + Type: RunningPod--rabbitmq-1 + Last Transition Time: 2025-08-15T15:20:12Z + Message: get pod; ConditionStatus:True; PodName:rabbitmq-2 + Observed Generation: 1 + Status: True + Type: GetPod--rabbitmq-2 + Last Transition Time: 2025-08-15T15:20:12Z + Message: evict pod; ConditionStatus:True; PodName:rabbitmq-2 + Observed Generation: 1 + Status: True + Type: EvictPod--rabbitmq-2 + Last Transition Time: 2025-08-15T15:20:22Z + Message: running pod; ConditionStatus:True; PodName:rabbitmq-2 + Observed Generation: 1 + Status: True + Type: RunningPod--rabbitmq-2 + Last Transition Time: 2025-08-15T15:20:27Z + Message: Successfully restarted all nodes + Observed Generation: 1 + Reason: RestartNodes + Status: True + Type: RestartNodes + Last Transition Time: 2025-08-15T15:20:27Z + Message: Successfuly completed reconfigure rmq + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Starting 105s KubeDB Ops-manager Operator Start processing for RabbitMQOpsRequest: demo/rmops-rotate-auth-user + Warning reconcile; ConditionStatus:True 100s KubeDB Ops-manager Operator reconcile; ConditionStatus:True + Warning reconcile; ConditionStatus:True 100s KubeDB Ops-manager Operator reconcile; ConditionStatus:True + Warning reconcile; ConditionStatus:True 100s KubeDB Ops-manager Operator reconcile; ConditionStatus:True + Warning reconcile; ConditionStatus:True 100s KubeDB Ops-manager Operator reconcile; ConditionStatus:True + Warning reconcile; ConditionStatus:True 100s KubeDB Ops-manager Operator reconcile; ConditionStatus:True + Warning reconcile; ConditionStatus:True 100s KubeDB Ops-manager Operator reconcile; ConditionStatus:True + Normal UpdateCredential 100s KubeDB Ops-manager Operator Successfully referenced the user provided authsecret + Warning reconcile; ConditionStatus:True 95s KubeDB Ops-manager Operator reconcile; ConditionStatus:True + Warning reconcile; ConditionStatus:True 95s KubeDB Ops-manager Operator reconcile; ConditionStatus:True + Warning reconcile; ConditionStatus:True 92s KubeDB Ops-manager Operator reconcile; ConditionStatus:True + Normal UpdatePetSets 92s KubeDB Ops-manager Operator successfully reconciled the rabbitmq with new auth credentials and configuration + Warning get pod; ConditionStatus:True; PodName:rabbitmq-0 87s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:rabbitmq-0 + Warning evict pod; ConditionStatus:True; PodName:rabbitmq-0 87s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:rabbitmq-0 + Warning running pod; ConditionStatus:False 82s KubeDB Ops-manager Operator running pod; ConditionStatus:False + Warning running pod; ConditionStatus:True; PodName:rabbitmq-0 77s KubeDB Ops-manager Operator running pod; ConditionStatus:True; PodName:rabbitmq-0 + Warning get pod; ConditionStatus:True; PodName:rabbitmq-1 72s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:rabbitmq-1 + Warning evict pod; ConditionStatus:True; PodName:rabbitmq-1 72s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:rabbitmq-1 + Warning running pod; ConditionStatus:False 67s KubeDB Ops-manager Operator running pod; ConditionStatus:False + Warning running pod; ConditionStatus:True; PodName:rabbitmq-1 62s KubeDB Ops-manager Operator running pod; ConditionStatus:True; PodName:rabbitmq-1 + Warning get pod; ConditionStatus:True; PodName:rabbitmq-2 57s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:rabbitmq-2 + Warning evict pod; ConditionStatus:True; PodName:rabbitmq-2 57s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:rabbitmq-2 + Warning running pod; ConditionStatus:False 52s KubeDB Ops-manager Operator running pod; ConditionStatus:False + Warning running pod; ConditionStatus:True; PodName:rabbitmq-2 47s KubeDB Ops-manager Operator running pod; ConditionStatus:True; PodName:rabbitmq-2 + Normal RestartNodes 42s KubeDB Ops-manager Operator Successfully restarted all nodes + +``` +**Verify auth is rotate** +```shell +$ kubectl get rm -n demo rabbitmq -ojson | jq .spec.authsecret.name +"rm-auth-user" +$ kubectl get secret -n demo rm-auth-user -o=jsonpath='{.data.username}' | base64 -d +rabbit⏎ +$ kubectl get secret -n demo rm-auth-user -o=jsonpath='{.data.password}' | base64 -d +RabbitMQ2⏎ +``` + +Let's verify if we can connect to the database using the new credentials. +```shell +$ kubectl exec -it -n demo rabbitmq-0 -c rabbitmq -- bash + +rabbitmq-0:/$ rabbitmqadmin -u rabbit -p 'RabbitMQ2' list queues ++---------------+----------+ +| name | messages | ++---------------+----------+ +| kubedb_system | 0 | ++---------------+----------+ + +``` +Also, there will be two more new keys in the secret that stores the previous credentials. The keys are `username.prev` and `password.prev`. You can find the secret and its data by running the following command: +```shell +$ kubectl get secret -n demo rm-auth-user -o go-template='{{ index .data "password.prev" }}' | base64 -d +tB7;0ATxvhxeau15⏎ +$ kubectl get secret -n demo rm-auth-user -o go-template='{{ index .data "username.prev" }}' | base64 -d +admin⏎ +``` +Let's confirm that the previous credentials no longer work. +```shell +$ kubectl exec -it -n demo rabbitmq-0 -c rabbitmq -- bash + +rabbitmq-0:/$ rabbitmqadmin -u admin -p 'tB7;0ATxvhxeau15' list queues +*** Access refused: /api/queues?columns=name,messages + +``` +The above output shows that the credential has been changed successfully. The previous username & password is stored in the secret for rollback purpose. + +## Cleaning up + +To clean up the Kubernetes resources you can delete the CRD or namespace. +Or, you can delete one by one resource by their name by this tutorial, run: + +```shell +$ kubectl delete RabbitMQopsrequest rm-rotate-auth-generated rmops-rotate-auth-user -n demo +RabbitMQopsrequest.ops.kubedb.com "rm-rotate-auth-generated" "rmops-rotate-auth-user" deleted +$ kubectl delete secret -n rm-auth-user +secret "rm-auth-user" deleted +$ kubectl delete secret -n demo rabbitmq-auth +secret "rabbitmq-auth " deleted + +``` + +## Next Steps + + +- Detail concepts of [RabbitMQ object](/docs/guides/rabbitmq/concepts/rabbitmq.md). +- Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md). diff --git a/docs/guides/redis/rotateauth/_index.md b/docs/guides/redis/rotateauth/_index.md new file mode 100644 index 0000000000..59a11c83d9 --- /dev/null +++ b/docs/guides/redis/rotateauth/_index.md @@ -0,0 +1,10 @@ +--- +title: Redis Rotate Authentication +menu: + docs_{{ .version }}: + identifier: rd-rotate-auth-redis + name: Rotate Authentication + parent: rd-redis-guides + weight: 48 +menu_name: docs_{{ .version }} +--- diff --git a/docs/guides/redis/rotateauth/rotateauth.md b/docs/guides/redis/rotateauth/rotateauth.md new file mode 100644 index 0000000000..b435d88be2 --- /dev/null +++ b/docs/guides/redis/rotateauth/rotateauth.md @@ -0,0 +1,415 @@ +--- +title: Redis Rotate Authentication +menu: + docs_{{ .version }}: + identifier: rd-rotate-auth + name: Guide + parent: rd-rotate-auth-redis + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- + +# Rotate Authentication of Redis + +**Rotate Authentication** is a feature of the KubeDB Ops-Manager that allows you to rotate a `Redis` user's authentication credentials using a `RedisOpsRequest`. There are two ways to perform this rotation. + +1. **Operator Generated:** The KubeDB operator automatically generates a random credential, updates the existing secret with the new credential The KubeDB operator automatically generates a random credential and updates the existing secret with the new credential.. +2. **User Defined:** The user can create their own credentials by defining a Secret of type `kubernetes.io/basic-auth` containing the desired `username` and `password`, and then reference this Secret in the `RedisOpsRequest`. + +## Before You Begin + +- At first, you need to have a Kubernetes cluster, and the `kubectl` command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using [kind](https://kind.sigs.k8s.io/docs/user/quick-start/). + +- Now, install KubeDB cli on your workstation and KubeDB operator in your cluster following the steps [here](/docs/setup/README.md). Make sure install with helm command including `--set global.featureGates.Redis=true` to ensure Redis CRD installation. + +- [StorageClass](https://kubernetes.io/docs/concepts/storage/storage-classes/) is required to run KubeDB. Check the available StorageClass in cluster. + + ```bash + $ kubectl get storageclasses + NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE + standard (default) rancher.io/local-path Delete WaitForFirstConsumer false 4h + ``` + +- To keep things isolated, this tutorial uses a separate namespace called `demo` throughout this tutorial. Run the following command to prepare your cluster for this tutorial: + + ```bash + $ kubectl create namespace demo + namespace/demo created + + $ kubectl get namespaces + NAME STATUS AGE + demo Active 10s + ``` + +> Note: The yaml files used in this tutorial are stored in [docs/examples](https://github.com/kubedb/docs/tree/{{< param "info.version" >}}/docs/examples) folder in GitHub repository [kubedb/docs](https://github.com/kubedb/docs). + +## Create a Redisdatabase + +KubeDB implements a `Redis` CRD to define the specification of a Redis server. Below is the `Redis` object created in this tutorial. + +`Note`: If your `KubeDB version` is less or equal to `v2024.6.4`, You have to use `v1alpha2` apiVersion. + +```yaml +apiVersion: kubedb.com/v1 +kind: Redis +metadata: + name: redis-quickstart + namespace: demo +spec: + version: 6.2.14 + storageType: Durable + storage: + storageClassName: "standard" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + deletionPolicy: DoNotTerminate +``` + +```bash +$ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/redis/quickstart/demo-v1.yaml +redis.kubedb.com/redis-quickstart created +``` + +Now, wait until redis-quickstart has status Ready. i.e, + +```shell +$ kubectl get rd -n demo -w +NAME VERSION STATUS AGE +redis-quickstart 6.2.14 Ready 74m +``` +## Verify authentication +The user can verify whether they are authorized by executing a query directly in the database. To do this, the user needs `username` and `password` in order to connect to the database using the `kubectl exec` command. Below is an example showing how to retrieve the credentials from the Secret. + +````shell +$ kubectl get rd -n demo redis-quickstart -ojson | jq .spec.authSecret.name +"redis-quickstart-auth" +$ kubectl get secret -n demo redis-quickstart-auth -o jsonpath='{.data.username}' | base64 -d +default⏎ +$ kubectl get secret -n demo redis-quickstart-auth -o jsonpath='{.data.password}' | base64 -d +nAiZo)pGW1f!se*2⏎ +```` + +## Create RotateAuth RedisOpsRequest + +#### 1. Using operator generated credentials: + +In order to rotate authentication to the Redis using operator generated, we have to create a `RedisOpsRequest` CRO with `RotateAuth` type. Below is the YAML of the `RedisOpsRequest` CRO that we are going to create, +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: RedisOpsRequest +metadata: + name: rdops-rotate-auth-generated + namespace: pool +spec: + type: RotateAuth + databaseRef: + name: redis-quickstart + timeout: 5m + apply: IfReady +``` +Here, + +- `spec.databaseRef.name` specifies that we are performing rotate authentication operation on `redis-quickstart` cluster. +- `spec.type` specifies that we are performing `RotateAuth` on Redis. + +Let's create the `RedisOpsRequest` CR we have shown above, +```shell +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{ .version }}/docs/examples/redis/rotate-auth/Redis-rotate-auth-generated.yaml +redisopsrequest.ops.kubedb.com/rdops-rotate-auth-generated created +``` +Let's wait for `RedisOpsrequest` to be `Successful`. Run the following command to watch `RedisOpsrequest` CRO +```shell + $ kubectl get rdops -n demo -w + NAME TYPE STATUS AGE +rdops-rotate-auth-generated RotateAuth Successful 45s +``` +If we describe the `RedisOpsRequest` we will get an overview of the steps that were followed. +```shell +$ kubectl describe Redisopsrequest -n demo rdops-rotate-auth-generated +Name: rdops-rotate-auth-generated +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: RedisOpsRequest +Metadata: + Creation Timestamp: 2025-07-18T11:35:14Z + Generation: 1 + Resource Version: 135839 + UID: 1c5e54b0-0f7d-4942-b569-61bbdb4c3f01 +Spec: + Apply: IfReady + Database Ref: + Name: redis-quickstart + Timeout: 5m + Type: RotateAuth +Status: + Conditions: + Last Transition Time: 2025-07-18T11:35:14Z + Message: Redis ops request has started to rotate auth for Redis + Observed Generation: 1 + Reason: RotateAuth + Status: True + Type: RotateAuth + Last Transition Time: 2025-07-18T11:35:17Z + Message: Successfully paused database + Observed Generation: 1 + Reason: DatabasePauseSucceeded + Status: True + Type: DatabasePauseSucceeded + Last Transition Time: 2025-07-18T11:35:17Z + Message: Successfully Generated New Auth Secret + Observed Generation: 1 + Reason: UpdateCredential + Status: True + Type: UpdateCredential + Last Transition Time: 2025-07-18T11:35:17Z + Message: Successfully patched config secret + Observed Generation: 1 + Reason: patchedSecret + Status: True + Type: patchedSecret + Last Transition Time: 2025-07-18T11:35:19Z + Message: Successfully updated petsets + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2025-07-18T11:35:24Z + Message: evict pod; ConditionStatus:True; PodName:redis-quickstart-0 + Observed Generation: 1 + Status: True + Type: EvictPod--redis-quickstart-0 + Last Transition Time: 2025-07-18T11:35:59Z + Message: is pod ready; ConditionStatus:True; PodName:redis-quickstart-0 + Observed Generation: 1 + Status: True + Type: IsPodReady--redis-quickstart-0 + Last Transition Time: 2025-07-18T11:35:59Z + Message: Successfully Restarted Pods + Observed Generation: 1 + Reason: RestartPods + Status: True + Type: RestartPods + Last Transition Time: 2025-07-18T11:35:59Z + Message: Successfully Rotated Auth + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal PauseDatabase 4m12s KubeDB Ops-manager Operator Pausing Redis demo/redis-quickstart + Warning evict pod; ConditionStatus:True; PodName:redis-quickstart-0 4m2s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:redis-quickstart-0 + Warning is pod ready; ConditionStatus:False; PodName:redis-quickstart-0 4m2s KubeDB Ops-manager Operator is pod ready; ConditionStatus:False; PodName:redis-quickstart-0 + Warning is pod ready; ConditionStatus:True; PodName:redis-quickstart-0 3m27s KubeDB Ops-manager Operator is pod ready; ConditionStatus:True; PodName:redis-quickstart-0 + Normal RestartPods 3m27s KubeDB Ops-manager Operator Successfully Restarted Pods + Normal ResumeDatabase 3m27s KubeDB Ops-manager Operator Resuming Redis demo/redis-quickstart + Normal ResumeDatabase 3m27s KubeDB Ops-manager Operator Successfully resumed Redis demo/redis-quickstart + Normal Successful 3m27s KubeDB Ops-manager Operator Succesfully Rotated Auth for Redis + +``` +**Verify Auth is rotated** +```shell +$ kubectl get rd -n demo redis-quickstart -ojson | jq .spec.authSecret.name +"redis-quickstart-auth" +$ kubectl get secret -n demo redis-quickstart-auth -o jsonpath='{.data.username}' | base64 -d +default⏎ +$ kubectl get secret -n demo redis-quickstart-auth -o jsonpath='{.data.password}' | base64 -d +jGPx0DDKaOb6hWAb⏎ +``` +Also, there will be two more new keys in the secret that stores the previous credentials. The keys are `username.prev` and `password.prev`. You can find the secret and its data by running the following command: + +```shell +$ kubectl get secret -n demo redis-quickstart-auth -o go-template='{{ index .data "username.prev" }}' | base64 -d +default⏎ +$ kubectl get secret -n demo redis-quickstart-auth -o go-template='{{ index .data "password.prev" }}' | base64 -d +nAiZo)pGW1f!se*2⏎ +``` +The above output shows that the password has been changed successfully. The previous username & password is stored for rollback purpose. +#### 2. Using user created credentials + +At first, we need to create a secret with kubernetes.io/basic-auth type using custom username and password. Below is the command to create a secret with kubernetes.io/basic-auth type, + +```shell +$ kubectl create secret generic redis-quickstart-user-auth -n demo \ + --type=kubernetes.io/basic-auth \ + --from-literal=username=admin \ + --from-literal=password=Redis-secret + secret/redis-quickstart-user-auth created +``` +Now create a `RedisOpsRequest` with `RotateAuth` type. Below is the YAML of the `RedisOpsRequest` that we are going to create, + +```shell +apiVersion: ops.kubedb.com/v1alpha1 +kind: RedisOpsRequest +metadata: + name: rdops-rotate-auth-user + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: redis-quickstart + authentication: + secretRef: + name: redis-quickstart-user-auth + timeout: 5m + apply: IfReady +``` +Here, + +- `spec.databaseRef.name` specifies that we are performing rotate authentication operation on `redis-quickstart`cluster. +- `spec.type` specifies that we are performing `RotateAuth` on Redis. +- `spec.authentication.secretRef.name` specifies that we are using `redis-quickstart-user-auth` as `spec.authSecret.name` for authentication. + +Let's create the `RedisOpsRequest` CR we have shown above, + +```shell +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{ .version }}/docs/examples/Redis/rotate-auth/rotate-auth-user.yaml +redisopsrequest.ops.kubedb.com/rdops-rotate-auth-user created +``` +Let’s wait for `RedisOpsRequest` to be Successful. Run the following command to watch `RedisOpsRequest` CRO: + +```shell +$ kubectl get rdops -n demo -w +NAME TYPE STATUS AGE +rdops-rotate-auth-generated RotateAuth Successful 6m39s +rdops-rotate-auth-user RotateAuth Successful 46s +``` +We can see from the above output that the `RedisOpsRequest` has succeeded. If we describe the `RedisOpsRequest` we will get an overview of the steps that were followed. +```shell +$ kubectl describe Redisopsrequest -n demo rdops-rotate-auth-user +Name: rdops-rotate-auth-user +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: RedisOpsRequest +Metadata: + Creation Timestamp: 2025-07-18T11:41:07Z + Generation: 1 + Resource Version: 136344 + UID: aa4f7fa3-4047-452f-ad1b-d39ef738c0f2 +Spec: + Apply: IfReady + Authentication: + Secret Ref: + Name: redis-quickstart-user-auth + Database Ref: + Name: redis-quickstart + Timeout: 5m + Type: RotateAuth +Status: + Conditions: + Last Transition Time: 2025-07-18T11:41:07Z + Message: Redis ops request has started to rotate auth for Redis + Observed Generation: 1 + Reason: RotateAuth + Status: True + Type: RotateAuth + Last Transition Time: 2025-07-18T11:41:10Z + Message: Successfully paused database + Observed Generation: 1 + Reason: DatabasePauseSucceeded + Status: True + Type: DatabasePauseSucceeded + Last Transition Time: 2025-07-18T11:41:10Z + Message: Successfully referenced the user provided authSecret + Observed Generation: 1 + Reason: UpdateCredential + Status: True + Type: UpdateCredential + Last Transition Time: 2025-07-18T11:41:10Z + Message: Successfully patched config secret + Observed Generation: 1 + Reason: patchedSecret + Status: True + Type: patchedSecret + Last Transition Time: 2025-07-18T11:41:12Z + Message: Successfully updated petsets + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2025-07-18T11:41:17Z + Message: evict pod; ConditionStatus:True; PodName:redis-quickstart-0 + Observed Generation: 1 + Status: True + Type: EvictPod--redis-quickstart-0 + Last Transition Time: 2025-07-18T11:41:52Z + Message: is pod ready; ConditionStatus:True; PodName:redis-quickstart-0 + Observed Generation: 1 + Status: True + Type: IsPodReady--redis-quickstart-0 + Last Transition Time: 2025-07-18T11:41:52Z + Message: Successfully Restarted Pods + Observed Generation: 1 + Reason: RestartPods + Status: True + Type: RestartPods + Last Transition Time: 2025-07-18T11:41:53Z + Message: Successfully Rotated Auth + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal PauseDatabase 115s KubeDB Ops-manager Operator Pausing Redis demo/redis-quickstart + Warning evict pod; ConditionStatus:True; PodName:redis-quickstart-0 105s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:redis-quickstart-0 + Warning is pod ready; ConditionStatus:False; PodName:redis-quickstart-0 105s KubeDB Ops-manager Operator is pod ready; ConditionStatus:False; PodName:redis-quickstart-0 + Warning is pod ready; ConditionStatus:True; PodName:redis-quickstart-0 70s KubeDB Ops-manager Operator is pod ready; ConditionStatus:True; PodName:redis-quickstart-0 + Normal RestartPods 70s KubeDB Ops-manager Operator Successfully Restarted Pods + Normal ResumeDatabase 69s KubeDB Ops-manager Operator Resuming Redis demo/redis-quickstart + Normal ResumeDatabase 69s KubeDB Ops-manager Operator Successfully resumed Redis demo/redis-quickstart + Normal Successful 69s KubeDB Ops-manager Operator Succesfully Rotated Auth for Redis + +``` +**Verify auth is rotate** +```shell +$ kubectl get rd -n demo redis-quickstart -ojson | jq .spec.authSecret.name +"redis-quickstart-user-auth" +$kubectl get secret -n demo redis-quickstart-user-auth -o=jsonpath='{.data.username}' | base64 -d +admin⏎ +$ kubectl get secret -n demo redis-quickstart-user-auth -o=jsonpath='{.data.password}' | base64 -d +Redis-secret⏎ +``` +Also, there will be two more new keys in the secret that stores the previous credentials. The keys are `username.prev` and `password.prev`. You can find the secret and its data by running the following command: +```shell +$ kubectl get secret -n demo redis-quickstart-user-auth -o go-template='{{ index .data "username.prev" }}' | base64 -d +default⏎ +$ kubectl get secret -n demo redis-quickstart-user-auth -o go-template='{{ index .data "password.prev" }}' | base64 -d +jGPx0DDKaOb6hWAb⏎ +``` + +The above output shows that the password has been changed successfully. The previous username & password is stored in the secret for rollback purpose. + +## Cleaning up + +To clean up the Kubernetes resources you can delete the CRD or namespace. +Or, you can delete one by one resource by their name by this tutorial, run: + +```shell +$ kubectl delete Redisopsrequest rdops-rotate-auth-generated rdops-rotate-auth-user -n demo +Redisopsrequest.ops.kubedb.com "rdops-rotate-auth-generated" "rdops-rotate-auth-user" deleted +$ kubectl delete secret -n demo redis-quickstart-user-auth +secret "redis-quickstart-user-auth" deleted +$ kubectl delete secret -n demo redis-quickstart-auth +secret "redis-quickstart-auth" deleted +``` + + +## Next Steps + +- Learn how to use KubeDB to run a Redis server [here](/docs/guides/redis/README.md). +- Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md). \ No newline at end of file diff --git a/docs/guides/singlestore/configuration/podtemplating/index.md b/docs/guides/singlestore/configuration/podtemplating/index.md index 8142f31311..483875e5a3 100644 --- a/docs/guides/singlestore/configuration/podtemplating/index.md +++ b/docs/guides/singlestore/configuration/podtemplating/index.md @@ -600,7 +600,7 @@ Containers: Mounts: /scripts from init-scripts (rw) /var/lib/memsql from data (rw) - /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-htm2z (ro) + /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-htm2z (rotate-auth) Conditions: Type Status PodReadyToStartContainers True diff --git a/docs/guides/solr/configuration/custom-pod-template.md b/docs/guides/solr/configuration/custom-pod-template.md index fdbd1f7335..45ca09801c 100644 --- a/docs/guides/solr/configuration/custom-pod-template.md +++ b/docs/guides/solr/configuration/custom-pod-template.md @@ -514,7 +514,7 @@ Init Containers: SOLR_ZK_CREDS_AND_ACLS: -DzkACLProvider=org.apache.solr.common.cloud.DigestZkACLProvider -DzkCredentialsInjector=org.apache.solr.common.cloud.VMParamsZkCredentialsInjector -DzkCredentialsProvider=org.apache.solr.common.cloud.DigestZkCredentialsProvider -DzkDigestPassword=nwbnmVwBoJhW)eft -DzkDigestReadonlyPassword=7PxFSc)z~DWLL)Tt -DzkDigestReadonlyUsername=zk-digest-readonly -DzkDigestUsername=zk-digest Mounts: /temp-config from default-config (rw) - /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-n9nxh (ro) + /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-n9nxh (rotate-auth) /var/security from auth-config (rw) /var/solr from slconfig (rw) Containers: @@ -556,7 +556,7 @@ Containers: ZK_CREDS_AND_ACLS: -DzkACLProvider=org.apache.solr.common.cloud.DigestZkACLProvider -DzkCredentialsInjector=org.apache.solr.common.cloud.VMParamsZkCredentialsInjector -DzkCredentialsProvider=org.apache.solr.common.cloud.DigestZkCredentialsProvider -DzkDigestPassword=nwbnmVwBoJhW)eft -DzkDigestReadonlyPassword=7PxFSc)z~DWLL)Tt -DzkDigestReadonlyUsername=zk-digest-readonly -DzkDigestUsername=zk-digest SOLR_ZK_CREDS_AND_ACLS: -DzkACLProvider=org.apache.solr.common.cloud.DigestZkACLProvider -DzkCredentialsInjector=org.apache.solr.common.cloud.VMParamsZkCredentialsInjector -DzkCredentialsProvider=org.apache.solr.common.cloud.DigestZkCredentialsProvider -DzkDigestPassword=nwbnmVwBoJhW)eft -DzkDigestReadonlyPassword=7PxFSc)z~DWLL)Tt -DzkDigestReadonlyUsername=zk-digest-readonly -DzkDigestUsername=zk-digest Mounts: - /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-n9nxh (ro) + /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-n9nxh (rotate-auth) /var/solr from slconfig (rw) /var/solr/data from solr-without-toleration-data (rw) Conditions: diff --git a/docs/guides/solr/rotateauth/_index.md b/docs/guides/solr/rotateauth/_index.md new file mode 100644 index 0000000000..b0b415b4b5 --- /dev/null +++ b/docs/guides/solr/rotateauth/_index.md @@ -0,0 +1,10 @@ +--- +title: Solr Rotate Authentication +menu: + docs_{{ .version }}: + identifier: sl-rotate-auth + name: Rotate Authentication + parent: sl-solr-guides + weight: 34 +menu_name: docs_{{ .version }} +--- \ No newline at end of file diff --git a/docs/guides/solr/rotateauth/rotateauth.md b/docs/guides/solr/rotateauth/rotateauth.md new file mode 100644 index 0000000000..669abdee3b --- /dev/null +++ b/docs/guides/solr/rotateauth/rotateauth.md @@ -0,0 +1,372 @@ +--- +title: Rotate Authentication Guide +menu: + docs_{{ .version }}: + identifier: sl-rotate-auth-details + name: Guide + parent: sl-rotate-auth + weight: 10 +menu_name: docs_{{ .version }} +section_menu_id: guides +--- +# Rotate Authentication of Solr + +**Rotate Authentication** is a feature of the KubeDB Ops-Manager that allows you to rotate a `Solr` user's authentication credentials using a `SolrOpsRequest`. There are two ways to perform this rotation. + +1. **Operator Generated:** The KubeDB operator automatically generates a random credential, updates the existing secret with the new credential The KubeDB operator automatically generates a random credential and updates the existing secret with the new credential.. +2. **User Defined:** The user can create their own credentials by defining a secret of type `kubernetes.io/basic-auth` containing the desired `username` and `password` and then reference this secret in the `SolrOpsRequest`. + + +> Note: YAML files used in this tutorial are stored in [docs/guides/solr/quickstart/overview/yamls](https://github.com/kubedb/docs/tree/{{< param "info.version" >}}/docs/guides/solr/quickstart/overview/yamls) folder in GitHub repository [kubedb/docs](https://github.com/kubedb/docs). + +> This tutorial demonstrates how to rotate authentication credentials for Solr managed by KubeDB. Before you begin, ensure that the Solr CRD is installed and running. If not, follow [this guide](/docs/guides/solr/quickstart/overview/index.md) to set it up. + +## Verify authentication +The user can verify whether they are authorized by executing a query directly in the database. To do this, the user needs `username` and `password` in order to connect to the database using the `kubectl exec` command. Below is an example showing how to retrieve the credentials from the secret. + +````shell +$ kubectl get solr -n demo solr-combined -ojson | jq .spec.authsecret.name +"solr-combined-auth" +$ kubectl get secret -n demo solr-combined-auth -o jsonpath='{.data.username}' | base64 -d +admin⏎ +$ kubectl get secret -n demo solr-combined-auth -o jsonpath='{.data.password}' | base64 -d +QtnsJluRRjaaWWec⏎ +```` + +## Create RotateAuth SolrOpsRequest + +#### 1. Using operator generated credentials: + +In order to rotate authentication to the Solr using operator generated, we have to create a `SolrOpsRequest` CRO with `RotateAuth` type. Below is the YAML of the `SolrOpsRequest` CRO that we are going to create, +```yaml +apiVersion: ops.kubedb.com/v1alpha1 +kind: SolrOpsRequest +metadata: + name: solrops-rotate-auth-generated + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: solr-combined + timeout: 5m + apply: IfReady +``` +Here, + +- `spec.databaseRef.name` specifies that we are performing rotate authentication operation on `solr-combined` cluster. +- `spec.type` specifies that we are performing `RotateAuth` on Solr. + +Let's create the `SolrOpsRequest` CR we have shown above, +```shell + $ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/solr/rotate-auth/rotate-auth.yaml +solropsrequest.ops.kubedb.com/solrops-rotate-auth-generated created +``` +Let's wait for `SolrOpsrequest` to be `Successful`. Run the following command to watch `SolrOpsrequest` CRO +```shell + $ kubectl get Solropsrequest -n demo + NAME TYPE STATUS AGE +solrops-rotate-auth-generated RotateAuth Successful 2m3s +``` +If we describe the `SolrOpsRequest` we will get an overview of the steps that were followed. +```shell +$ kubectl describe Solropsrequest -n demo solrops-rotate-auth-generated +Name: solrops-rotate-auth-generated +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: SolrOpsRequest +Metadata: + Creation Timestamp: 2025-07-21T05:45:10Z + Generation: 1 + Resource Version: 151277 + UID: eb1695d2-2354-4f12-9dc2-cf14f55031e9 +Spec: + Apply: IfReady + Database Ref: + Name: solr-combined + Timeout: 5m + Type: RotateAuth +Status: + Conditions: + Last Transition Time: 2025-07-21T05:45:10Z + Message: Solr ops-request has started to rotate auth for solr nodes + Observed Generation: 1 + Reason: RotateAuth + Status: True + Type: RotateAuth + Last Transition Time: 2025-07-21T05:45:13Z + Message: Successfully generated new credentials + Observed Generation: 1 + Reason: UpdateCredential + Status: True + Type: UpdateCredential + Last Transition Time: 2025-07-21T05:45:20Z + Message: successfully reconciled the Solr with updated version + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2025-07-21T05:47:13Z + Message: Successfully restarted all nodes + Observed Generation: 1 + Reason: RestartNodes + Status: True + Type: RestartNodes + Last Transition Time: 2025-07-21T05:45:25Z + Message: get pod; ConditionStatus:True; PodName:solr-combined-0 + Observed Generation: 1 + Status: True + Type: GetPod--solr-combined-0 + Last Transition Time: 2025-07-21T05:45:25Z + Message: evict pod; ConditionStatus:True; PodName:solr-combined-0 + Observed Generation: 1 + Status: True + Type: EvictPod--solr-combined-0 + Last Transition Time: 2025-07-21T05:45:30Z + Message: running pod; ConditionStatus:False + Observed Generation: 1 + Status: False + Type: RunningPod + Last Transition Time: 2025-07-21T05:46:10Z + Message: get pod; ConditionStatus:True; PodName:solr-combined-1 + Observed Generation: 1 + Status: True + Type: GetPod--solr-combined-1 + Last Transition Time: 2025-07-21T05:46:10Z + Message: evict pod; ConditionStatus:True; PodName:solr-combined-1 + Observed Generation: 1 + Status: True + Type: EvictPod--solr-combined-1 + Last Transition Time: 2025-07-21T05:47:13Z + Message: Successfully completed reconfigure solr + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Starting 7m23s KubeDB Ops-manager Operator Start processing for SolrOpsRequest: demo/solrops-rotate-auth-generated + Normal Starting 7m23s KubeDB Ops-manager Operator Pausing Solr databse: demo/solr-combined + Normal Successful 7m23s KubeDB Ops-manager Operator Successfully paused Solr database: demo/solr-combined for SolrOpsRequest: solrops-rotate-auth-generated + Normal UpdatePetSets 7m13s KubeDB Ops-manager Operator successfully reconciled the Solr with updated version + Warning get pod; ConditionStatus:True; PodName:solr-combined-0 7m8s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:solr-combined-0 + Warning evict pod; ConditionStatus:True; PodName:solr-combined-0 7m8s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:solr-combined-0 + Warning running pod; ConditionStatus:False 7m3s KubeDB Ops-manager Operator running pod; ConditionStatus:False + Warning get pod; ConditionStatus:True; PodName:solr-combined-1 6m23s KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:solr-combined-1 + Warning evict pod; ConditionStatus:True; PodName:solr-combined-1 6m23s KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:solr-combined-1 + Normal RestartNodes 5m20s KubeDB Ops-manager Operator Successfully restarted all nodes + Normal RestartNodes 5m20s KubeDB Ops-manager Operator Successfully restarted all nodes + Normal Starting 5m20s KubeDB Ops-manager Operator Resuming Solr database: demo/solr-combined + Normal Successful 5m20s KubeDB Ops-manager Operator Successfully resumed Solr database: demo/solr-combined for SolrOpsRequest: solrops-rotate-auth-generated + +``` +**Verify Auth is rotated** +```shell +$ kubectl get solr -n demo solr-combined -ojson | jq .spec.authsecret.name +"solr-combined-auth" +$ kubectl get secret -n demo solr-combined-auth -o jsonpath='{.data.username}' | base64 -d +admin⏎ +$ kubectl get secret -n demo solr-combined-auth -o jsonpath='{.data.password}' | base64 -d +dt(MVdBeBDlEy~Cp⏎ +``` +Also, there will be two more new keys in the secret that stores the previous credentials. The keys are `username.prev` and `password.prev`. You can find the secret and its data by running the following command: + +```shell +$ kubectl get secret -n demo solr-combined-auth -o go-template='{{ index .data "username.prev" }}' | base64 -d +admin⏎ +$ kubectl get secret -n demo solr-combined-auth -o go-template='{{ index .data "password.prev" }}' | base64 -d +QtnsJluRRjaaWWec⏎ +``` +The above output shows that the password has been changed successfully. The previous username & password is stored for rollback purpose. +#### 2. Using user created credentials + +At first, we need to create a secret with kubernetes.io/basic-auth type using custom username and password. Below is the command to create a secret with kubernetes.io/basic-auth type, + +```shell +$ kubectl create secret generic solr-combined-user-auth -n demo \ + --type=kubernetes.io/basic-auth \ + --from-literal=username=admin \ + --from-literal=password=Solr-secret + secret/solr-combined-user-auth created +``` +Now create a `SolrOpsRequest` with `RotateAuth` type. Below is the YAML of the `SolrOpsRequest` that we are going to create, + +```shell +apiVersion: ops.kubedb.com/v1alpha1 +kind: SolrOpsRequest +metadata: + name: solrops-rotate-auth-user + namespace: demo +spec: + type: RotateAuth + databaseRef: + name: solr-combined + authentication: + secretRef: + name: solr-combined-user-auth + timeout: 5m + apply: IfReady +``` +Here, + +- `spec.databaseRef.name` specifies that we are performing rotate authentication operation on `solr-combined`cluster. +- `spec.type` specifies that we are performing `RotateAuth` on Solr. +- `spec.authentication.secretRef.name` specifies that we are using `solr-combined-user-auth` as `spec.authsecret.name` for authentication. + +Let's create the `SolrOpsRequest` CR we have shown above, + +```shell +$ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/examples/solr/rotate-auth/rotateauthuser.yaml +solropsrequest.ops.kubedb.com/solrops-rotate-auth-user created +``` +Let’s wait for `SolrOpsRequest` to be Successful. Run the following command to watch `SolrOpsRequest` CRO: + +```shell +$ kubectl get Solropsrequest -n demo +NAME TYPE STATUS AGE +solrops-rotate-auth-generated RotateAuth Successful 13m +solrops-rotate-auth-user RotateAuth Successful 2m3s +``` +We can see from the above output that the `SolrOpsRequest` has succeeded. If we describe the `SolrOpsRequest` we will get an overview of the steps that were followed. +```shell +$ kubectl describe Solropsrequest -n demo solrops-rotate-auth-user +Name: solrops-rotate-auth-user +Namespace: demo +Labels: +Annotations: +API Version: ops.kubedb.com/v1alpha1 +Kind: SolrOpsRequest +Metadata: + Creation Timestamp: 2025-07-21T05:57:25Z + Generation: 1 + Resource Version: 152942 + UID: 35345a38-15f1-40d1-ae7f-155e4f9663d3 +Spec: + Apply: IfReady + Authentication: + secret Ref: + Name: solr-combined-user-auth + Database Ref: + Name: solr-combined + Timeout: 5m + Type: RotateAuth +Status: + Conditions: + Last Transition Time: 2025-07-21T05:57:25Z + Message: Solr ops-request has started to rotate auth for solr nodes + Observed Generation: 1 + Reason: RotateAuth + Status: True + Type: RotateAuth + Last Transition Time: 2025-07-21T05:57:28Z + Message: Successfully referenced the user provided authsecret + Observed Generation: 1 + Reason: UpdateCredential + Status: True + Type: UpdateCredential + Last Transition Time: 2025-07-21T05:57:36Z + Message: successfully reconciled the Solr with updated version + Observed Generation: 1 + Reason: UpdatePetSets + Status: True + Type: UpdatePetSets + Last Transition Time: 2025-07-21T05:59:27Z + Message: Successfully restarted all nodes + Observed Generation: 1 + Reason: RestartNodes + Status: True + Type: RestartNodes + Last Transition Time: 2025-07-21T05:57:41Z + Message: get pod; ConditionStatus:True; PodName:solr-combined-0 + Observed Generation: 1 + Status: True + Type: GetPod--solr-combined-0 + Last Transition Time: 2025-07-21T05:57:41Z + Message: evict pod; ConditionStatus:True; PodName:solr-combined-0 + Observed Generation: 1 + Status: True + Type: EvictPod--solr-combined-0 + Last Transition Time: 2025-07-21T05:57:46Z + Message: running pod; ConditionStatus:False + Observed Generation: 1 + Status: False + Type: RunningPod + Last Transition Time: 2025-07-21T05:58:26Z + Message: get pod; ConditionStatus:True; PodName:solr-combined-1 + Observed Generation: 1 + Status: True + Type: GetPod--solr-combined-1 + Last Transition Time: 2025-07-21T05:58:26Z + Message: evict pod; ConditionStatus:True; PodName:solr-combined-1 + Observed Generation: 1 + Status: True + Type: EvictPod--solr-combined-1 + Last Transition Time: 2025-07-21T05:59:28Z + Message: Successfully completed reconfigure solr + Observed Generation: 1 + Reason: Successful + Status: True + Type: Successful + Observed Generation: 1 + Phase: Successful +Events: + Type Reason Age From Message + ---- ------ ---- ---- ------- + Normal Starting 13m KubeDB Ops-manager Operator Start processing for SolrOpsRequest: demo/solrops-rotate-auth-user + Normal Starting 13m KubeDB Ops-manager Operator Pausing Solr databse: demo/solr-combined + Normal Successful 13m KubeDB Ops-manager Operator Successfully paused Solr database: demo/solr-combined for SolrOpsRequest: solrops-rotate-auth-user + Normal UpdatePetSets 12m KubeDB Ops-manager Operator successfully reconciled the Solr with updated version + Warning get pod; ConditionStatus:True; PodName:solr-combined-0 12m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:solr-combined-0 + Warning evict pod; ConditionStatus:True; PodName:solr-combined-0 12m KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:solr-combined-0 + Warning running pod; ConditionStatus:False 12m KubeDB Ops-manager Operator running pod; ConditionStatus:False + Warning get pod; ConditionStatus:True; PodName:solr-combined-1 12m KubeDB Ops-manager Operator get pod; ConditionStatus:True; PodName:solr-combined-1 + Warning evict pod; ConditionStatus:True; PodName:solr-combined-1 12m KubeDB Ops-manager Operator evict pod; ConditionStatus:True; PodName:solr-combined-1 + Normal RestartNodes 11m KubeDB Ops-manager Operator Successfully restarted all nodes + Normal Starting 11m KubeDB Ops-manager Operator Resuming Solr database: demo/solr-combined + Normal Successful 11m KubeDB Ops-manager Operator Successfully resumed Solr database: demo/solr-combined for SolrOpsRequest: solrops-rotate-auth-user + +``` +**Verify auth is rotate** +```shell +$ kubectl get solr -n demo solr-combined -ojson | jq .spec.authsecret.name +"solr-combined-user-auth" +$ kubectl get secret -n demo solr-combined-user-auth -o jsonpath='{.data.username}' | base64 -d +solr⏎ +$ kubectl get secret -n demo solr-combined-user-auth -o jsonpath='{.data.password}' | base64 -d +Solr-secret⏎ +``` +Also, there will be two more new keys in the secret that stores the previous credentials. The keys are `username.prev` and `password.prev`. You can find the secret and its data by running the following command: +```shell +$ kubectl get secret -n demo solr-combined-user-auth -o go-template='{{ index .data "username.prev" }}' | base64 -d +Solr +$ kubectl get secret -n demo solr-combined-user-auth -o go-template='{{ index .data "password.prev" }}' | base64 -d +dt(MVdBeBDlEy~Cp⏎ +``` + +The above output shows that the password has been changed successfully. The previous username & password is stored in the secret for rollback purpose. + +## Cleaning up + +To clean up the Kubernetes resources you can delete the CRD or namespace. +Or, you can delete one by one resource by their name by this tutorial, run: + +```shell +$ kubectl delete Solropsrequest solrops-rotate-auth-generated solrops-rotate-auth-user -n demo +Solropsrequest.ops.kubedb.com "solrops-rotate-auth-generated" "solrops-rotate-auth-user" deleted +$ kubectl delete secret -n demo solr-combined-user-auth +secret "solr-combined-user-auth" deleted +$ kubectl delete secret -n demo solr-combined-auth +secret "solr-combined-auth" deleted +``` + +## Next Steps + +- Detail concepts of [Solr object](/docs/guides/solr/concepts/solr.md). +- Different Solr topology clustering modes [here](/docs/guides/solr/clustering/topology_cluster.md). +- Monitor your Solr database with KubeDB using [out-of-the-box Prometheus operator](/docs/guides/solr/monitoring/prometheus-operator.md). +- Monitor your Solr database with KubeDB using [out-of-the-box builtin-Prometheus](/docs/guides/solr/monitoring/prometheus-builtin.md) +- Want to hack on KubeDB? Check our [contribution guidelines](/docs/CONTRIBUTING.md).