MinIO Operator certificate issued by Kubernetes CSR
In the current Kubernetes landscape, the standard approach for creating, managing, and automating TLS certificates is through the use of the kind: CertificateSigningRequest
(CSR) resource. This native Kubernetes resource provides a robust and efficient way to handle the entire lifecycle of certificates within your cluster.
By leveraging the CSR resource, you can streamline and automate various aspects of certificate management, including:
- Creating certificates: CSRs allow you to easily generate new certificates for your services, ensuring secure communication between components within your cluster.
- Renewing certificates: With CSRs, you can automate the process of renewing certificates before they expire, eliminating the need for manual intervention and reducing the risk of service disruptions.
- Revoking certificates: In case a certificate needs to be revoked due to security concerns or other reasons, CSRs provide a straightforward mechanism to invalidate the certificate and prevent its further use.
We will focus on utilizing the Kubernetes CSR resource specifically for creating a certificate that can be used by MinIO. By the end of this guide, you will have a clear understanding of how to generate a certificate using CSR, store it securely in a Kubernetes Secret, and configure MinIO to access and use the generated certificate.
The generated private keys and public certificates will be securely stored in a Kubernetes Secret named operator-tls. This Secret will be accessible to the Operators, allowing them to utilize the certificates for secure communication.
Tutorial
To start, we will generate a self-signed private key using the Elliptic Curve Digital Signature Algorithm (ECDSA) with the P-256 curve. ECDSA is a widely-used and secure algorithm for generating key pairs.
Step 1: Generate a Self-Signed Private Key
To start, we will generate a self-signed private key using the “Elliptic Curve Digital Signature Algorithm” (ECDSA) with the P-256 curve. ECDSA is a widely-used and secure algorithm for generating key pairs.
openssl ecparam -name prime256v1 -genkey -noout -out private.key |
Optionally you could use a different algorithm, using RSA.
openssl genrsa -out private.key 2048 |
Step 2: Generate a Certificate Signing Request (CSR)
With the private key generated, we can now create a Certificate Signing Request (CSR). The CSR contains information about the entity requesting the certificate and is signed with the private key.
openssl req -new -key private.key -out curve.csr \ -subj "/O=system:nodes/CN=system:node:operator.minio-operator.svc" \ -addext "subjectAltName = DNS:operator,DNS:operator.minio-operator.svc,DNS:operator.minio-operator.svc.cluster.local" |
Step 3: Encode the CSR in Base64
To include the CSR in a Kubernetes resource, we need to convert it to a base64-encoded string.
base64 curve.csr |
Step 4: Create a Kubernetes CertificateSigningRequest
Create a file named csr-manual.yaml
with the following contents, replacing <copy base64 encoded curve.csr here>
with the base64-encoded CSR from the previous step.
apiVersion: certificates.k8s.io/v1 kind: CertificateSigningRequest metadata: name: operator-minio-operator-csr spec: request: <copy base64 encoded curve.csr here> signerName: kubernetes.io/kubelet-serving expirationSeconds: 604800 #extend here for 1 year long groups: - system:serviceaccounts - system:serviceaccounts:minio-operator - system:authenticated - system:nodes usages: - "digital signature" - "key encipherment" - "server auth" username: system:serviceaccount:minio-operator:minio-operator |
Note: Regarding EKS 1.21 and 1.22: On EKS 1.22+ the signerName kubernetes.io/legacy-unknown
is not allowed, you should set a signerName as in the example above or beta.eks.amazonaws.com/app-serving
, for more details on CSR signing on EKS see Certificate signing documentation. On previous versions of EKS (1.21 and below) you could use the certificate CSR API v1beta1
and send the signerName kubernetes.io/legacy-unknown.
Note: on Kubernetes 1.21 and below: The field expirationSeconds
was introduced in Kubernetes 1.22, prior to that the field is silently dropped and not honored
Using the csr-manual.yaml
file created in the previous step, create the Kubernetes CSR resource.
kubectl apply -f csr-manual.yaml |
Step 6: Approve the CSR
Approve the CSR manually. This is a one-time step.
kubectl certificate approve operator-minio-operator-csr |
Step 7: Retrieve the Signed Certificate
Get the public certificate from .status.certificate
key in the Kubernetes csr
resource.
kubectl get csr operator-minio-operator-csr -o jsonpath="{.status.certificate}" | base64 --decode > public.crt |
Step 7: Verify the Certificate
Let’s verify the certificate we fetched above.
Extract the certificate from the CSR resource, it will be in base64. Decode the base64 and read it with OpenSSL as shown below.
kubectl get csr operator-minio-operator-csr -ojsonpath="{.status.certificate}" | base64 --decode | openssl x509 -noout -text |
A certificate description similar to this would appear:
Certificate: Data: Version: 3 (0x2) Serial Number: 19:35:68:7b:bc:16:51:b1:95:14:15:45:13:27:e2:b7 Signature Algorithm: sha256WithRSAEncryption Issuer: CN=kubernetes Validity Not Before: Mar 15 22:25:10 2023 GMT Not After : Mar 14 22:25:10 2024 GMT Subject: O=system:nodes, CN=system:node:operator.minio-operator.svc Subject Public Key Info: Public Key Algorithm: id-ecPublicKey Public-Key: (256 bit) pub: 04:5b:53:08:98:54:8f:45:c9:e9:15:49:73:cc:50: fe:32:ec:33:de:f8:79:6e:87:a9:7d:01:3e:c3:b0: 20:21:69:46:33:a5:44:92:18:90:79:4f:b4:e5:d9: a7:94:5f:b1:4b:73:57:e3:3a:cc:d8:be:24:94:3f: 32:2d:d3:f4:38 ASN1 OID: prime256v1 NIST CURVE: P-256 X509v3 extensions: X509v3 Key Usage: critical Digital Signature, Key Encipherment X509v3 Extended Key Usage: TLS Web Server Authentication X509v3 Basic Constraints: critical CA:FALSE X509v3 Authority Key Identifier: keyid:73:58:4C:D0:20:80:2A:C4:7A:5E:EE:26:C0:28:50:CA:F2:05:48:73 X509v3 Subject Alternative Name: DNS:operator, DNS:operator.minio-operator.svc, DNS:operator.minio-operator.svc.cluster.local Signature Algorithm: sha256WithRSAEncryption 64:1c:de:99:cd:54:e8:eb:08:fd:89:c5:6a:94:a5:29:dd:a9: ... |
The output will display the certificate details, including the subject, issuer, validity period, and extensions.
Step 9: Create a Kubernetes Secret
Finally, this is where the rubber meets the road. We’ll create a Kubernetes secret
for Operator to use
kubectl create secret generic --from-file=./private.key --from-file=./public.crt operator-tls -n minio-operator |
Next time the operator starts, it will not attempt to create the certificate or the secret, instead it will be using the one we stored in the secret minio-operator
.
Simplifying Certificate Management with MinIO and Kubernetes
We couldn’t have written this short tutorial with another object store. Other similar object stores are tremendously complex and time consuming to set up, but we just set up the MinIO operator to use certificates from a secret without too much lift by just using built-in Kubernetes resources.
While other object storage solutions often require complex configurations and time-consuming setup processes, MinIO's design and tight integration with Kubernetes allow developers and administrators to focus on their core business logic, knowing that their object storage is secure and properly authenticated. The simplicity and efficiency of MinIO's certificate management process set it apart from the competition, making it the preferred choice for businesses seeking a powerful and reliable object storage solution.
If you have any questions, encounter challenges, or simply want to share your experiences with MinIO, our vibrant community is here to help. Join us on Slack, where you can connect with fellow MinIO enthusiasts, get expert advice, and stay up-to-date with the latest developments in the world of object storage.