How To Secure Kubernetes Secrets

Kubernetes Secrets management is important for safeguarding sensitive information, such as passwords, OAuth tokens, and SSH keys. However, out-of-the-box Kubernetes Secrets are stored in base64 encoding, which is not encrypted; thus, it's imperative to add additional layers of security. This post explores various strategies to enhance the security of Kubernetes Secrets.

Creating a Kubernetes secret can be done in several ways, depending on the type of data you are handling. Below are the steps and configurations for creating a generic secret, a docker-registry secret, and a TLS secret:

Creating a Generic Secret:

  • You can create a generic secret from a literal or from a file. Here's how you can do it from a literal:
kubectl create secret generic my-secret --from-literal=key1=value1 --from-literal=key2=value2

And from a file:

echo -n 'value1' > ./key1.txt

echo -n 'value2' > ./key2.txt

kubectl create secret generic my-secret --from-file=key1=./key1.txt --from-file=key2=./key2.txt

Creating a Docker-Registry Secret

  • If you need to authenticate to a Docker registry, you can create a docker-registry secret:
kubectl create secret docker-registry my-reg-secret --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL

These commands will create secrets in the current namespace. If you want to create a secret in a specific namespace, you can add the --namespace flag followed by the namespace name.

In addition to the command line, you can also create secrets using a YAML configuration file. Here's an example of a generic secret configuration:

apiVersion: v1
kind: Secret
metadata:
  name: my-secret
type: Opaque
data:
  key1: dmFsdWUx  # base64 encoded value of 'value1'
  key2: dmFsdWUy  # base64 encoded value of 'value2'

You can then apply this configuration using kubectl apply -f ./secret.yaml

Encrypting Secrets at Rest

  • Use EncryptionConfig: Create an EncryptionConfig file with the necessary encryption providers. Below is a sample configuration using the aescbc encryption provider:
kind: EncryptionConfig
apiVersion: v1
resources:
  - resources:
      - secrets
    providers:
      - aescbc:
          keys:
            - name: key1
              secret: <base64-encoded AES key>
      - identity: {}
  • Configure the API server: Specify the --encryption-provider-config flag and the path to the EncryptionConfig file when starting the Kubernetes API server:
kube-apiserver --encryption-provider-config=/path/to/encryption-config.yaml

Encrypting Secrets in Transit

  • Enable TLS: Ensure that TLS is enabled for all communications between your Kubernetes components, etcd.
  • Role-Based Access Control (RBAC): Define roles with the necessary permissions and bind them to users or groups. Below is an example of a Role and RoleBinding for managing Secrets:
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: default
  name: secret-manager
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: secret-manager-binding
  namespace: default
subjects:
- kind: User
  name: alice
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: secret-manager
  apiGroup: rbac.authorization.k8s.io

Third-Party Secrets Management Solutions

Integrating third-party secret management solutions like CTO.ai secret management store, you can enable a more robust secret protection and lifecycle management.

Storing Secrets Securely

Use CTOai secrets to store and manage your secrets securely. Secrets allow you to share environment variables across multiple projects.

version: "1"
commands:
# setup aws ecs fargate infrastructure
  - name: setup-aws-ecs-fargate:0.3.2
    run: ./node_modules/.bin/ts-node /ops/src/setup.ts
    description: "setup an environment"
    # environment variables 
    env:
    # add static env vars
      static:
        - STACK_TYPE=aws-ecs-fargate
        - AWS_REGION=us-west-1
        - JSII_DEPRECATED=quiet
      # add and store aws secrets
      secrets:
        - AWS_ACCESS_KEY_ID
        - AWS_SECRET_ACCESS_KEY
        - AWS_ACCOUNT_NUMBER

Environment Variables

Store Kubernetes secrets as environment variables within CTO.ai. This way, they can be accessed securely within your pipeline.

version: "1"
commands:
  # setup your digitalocean infrastructure and specify your configs
  - name: setup-do-k8s-cdktf:0.1.2
    run: ./node_modules/.bin/ts-node /ops/src/setup.ts
    description: "Setup Kubernetes infrastructure on DigitalOcean"
    env:
      static:
        - STACK_TYPE=do-k8s-cdktf
        - STACK_ENTROPY=20220921
        - TFC_ORG=cto-ai
        - REGION=nyc3
      secrets:
        - DO_TOKEN
        - DO_SPACES_ACCESS_KEY_ID
        - DO_SPACES_SECRET_ACCESS_KEY
        - TFC_TOKEN
      configs:
        - DEV_DO_K8S_CDKTF_STATE
        - STG_DO_K8S_CDKTF_STATE
        - PRD_DO_K8S_CDKTF_STATE
        - DO_DEV_K8S_CONFIG
        - DO_STG_K8S_CONFIG
        - DO_PRD_K8S_CONFIG
        - DO_DEV_REDIS_CONFIG
        - DO_DEV_POSTGRES_CONFIG
        - DO_DEV_MYSQL_CONFIG

Conclusion

Securing Kubernetes Secrets requires a multi-faceted approach. By encrypting secrets, enforcing strict access controls, and using CTO.ai secrets management solutions, you can significantly enhance the security posture of your Kubernetes environment.