Usuarios
Utilizamos cuentas de servicio para dar permisos a aplicaciones, como si fueran bots.
- podemos tener usuarios, pero no existe un recurso usuario en Kubernetes.
- podemos tener cuentas de servicio.
Si no existe un usuario en Kubernetes, ¿qué es un usuario?
Un usuario es alguien que tiene un certificado y una clave que fue firmada por la autoridad certificadora de Kubernetes.
Definimos el usuario por el CN (common name) del certificado.

Después de la autorización, los permisos se verifican en cada petición que se ejecuta por la API de Kubernetes comparando el CN con los permisos que puede tener.
Para crear un certificado necesitamos crear una solicitud de certificado (CSR) y enviarla para ser firmada por la CA de Kubernetes. Para crear un CSR se pueden usar varias herramientas, pero la más común es OpenSSL.
Un CSR es el certificado sin la firma de una CA.
El segundo paso es enviar el CSR a la API de Kubernetes mediante un CertificateSigningRequest para que sea firmado por la CA del clúster Kubernetes. La API es el único componente de Kubernetes que tiene acceso al certificado de la autoridad certificadora del clúster, pero necesita ser aprobado por alguien que tenga ese poder de liberar esta aprobación (admin del clúster por ejemplo).
Una vez aprobado ese CertificateSigningRequest, la API firmará el CSR y en el mismo CertificateSigningRequest se disponibilizará el CRT que es el certificado firmado por la CA.
El CRT es el CSR + Firma de la CA.
Este debe ser enviado al solicitante de alguna manera, pero no es automático. Podemos copiarlo y enviarlo por email por ejemplo.

Solo para que conste, como administrador de un clúster self hosted y teniendo acceso a los nodos masters, podemos tener acceso a la CA del clúster. Si queremos copiar el certificado y firmarlo nosotros mismos sin la API de Kubernetes es posible.
La API de Kubernetes facilita el proceso para nosotros, mantiene el certificado dentro del clúster garantizando la seguridad. No es porque podamos hacerlo que debamos hacerlo.
Una vez que un certificado es emitido no existe una manera de revocarlo. Permanece válido siempre que la fecha de expiración no haya sido alcanzada.
Si un certificado está comprometido, lo que debemos hacer:
- Eliminar todos los accesos vía RBAC.
- El nombre de usuario no podrá ser usado hasta que el certificado expire.
- Recrear la CA del clúster y reemitir todos los certificados.
Sabiendo esto:
- No compartas certificados o accesos.
- No emitas certificados de larga validez.
- No uses nombres simples como jane, usa el correo electrónico que es algo único.
- Gestiona el acceso al certificado con un gestor de contraseñas.
Creando un certificado de usuario
# Generando la clave privada
root@cks-master:/etc/kubernetes/manifests# openssl genrsa -out david.key 2048
Generating RSA private key, 2048 bit long modulus (2 primes)
...........................+++++
............................................................................................................................+++++
e is 65537 (0x010001)
# Generando el CSR
root@cks-master:~# openssl req -new -key david.key -out david.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:david
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
root@cks-master:~# ls david.*
david.csr david.key
# Necesitaremos el CSR en base64 para rellenar la solicitud
root@cks-master:~# cat david.csr | base64 | tr -d "\n"
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ21qQ0NBWUlDQVFBd1ZURUxNQWtHQTFVRUJoTUNRVlV4RXpBUkJnTlZCQWdNQ2xOdmJXVXRVM1JoZEdVeApJVEFmQmdOVkJBb01HRWx1ZEdWeWJtVjBJRmRwWkdkcGRITWdVSFI1SUV4MFpERU9NQXdHQTFVRUF3d0ZaR0YyCmFXUXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDMEZBa0FPK3N2VXdFTVhiTUMKK0hZMjdEbDh4QTZSWG83YmxIbnl5QkE3Y2J1MG9qa3FIV1ZEQU5LWnczMnd6WDFhTXYrcHZFNmVFejdRVE9wZgo2RlM4WmZaQnkzenJxejZFQWR2WVFWNTIxZUJlTURBeVhrY1R1RkhoZmFNY1RsS2NTaS9RbTdFaGJyOXdhbW5oCk9jcC9PY05Na3J3OW1LKzRlcTQxUEFLTHBVTnB1bURLR0RQQWVVUW0wQnJDYzdvTzlpVG1veVRUaDlSejNKTHQKNDU4eFUxQ3ZVWVBsTnZtYldIWEFrQktXOVlLOGFWRy9pTjhtaDY0VWozbENVZHcyQ29HVFFhNjVlZGxWYTZCVgpwWVF4dExMa1BmS2RmOGpvQUxpYzU2NGgydnB4RGRkM3JYQXN2WUtuYW0wZHVtUmJBZFpPYWlqR3RiN29HVFZYCkFEZjNBZ01CQUFHZ0FEQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFlWlk2WnRVMi9Dd0YwcGN1Ly9za1F1LzAKUlg4d0J6b3d5RW43THJlOXlsN3JRV2NLRmhRVER4YloxeFFOZjVKYTd5bjdIQ1J2M2ZpN1hCUURRSVJMckRldgo0WkpIclVDVDkvbW1qYUVZMnAyRHJHREplMEptdXpZZFYxczZtN0hWdmJSVThQUVJFazNGNUtvSjlPbFBncHhYClplYjhkS2dNNUxyY0JkZHRZMytqVXovRGVqckR2UnlVT2g2YkgvVzNNeDhicS8ycEhNRXFvRFFNUStVZzdheE4Kd3Nrbjk1eDVZM2VpNFpoVFBYVmk3R05jRlNzQWpXQWpBZk5aWC9BNjF2SDQ5UnlZT2o3eDNFZlJVeFdSRHRNZQphcmJ0NG8zdzlULzdxYW5jK1I4S2NqNTVvdC9MaXNpY0hkbTM4a3FQK1NNOGE0endLaUJZN2xIUk1sTjlwQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQo=root@cks-master:~#
Creamos un CertificationSigningRequest con el yaml siguiente.
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: david
spec:
request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ21qQ0NBWUlDQVFBd1ZURUxNQWtHQTFVRUJoTUNRVlV4RXpBUkJnTlZCQWdNQ2xOdmJXVXRVM1JoZEdVeApJVEFmQmdOVkJBb01HRWx1ZEdWeWJtVjBJRmRwWkdkcGRITWdVSFI1SUV4MFpERU9NQXdHQTFVRUF3d0ZaR0YyCmFXUXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDMEZBa0FPK3N2VXdFTVhiTUMKK0hZMjdEbDh4QTZSWG83YmxIbnl5QkE3Y2J1MG9qa3FIV1ZEQU5LWnczMnd6WDFhTXYrcHZFNmVFejdRVE9wZgo2RlM4WmZaQnkzenJxejZFQWR2WVFWNTIxZUJlTURBeVhrY1R1RkhoZmFNY1RsS2NTaS9RbTdFaGJyOXdhbW5oCk9jcC9PY05Na3J3OW1LKzRlcTQxUEFLTHBVTnB1bURLR0RQQWVVUW0wQnJDYzdvTzlpVG1veVRUaDlSejNKTHQKNDU4eFUxQ3ZVWVBsTnZtYldIWEFrQktXOVlLOGFWRy9pTjhtaDY0VWozbENVZHcyQ29HVFFhNjVlZGxWYTZCVgpwWVF4dExMa1BmS2RmOGpvQUxpYzU2NGgydnB4RGRkM3JYQXN2WUtuYW0wZHVtUmJBZFpPYWlqR3RiN29HVFZYCkFEZjNBZ01CQUFHZ0FEQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFlWlk2WnRVMi9Dd0YwcGN1Ly9za1F1LzAKUlg4d0J6b3d5RW43THJlOXlsN3JRV2NLRmhRVER4YloxeFFOZjVKYTd5bjdIQ1J2M2ZpN1hCUURRSVJMckRldgo0WkpIclVDVDkvbW1qYUVZMnAyRHJHREplMEptdXpZZFYxczZtN0hWdmJSVThQUVJFazNGNUtvSjlPbFBncHhYClplYjhkS2dNNUxyY0JkZHRZMytqVXovRGVqckR2UnlVT2g2YkgvVzNNeDhicS8ycEhNRXFvRFFNUStVZzdheE4Kd3Nrbjk1eDVZM2VpNFpoVFBYVmk3R05jRlNzQWpXQWpBZk5aWC9BNjF2SDQ5UnlZT2o3eDNFZlJVeFdSRHRNZQphcmJ0NG8zdzlULzdxYW5jK1I4S2NqNTVvdC9MaXNpY0hkbTM4a3FQK1NNOGE0endLaUJZN2xIUk1sTjlwQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQo=
signerName: kubernetes.io/kube-apiserver-client
# expirationSeconds: 86400 # un día
expirationSeconds: 15552000 # 180 días
usages:
- client auth
Ahora podemos aplicar ese yaml.
root@cks-master:~# kubectl apply -f csr.yaml
certificatesigningrequest.certificates.k8s.io/david created
# Podemos ver los CSR en estado de pending esperando aprobación
root@cks-master:~# k get csr
NAME AGE SIGNERNAME REQUESTOR REQUESTEDDURATION CONDITION
david 35s kubernetes.io/kube-apiserver-client kubernetes-admin 180d Pending
# Vamos a aprobar
root@cks-master:~# k certificate approve david
certificatesigningrequest.certificates.k8s.io/david approved
# Comprobando
root@cks-master:~# k get csr
NAME AGE SIGNERNAME REQUESTOR REQUESTEDDURATION CONDITION
david 4m20s kubernetes.io/kube-apiserver-client kubernetes-admin 180d Approved,Issued
root@cks-master:~# k get csr david -o yaml
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"certificates.k8s.io/v1","kind":"CertificateSigningRequest","metadata":{"annotations":{},"name":"david"},"spec":{"expirationSeconds":15552000,"request":"LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ21qQ0NBWUlDQVFBd1ZURUxNQWtHQTFVRUJoTUNRVlV4RXpBUkJnTlZCQWdNQ2xOdmJXVXRVM1JoZEdVeApJVEFmQmdOVkJBb01HRWx1ZEdWeWJtVjBJRmRwWkdkcGRITWdVSFI1SUV4MFpERU9NQXdHQTFVRUF3d0ZaR0YyCmFXUXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDMEZBa0FPK3N2VXdFTVhiTUMKK0hZMjdEbDh4QTZSWG83YmxIbnl5QkE3Y2J1MG9qa3FIV1ZEQU5LWnczMnd6WDFhTXYrcHZFNmVFejdRVE9wZgo2RlM4WmZaQnkzenJxejZFQWR2WVFWNTIxZUJlTURBeVhrY1R1RkhoZmFNY1RsS2NTaS9RbTdFaGJyOXdhbW5oCk9jcC9PY05Na3J3OW1LKzRlcTQxUEFLTHBVTnB1bURLR0RQQWVVUW0wQnJDYzdvTzlpVG1veVRUaDlSejNKTHQKNDU4eFUxQ3ZVWVBsTnZtYldIWEFrQktXOVlLOGFWRy9pTjhtaDY0VWozbENVZHcyQ29HVFFhNjVlZGxWYTZCVgpwWVF4dExMa1BmS2RmOGpvQUxpYzU2NGgydnB4RGRkM3JYQXN2WUtuYW0wZHVtUmJBZFpPYWlqR3RiN29HVFZYCkFEZjNBZ01CQUFHZ0FEQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFlWlk2WnRVMi9Dd0YwcGN1Ly9za1F1LzAKUlg4d0J6b3d5RW43THJlOXlsN3JRV2NLRmhRVER4YloxeFFOZjVKYTd5bjdIQ1J2M2ZpN1hCUURRSVJMckRldgo0WkpIclVDVDkvbW1qYUVZMnAyRHJHREplMEptdXpZZFYxczZtN0hWdmJSVThQUVJFazNGNUtvSjlPbFBncHhYClplYjhkS2dNNUxyY0JkZHRZMytqVXovRGVqckR2UnlVT2g2YkgvVzNNeDhicS8ycEhNRXFvRFFNUStVZzdheE4Kd3Nrbjk1eDVZM2VpNFpoVFBYVmk3R05jRlNzQWpXQWpBZk5aWC9BNjF2SDQ5UnlZT2o3eDNFZlJVeFdSRHRNZQphcmJ0NG8zdzlULzdxYW5jK1I4S2NqNTVvdC9MaXNpY0hkbTM4a3FQK1NNOGE0endLaUJZN2xIUk1sTjlwQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQo=","signerName":"kubernetes.io/kube-apiserver-client","usages":["client auth"]}}
creationTimestamp: "2024-08-21T03:47:18Z"
name: david
resourceVersion: "397047"
uid: ef44740a-a188-4fd2-9fac-e6ab8481560c
spec:
expirationSeconds: 15552000
groups:
- kubeadm:cluster-admins
- system:authenticated
request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ21qQ0NBWUlDQVFBd1ZURUxNQWtHQTFVRUJoTUNRVlV4RXpBUkJnTlZCQWdNQ2xOdmJXVXRVM1JoZEdVeApJVEFmQmdOVkJBb01HRWx1ZEdWeWJtVjBJRmRwWkdkcGRITWdVSFI1SUV4MFpERU9NQXdHQTFVRUF3d0ZaR0YyCmFXUXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDMEZBa0FPK3N2VXdFTVhiTUMKK0hZMjdEbDh4QTZSWG83YmxIbnl5QkE3Y2J1MG9qa3FIV1ZEQU5LWnczMnd6WDFhTXYrcHZFNmVFejdRVE9wZgo2RlM4WmZaQnkzenJxejZFQWR2WVFWNTIxZUJlTURBeVhrY1R1RkhoZmFNY1RsS2NTaS9RbTdFaGJyOXdhbW5oCk9jcC9PY05Na3J3OW1LKzRlcTQxUEFLTHBVTnB1bURLR0RQQWVVUW0wQnJDYzdvTzlpVG1veVRUaDlSejNKTHQKNDU4eFUxQ3ZVWVBsTnZtYldIWEFrQktXOVlLOGFWRy9pTjhtaDY0VWozbENVZHcyQ29HVFFhNjVlZGxWYTZCVgpwWVF4dExMa1BmS2RmOGpvQUxpYzU2NGgydnB4RGRkM3JYQXN2WUtuYW0wZHVtUmJBZFpPYWlqR3RiN29HVFZYCkFEZjNBZ01CQUFHZ0FEQU5CZ2txaGtpRzl3MEJBUXNGQUFPQ0FRRUFlWlk2WnRVMi9Dd0YwcGN1Ly9za1F1LzAKUlg4d0J6b3d5RW43THJlOXlsN3JRV2NLRmhRVER4YloxeFFOZjVKYTd5bjdIQ1J2M2ZpN1hCUURRSVJMckRldgo0WkpIclVDVDkvbW1qYUVZMnAyRHJHREplMEptdXpZZFYxczZtN0hWdmJSVThQUVJFazNGNUtvSjlPbFBncHhYClplYjhkS2dNNUxyY0JkZHRZMytqVXovRGVqckR2UnlVT2g2YkgvVzNNeDhicS8ycEhNRXFvRFFNUStVZzdheE4Kd3Nrbjk1eDVZM2VpNFpoVFBYVmk3R05jRlNzQWpXQWpBZk5aWC9BNjF2SDQ5UnlZT2o3eDNFZlJVeFdSRHRNZQphcmJ0NG8zdzlULzdxYW5jK1I4S2NqNTVvdC9MaXNpY0hkbTM4a3FQK1NNOGE0endLaUJZN2xIUk1sTjlwQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQo=
signerName: kubernetes.io/kube-apiserver-client
usages:
- client auth
username: kubernetes-admin
status:
# El Certificado está aquí pero está en base64
certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURPakNDQWlLZ0F3SUJBZ0lRU3BRcDJUaEZjOE54NWtSOW45UGQ1VEFOQmdrcWhraUc5dzBCQVFzRkFEQVYKTVJNd0VRWURWUVFERXdwcmRXSmxjbTVsZEdWek1CNFhEVEkwTURneU1UQXpORFl6TVZvWERUSTFNREl4TnpBegpORFl6TVZvd1ZURUxNQWtHQTFVRUJoTUNRVlV4RXpBUkJnTlZCQWdUQ2xOdmJXVXRVM1JoZEdVeElUQWZCZ05WCkJBb1RHRWx1ZEdWeWJtVjBJRmRwWkdkcGRITWdVSFI1SUV4MFpERU9NQXdHQTFVRUF4TUZaR0YyYVdRd2dnRWkKTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDMEZBa0FPK3N2VXdFTVhiTUMrSFkyN0RsOAp4QTZSWG83YmxIbnl5QkE3Y2J1MG9qa3FIV1ZEQU5LWnczMnd6WDFhTXYrcHZFNmVFejdRVE9wZjZGUzhaZlpCCnkzenJxejZFQWR2WVFWNTIxZUJlTURBeVhrY1R1RkhoZmFNY1RsS2NTaS9RbTdFaGJyOXdhbW5oT2NwL09jTk0Ka3J3OW1LKzRlcTQxUEFLTHBVTnB1bURLR0RQQWVVUW0wQnJDYzdvTzlpVG1veVRUaDlSejNKTHQ0NTh4VTFDdgpVWVBsTnZtYldIWEFrQktXOVlLOGFWRy9pTjhtaDY0VWozbENVZHcyQ29HVFFhNjVlZGxWYTZCVnBZUXh0TExrClBmS2RmOGpvQUxpYzU2NGgydnB4RGRkM3JYQXN2WUtuYW0wZHVtUmJBZFpPYWlqR3RiN29HVFZYQURmM0FnTUIKQUFHalJqQkVNQk1HQTFVZEpRUU1NQW9HQ0NzR0FRVUZCd01DTUF3R0ExVWRFd0VCL3dRQ01BQXdId1lEVlIwagpCQmd3Rm9BVXVxUE1RNGcvaGVCb2tsaDZheUpWQm5UNkFZNHdEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBTXY1Cmpsakh1NWhiUzVzVkdZNjR5V3JvVVpjcmhVZm9oM3JGTXlqTDBpa09mbU9XKy9qRmM2ckF0UzRLbUg0ZzRWNEUKRUFVZVVFak9MNDc4WlVqK3QvWDFmNGczd25KQThmRnhxNm5pcmxWMlNPdkJTSlBRSjllaWJ0Q04wa1VlQlNudwpvK29nM2FkUFVDNWk3ZUFHS1hNQkIzZjFTelhZRlNxbG83Zkx3MUs5OG44N0o4bkNVUUgrNzN6d2lQNDJWTGNwCkxQNnI0a2NvS0hacEhiSlZtRTZEcGExTzBCazR1Qm1PaDNvbE1ZaGd6Ymx0czZrMURnNUFjdWhhRjIyOFhuYnUKRFJqZDh5NFk4UkJBZnpZbDRvaHluSkxESWdoZ3hISzZEZlNKYzlBWjZtREtoWm5tbkI5d0o1T3MycmNxekRtNwpxNDdYbDFpd3l2OVkxRm8raFNjPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
conditions:
- lastTransitionTime: "2024-08-21T03:51:31Z"
lastUpdateTime: "2024-08-21T03:51:31Z"
message: This CSR was approved by kubectl certificate approve.
reason: KubectlApprove
status: "True"
type: Approved
# Para facilitar podemos usar el jsonpath y ya hacer el decode
root@cks-master:~# kubectl get csr david -o jsonpath='{.status.certificate}' | base64 --decode
-----BEGIN CERTIFICATE-----
MIIDOjCCAiKgAwIBAgIQSpQp2ThFc8Nx5kR9n9Pd5TANBgkqhkiG9w0BAQsFADAV
MRMwEQYDVQQDEwprdWJlcm5ldGVzMB4XDTI0MDgyMTAzNDYzMVoXDTI1MDIxNzAz
NDYzMVowVTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNV
BAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEOMAwGA1UEAxMFZGF2aWQwggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC0FAkAO+svUwEMXbMC+HY27Dl8
xA6RXo7blHnyyBA7cbu0ojkqHWVDANKZw32wzX1aMv+pvE6eEz7QTOpf6FS8ZfZB
y3zrqz6EAdvYQV521eBeMDAyXkcTuFHhfaMcTlKcSi/Qm7Ehbr9wamnhOcp/OcNM
krw9mK+4eq41PAKLpUNpumDKGDPAeUQm0BrCc7oO9iTmoyTTh9Rz3JLt458xU1Cv
UYPlNvmbWHXAkBKW9YK8aVG/iN8mh64Uj3lCUdw2CoGTQa65edlVa6BVpYQxtLLk
PfKdf8joALic564h2vpxDdd3rXAsvYKnam0dumRbAdZOaijGtb7oGTVXADf3AgMB
AAGjRjBEMBMGA1UdJQQMMAoGCCsGAQUFBwMCMAwGA1UdEwEB/wQCMAAwHwYDVR0j
BBgwFoAUuqPMQ4g/heBoklh6ayJVBnT6AY4wDQYJKoZIhvcNAQELBQADggEBAMv5
jljHu5hbS5sVGY64yWroUZcrhUfoh3rFMyjL0ikOfmOW+/jFc6rAtS4KmH4g4V4E
EAUeUEjOL478ZUj+t/X1f4g3wnJA8fFxq6nirlV2SOvBSJPQJ9eibtCN0kUeBSnw
o+og3adPUC5i7eAGKXMBB3f1SzXYFSqlo7fLw1K98n87J8nCUQH+73zwiP42VLcp
LP6r4kcoKHZpHbJVmE6Dpa1O0Bk4uBmOh3olMYhgzblts6k1Dg5AcuhaF228Xnbu
DRjd8y4Y8RBAfzYl4ohynJLDIghgxHK6DfSJc9AZ6mDKhZnmnB9wJ5Os2rcqzDm7
q47Xl1iwyv9Y1Fo+hSc=
-----END CERTIFICATE-----
kubectl get csr david -o jsonpath='{.status.certificate}' | base64 --decode > david.crt
Ahora podemos usar ese certificado y la clave. Observa que en ningún momento enviamos la clave privada. La clave privada debe quedarse solo con el cliente.
# Estamos añadiendo un usuario a nuestro kubeconfig
root@cks-master:~# k config set-credentials david --client-key=david.key --client-certificate=david.crt
User "david" set.
root@cks-master:~# k config view
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://10.128.0.5:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin
name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: david
user:
client-certificate: /root/david.crt
client-key: /root/david.key
- name: kubernetes-admin
user:
client-certificate-data: DATA+OMITTED
client-key-data: DATA+OMITTED
# Si queremos omitir todos los certificados como muestra kubernetes-admin
root@cks-master:~# k config set-credentials david --client-key=david.key --client-certificate=david.crt --embed-certs
User "david" set.
root@cks-master:~# k config view
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://10.128.0.5:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin
name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: david
user:
client-certificate-data: DATA+OMITTED
client-key-data: DATA+OMITTED
- name: kubernetes-admin
user:
client-certificate-data: DATA+OMITTED
client-key-data: DATA+OMITTED
# Para ver los valores rellenados
root@cks-master:~# k config view --raw
# Ahora vamos a conectar el usuario al clúster mediante el contexto
root@cks-master:~# k config set-context david --user=david --cluster=kubernetes
Context "david" created.
root@cks-master:~# k config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
david kubernetes david
* kubernetes-admin@kubernetes kubernetes kubernetes-admin
# Vamos a usar ese contexto
root@cks-master:~# k config use-context david
Switched to context "david".
# Pero el usuario david no tiene permiso para nada
root@cks-master:~# k get ns
Error from server (Forbidden): namespaces is forbidden: User "david" cannot list resource "namespaces" in API group "" at the cluster scope
root@cks-master:~#
Si fuera el usuario jane tendría permiso para lo que configuramos arriba.
Haz el mismo proceso para jane.