Mutual TLS with self-signed certificates in kubernetes
Contents
Introduction
During my daily work very often I need to set up mutual tls for given service or database. The problem appears during local development, because on local Kubernetes cluster mutual authentication is not provided. In that case, cert manager will help us to solve this problem.
Warning
Self-signed certificates are very useful for local development and testing, but
they shouldn’t be used in production environment. In that case, you can use Vault.
0. Prepare necessary configuration files
certconfig.txt
[ req ]
default_md = sha256
prompt = no
string_mask = utf8only
req_extensions = req_ext
distinguished_name = req_distinguished_name
[ req_distinguished_name ]
commonName = kukulam
organizationName = kukulam.dev
[ req_ext ]
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
keyUsage=critical,digitalSignature,keyEncipherment,keyCertSign
extendedKeyUsage=critical,serverAuth,clientAuth
basicConstraints=critical,CA:true
subjectAltName = @alt_names
[ alt_names ]
DNS.0 = localhost
csrconfig.txt
[ req ]
default_md = sha256
prompt = no
string_mask = utf8only
req_extensions = req_ext
distinguished_name = req_distinguished_name
[ req_distinguished_name ]
commonName = kukulam
organizationName = kukulam.dev
[ req_ext ]
keyUsage=critical,digitalSignature,keyEncipherment,keyCertSign
extendedKeyUsage=critical,serverAuth,clientAuth
basicConstraints=critical,CA:true
subjectAltName = @alt_names
[ alt_names ]
DNS.0 = localhost
generate-cert.sh
Tip
If bash commands are too nerdy for you, there is website which could do the same job.
You can generate certificate by using certificatetools.
Script generates tls.crt
and tls.key
file using configs: csrconfig.txt
, certconfig.txt
.
# Generate the RSA private key
openssl genpkey -outform PEM -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out tls.key
# Create the CSR
openssl req -new -nodes -key tls.key -config csrconfig.txt -nameopt utf8 -utf8 -out cert.csr
# Self-sign your CSR
openssl req -x509 -nodes -in cert.csr -days 365 -key tls.key -config certconfig.txt -extensions req_ext -nameopt utf8 -utf8 -out tls.crt
# Clean up
rm cert.csr
Result:
» ./generate-cert.sh
.+++
..........................................................................................................................................................................+++
» ls
certconfig.txt csrconfig.txt generate-cert.sh tls.crt tls.key
» cat tls.crt
-----BEGIN CERTIFICATE-----
MIIDcDCCAligAwIBAgIJAJ29UKxmiWYsMA0GCSqGSIb3DQEBCwUAMCgxEDAOBgNV
BAMMB2t1a3VsYW0xFDASBgNVBAoMC2t1a3VsYW0uZGV2MB4XDTIzMDQwMzE5MjYw
N1oXDTI0MDQwMjE5MjYwN1owKDEQMA4GA1UEAwwHa3VrdWxhbTEUMBIGA1UECgwL
a3VrdWxhbS5kZXYwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDP9N29
vvDTt7R6izGtUDK7IyrwwZmCHXn5wrle8nXBFvBrHO2lHyyCUARrO986wInW4mXs
UbRyVe8O2Q9ArrRZcMCL55VDEpDDQTROpoxYyYlp30EtOdKDw1cwYQAGGFIjCVrI
IhMaxmP1j7s2FgdNHym6wADEcYzJPLHJxRv9NUd62aTm6UQgjz2bB5CWG6ipYdcO
sMcwaAOhR8pMC1b23gcauVY2ZfhbLVNTZpvfZj9q0IpIds7EjfjzPETKcbvnEtqo
fk6Dm7GO7dusQMZEXccHfLT1HsbIedU9VzXX0l9QIzIo9YhcllkM0l582O9zCvXT
daw0FggHQJCi/sBzAgMBAAGjgZwwgZkwHQYDVR0OBBYEFHWKDAByGkn+vQT0rJG5
EpSJ7xUDMB8GA1UdIwQYMBaAFHWKDAByGkn+vQT0rJG5EpSJ7xUDMA4GA1UdDwEB
/wQEAwICpDAgBgNVHSUBAf8EFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDwYDVR0T
AQH/BAUwAwEB/zAUBgNVHREEDTALgglsb2NhbGhvc3QwDQYJKoZIhvcNAQELBQAD
ggEBABu7JecWhZAx06GL65NSlLicSr8Ie8OmU56uFNY8PWvGt17Hirv47/nCgyLz
ATeDU5TJGLSB/xiOsdUU5i4K8SqTFfunay6rXKkr2We29xR6CLz+LvE27bP7eZ5X
twPeoiuOaFtqQejS4qBEAH3LqSH86sFP1sM69P9MHpoFOZLo4GYMMG8hbmw0vHN6
vSdtZ8FdM+38QkL9Jcjqgh5zSU2GZ+D21TjX5bLr2udxxHRKh+b3IgVz6CbUCWc+
UFQQn55sYUVN6WvA+DZkPr5Mo8KEmd1OwMF8wV/quzvchxbSJq4193ZmgGu7oFAW
BmNdqsdlVXQw5cyATjb5CcG/oTM=
-----END CERTIFICATE-----
» cat tls.key
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDP9N29vvDTt7R6
izGtUDK7IyrwwZmCHXn5wrle8nXBFvBrHO2lHyyCUARrO986wInW4mXsUbRyVe8O
2Q9ArrRZcMCL55VDEpDDQTROpoxYyYlp30EtOdKDw1cwYQAGGFIjCVrIIhMaxmP1
j7s2FgdNHym6wADEcYzJPLHJxRv9NUd62aTm6UQgjz2bB5CWG6ipYdcOsMcwaAOh
R8pMC1b23gcauVY2ZfhbLVNTZpvfZj9q0IpIds7EjfjzPETKcbvnEtqofk6Dm7GO
7dusQMZEXccHfLT1HsbIedU9VzXX0l9QIzIo9YhcllkM0l582O9zCvXTdaw0FggH
QJCi/sBzAgMBAAECggEAGKBl1f+To27g15Y+Rsj1iQXMIwC6Phdhh3tQ2naaDUi7
JeQiHGjJq5DwRQatE9cTO7hJ26d9WADnM3nu/Xjy8JiSpL7DBVNgg07oc9vzSNxt
AnWm0UVEscfjPl5uU0p0B6Qm9QZb/tK5qa3gvLH1IWPsXCo6rQjJZFdksoE+JEkB
TKUITpQ0zyMLJiPTPBg+pX1YOZwV0rYCHexnIX2FlAm1Hith48wA5y92KdImQA7B
qFpSGT4QnKY9xn0kSXPA6EKG/VRgqKRFwg5RgFByYRTmU1KdTWlII7vagTQnPl3G
jbritQSVVu320fUOhcxqSe+iwaWDL6gZ1JXRRjAWgQKBgQDoqNeQsiMfSo7Aa+eN
2EJfATtzsRqwXqfQIUnBf6bgnOG7lOJFSnP7X1bAYPe9z4l8viIU6kN0gRofYBE6
AW0BarRRdZvNcHELgWhIOFlrRx0ye/FnW5UmF26zXY0amc6/gHyFPq3oPKcdzYlB
tX5zZV6xdktZK20XphsH5TEZQQKBgQDk0ZnyC8oF+7WJYfTaeBGaN06bV+cN2qEi
cuFE7zQad/W5zBUkisYPvwizS+EX+kG0jZwi/Bi0hWUwuzcW1pttVRoujzteCy+3
GG/8MZJcr+Rnzzt1LnKV8BQyCP/kEs12/dDyyBB2SEQDJD3ZOrShg2aDUuXilLTl
iaGhSEwYswKBgQCAHiH+qynOHGd5rLHpGVKLMImFjtxMjQNKCFquNFY30Aw6GKV1
VKeDoB+MdplWK8fhKm5oKAyXRlSVPHigAZL+Ob0sMmBmg+msVUmQo38SJSn91+S6
buM2A6dRHE4MfPAt4lovobFwdp3sOne/+Gq2rvazMJoTc2dyo2S1N0+PQQKBgCOM
xQQr/LktQCkWBPqkSOfSy+2qnIU0gHBftMwG9ete09iH8oj43oi3v1xL367f/LFW
hvmQfS4ew3fsvkRYF1HHNQgizLBxwHoL2+ossXahBTVzpuMv0jGlWR3k9Ay1NyLT
kFEH8DbQR3DNgqZrToEBbz3b9UdcnzZCSdBK8TetAoGADxvNI9KyZ2MPT3PDrPAT
i40dcVcOprKouwxcHEaPwwHSkgvEegpLUl3KLgjI3CF2RwmKsf7p2lqTrh7by/pP
G9YcwpMhaG9juXBtsox2mGm0I7KvWYxg/F2FeiFP09mAjwTPFRf7i0XBMqBAWkxD
fGdZQsJxw8Ly+8ANLZG4lEU=
-----END PRIVATE KEY-----
1. Encode certificate with base64
Note
To encode you can use the bash command base64
» echo "text" | base64
dGV4dAo=
or you can use base64encode website.
Encoded tls.crt
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURjRENDQWxpZ0F3SUJBZ0lKQUoyOVVLeG1pV1lzTUEwR0NTcUdTSWIzRFFFQkN3VUFNQ2d4RURBT0JnTlYKQkFNTUIydDFhM1ZzWVcweEZEQVNCZ05WQkFvTUMydDFhM1ZzWVcwdVpHVjJNQjRYRFRJek1EUXdNekU1TWpZdwpOMW9YRFRJME1EUXdNakU1TWpZd04xb3dLREVRTUE0R0ExVUVBd3dIYTNWcmRXeGhiVEVVTUJJR0ExVUVDZ3dMCmEzVnJkV3hoYlM1a1pYWXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFEUDlOMjkKdnZEVHQ3UjZpekd0VURLN0l5cnd3Wm1DSFhuNXdybGU4blhCRnZCckhPMmxIeXlDVUFSck85ODZ3SW5XNG1YcwpVYlJ5VmU4TzJROUFyclJaY01DTDU1VkRFcEREUVRST3BveFl5WWxwMzBFdE9kS0R3MWN3WVFBR0dGSWpDVnJJCkloTWF4bVAxajdzMkZnZE5IeW02d0FERWNZekpQTEhKeFJ2OU5VZDYyYVRtNlVRZ2p6MmJCNUNXRzZpcFlkY08Kc01jd2FBT2hSOHBNQzFiMjNnY2F1VlkyWmZoYkxWTlRacHZmWmo5cTBJcElkczdFamZqelBFVEtjYnZuRXRxbwpmazZEbTdHTzdkdXNRTVpFWGNjSGZMVDFIc2JJZWRVOVZ6WFgwbDlRSXpJbzlZaGNsbGtNMGw1ODJPOXpDdlhUCmRhdzBGZ2dIUUpDaS9zQnpBZ01CQUFHamdad3dnWmt3SFFZRFZSME9CQllFRkhXS0RBQnlHa24rdlFUMHJKRzUKRXBTSjd4VURNQjhHQTFVZEl3UVlNQmFBRkhXS0RBQnlHa24rdlFUMHJKRzVFcFNKN3hVRE1BNEdBMVVkRHdFQgovd1FFQXdJQ3BEQWdCZ05WSFNVQkFmOEVGakFVQmdnckJnRUZCUWNEQVFZSUt3WUJCUVVIQXdJd0R3WURWUjBUCkFRSC9CQVV3QXdFQi96QVVCZ05WSFJFRURUQUxnZ2xzYjJOaGJHaHZjM1F3RFFZSktvWklodmNOQVFFTEJRQUQKZ2dFQkFCdTdKZWNXaFpBeDA2R0w2NU5TbExpY1NyOEllOE9tVTU2dUZOWThQV3ZHdDE3SGlydjQ3L25DZ3lMegpBVGVEVTVUSkdMU0IveGlPc2RVVTVpNEs4U3FURmZ1bmF5NnJYS2tyMldlMjl4UjZDTHorTHZFMjdiUDdlWjVYCnR3UGVvaXVPYUZ0cVFlalM0cUJFQUgzTHFTSDg2c0ZQMXNNNjlQOU1IcG9GT1pMbzRHWU1NRzhoYm13MHZITjYKdlNkdFo4RmRNKzM4UWtMOUpjanFnaDV6U1UyR1orRDIxVGpYNWJMcjJ1ZHh4SFJLaCtiM0lnVno2Q2JVQ1djKwpVRlFRbjU1c1lVVk42V3ZBK0Raa1ByNU1vOEtFbWQxT3dNRjh3Vi9xdXp2Y2h4YlNKcTQxOTNabWdHdTdvRkFXCkJtTmRxc2RsVlhRdzVjeUFUamI1Q2NHL29UTT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ==
Encoded tls.key
LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRRFA5TjI5dnZEVHQ3UjYKaXpHdFVESzdJeXJ3d1ptQ0hYbjV3cmxlOG5YQkZ2QnJITzJsSHl5Q1VBUnJPOTg2d0luVzRtWHNVYlJ5VmU4TwoyUTlBcnJSWmNNQ0w1NVZERXBERFFUUk9wb3hZeVlscDMwRXRPZEtEdzFjd1lRQUdHRklqQ1ZySUloTWF4bVAxCmo3czJGZ2ROSHltNndBREVjWXpKUExISnhSdjlOVWQ2MmFUbTZVUWdqejJiQjVDV0c2aXBZZGNPc01jd2FBT2gKUjhwTUMxYjIzZ2NhdVZZMlpmaGJMVk5UWnB2ZlpqOXEwSXBJZHM3RWpmanpQRVRLY2J2bkV0cW9mazZEbTdHTwo3ZHVzUU1aRVhjY0hmTFQxSHNiSWVkVTlWelhYMGw5UUl6SW85WWhjbGxrTTBsNTgyTzl6Q3ZYVGRhdzBGZ2dIClFKQ2kvc0J6QWdNQkFBRUNnZ0VBR0tCbDFmK1RvMjdnMTVZK1JzajFpUVhNSXdDNlBoZGhoM3RRMm5hYURVaTcKSmVRaUhHakpxNUR3UlFhdEU5Y1RPN2hKMjZkOVdBRG5NM251L1hqeThKaVNwTDdEQlZOZ2cwN29jOXZ6U054dApBbldtMFVWRXNjZmpQbDV1VTBwMEI2UW05UVpiL3RLNXFhM2d2TEgxSVdQc1hDbzZyUWpKWkZka3NvRStKRWtCClRLVUlUcFEwenlNTEppUFRQQmcrcFgxWU9ad1YwcllDSGV4bklYMkZsQW0xSGl0aDQ4d0E1eTkyS2RJbVFBN0IKcUZwU0dUNFFuS1k5eG4wa1NYUEE2RUtHL1ZSZ3FLUkZ3ZzVSZ0ZCeVlSVG1VMUtkVFdsSUk3dmFnVFFuUGwzRwpqYnJpdFFTVlZ1MzIwZlVPaGN4cVNlK2l3YVdETDZnWjFKWFJSakFXZ1FLQmdRRG9xTmVRc2lNZlNvN0FhK2VOCjJFSmZBVHR6c1Jxd1hxZlFJVW5CZjZiZ25PRzdsT0pGU25QN1gxYkFZUGU5ejRsOHZpSVU2a04wZ1JvZllCRTYKQVcwQmFyUlJkWnZOY0hFTGdXaElPRmxyUngweWUvRm5XNVVtRjI2elhZMGFtYzYvZ0h5RlBxM29QS2NkellsQgp0WDV6WlY2eGRrdFpLMjBYcGhzSDVURVpRUUtCZ1FEazBabnlDOG9GKzdXSllmVGFlQkdhTjA2YlYrY04ycUVpCmN1RkU3elFhZC9XNXpCVWtpc1lQdndpelMrRVgra0cwalp3aS9CaTBoV1V3dXpjVzFwdHRWUm91anp0ZUN5KzMKR0cvOE1aSmNyK1Juenp0MUxuS1Y4QlF5Q1Ava0VzMTIvZER5eUJCMlNFUURKRDNaT3JTaGcyYURVdVhpbExUbAppYUdoU0V3WXN3S0JnUUNBSGlIK3F5bk9IR2Q1ckxIcEdWS0xNSW1GanR4TWpRTktDRnF1TkZZMzBBdzZHS1YxClZLZURvQitNZHBsV0s4ZmhLbTVvS0F5WFJsU1ZQSGlnQVpMK09iMHNNbUJtZyttc1ZVbVFvMzhTSlNuOTErUzYKYnVNMkE2ZFJIRTRNZlBBdDRsb3ZvYkZ3ZHAzc09uZS8rR3EycnZhek1Kb1RjMmR5bzJTMU4wK1BRUUtCZ0NPTQp4UVFyL0xrdFFDa1dCUHFrU09mU3krMnFuSVUwZ0hCZnRNd0c5ZXRlMDlpSDhvajQzb2kzdjF4TDM2N2YvTEZXCmh2bVFmUzRldzNmc3ZrUllGMUhITlFnaXpMQnh3SG9MMitvc3NYYWhCVFZ6cHVNdjBqR2xXUjNrOUF5MU55TFQKa0ZFSDhEYlFSM0ROZ3FaclRvRUJiejNiOVVkY256WkNTZEJLOFRldEFvR0FEeHZOSTlLeVoyTVBUM1BEclBBVAppNDBkY1ZjT3ByS291d3hjSEVhUHd3SFNrZ3ZFZWdwTFVsM0tMZ2pJM0NGMlJ3bUtzZjdwMmxxVHJoN2J5L3BQCkc5WWN3cE1oYUc5anVYQnRzb3gybUdtMEk3S3ZXWXhnL0YyRmVpRlAwOW1BandUUEZSZjdpMFhCTXFCQVdreEQKZkdkWlFzSnh3OEx5KzhBTkxaRzRsRVU9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0=
2. Setup ClusterIssuer
with cert-manager
in kubernetes
Note
You can use
Issuer
instead of ClusterIssuer
if you want to
isolate resource within single namespace. ClusterIssuer
is visible globally
in kubernetes cluster.cluster-issuer-secrets.yml
apiVersion: v1
kind: Secret
metadata:
name: ca-issuer-certs
namespace: cert-manager
data:
tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURjRENDQWxpZ0F3SUJBZ0lKQUoyOVVLeG1pV1lzTUEwR0NTcUdTSWIzRFFFQkN3VUFNQ2d4RURBT0JnTlYKQkFNTUIydDFhM1ZzWVcweEZEQVNCZ05WQkFvTUMydDFhM1ZzWVcwdVpHVjJNQjRYRFRJek1EUXdNekU1TWpZdwpOMW9YRFRJME1EUXdNakU1TWpZd04xb3dLREVRTUE0R0ExVUVBd3dIYTNWcmRXeGhiVEVVTUJJR0ExVUVDZ3dMCmEzVnJkV3hoYlM1a1pYWXdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFEUDlOMjkKdnZEVHQ3UjZpekd0VURLN0l5cnd3Wm1DSFhuNXdybGU4blhCRnZCckhPMmxIeXlDVUFSck85ODZ3SW5XNG1YcwpVYlJ5VmU4TzJROUFyclJaY01DTDU1VkRFcEREUVRST3BveFl5WWxwMzBFdE9kS0R3MWN3WVFBR0dGSWpDVnJJCkloTWF4bVAxajdzMkZnZE5IeW02d0FERWNZekpQTEhKeFJ2OU5VZDYyYVRtNlVRZ2p6MmJCNUNXRzZpcFlkY08Kc01jd2FBT2hSOHBNQzFiMjNnY2F1VlkyWmZoYkxWTlRacHZmWmo5cTBJcElkczdFamZqelBFVEtjYnZuRXRxbwpmazZEbTdHTzdkdXNRTVpFWGNjSGZMVDFIc2JJZWRVOVZ6WFgwbDlRSXpJbzlZaGNsbGtNMGw1ODJPOXpDdlhUCmRhdzBGZ2dIUUpDaS9zQnpBZ01CQUFHamdad3dnWmt3SFFZRFZSME9CQllFRkhXS0RBQnlHa24rdlFUMHJKRzUKRXBTSjd4VURNQjhHQTFVZEl3UVlNQmFBRkhXS0RBQnlHa24rdlFUMHJKRzVFcFNKN3hVRE1BNEdBMVVkRHdFQgovd1FFQXdJQ3BEQWdCZ05WSFNVQkFmOEVGakFVQmdnckJnRUZCUWNEQVFZSUt3WUJCUVVIQXdJd0R3WURWUjBUCkFRSC9CQVV3QXdFQi96QVVCZ05WSFJFRURUQUxnZ2xzYjJOaGJHaHZjM1F3RFFZSktvWklodmNOQVFFTEJRQUQKZ2dFQkFCdTdKZWNXaFpBeDA2R0w2NU5TbExpY1NyOEllOE9tVTU2dUZOWThQV3ZHdDE3SGlydjQ3L25DZ3lMegpBVGVEVTVUSkdMU0IveGlPc2RVVTVpNEs4U3FURmZ1bmF5NnJYS2tyMldlMjl4UjZDTHorTHZFMjdiUDdlWjVYCnR3UGVvaXVPYUZ0cVFlalM0cUJFQUgzTHFTSDg2c0ZQMXNNNjlQOU1IcG9GT1pMbzRHWU1NRzhoYm13MHZITjYKdlNkdFo4RmRNKzM4UWtMOUpjanFnaDV6U1UyR1orRDIxVGpYNWJMcjJ1ZHh4SFJLaCtiM0lnVno2Q2JVQ1djKwpVRlFRbjU1c1lVVk42V3ZBK0Raa1ByNU1vOEtFbWQxT3dNRjh3Vi9xdXp2Y2h4YlNKcTQxOTNabWdHdTdvRkFXCkJtTmRxc2RsVlhRdzVjeUFUamI1Q2NHL29UTT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ==
tls.key: LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUV2UUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQktjd2dnU2pBZ0VBQW9JQkFRRFA5TjI5dnZEVHQ3UjYKaXpHdFVESzdJeXJ3d1ptQ0hYbjV3cmxlOG5YQkZ2QnJITzJsSHl5Q1VBUnJPOTg2d0luVzRtWHNVYlJ5VmU4TwoyUTlBcnJSWmNNQ0w1NVZERXBERFFUUk9wb3hZeVlscDMwRXRPZEtEdzFjd1lRQUdHRklqQ1ZySUloTWF4bVAxCmo3czJGZ2ROSHltNndBREVjWXpKUExISnhSdjlOVWQ2MmFUbTZVUWdqejJiQjVDV0c2aXBZZGNPc01jd2FBT2gKUjhwTUMxYjIzZ2NhdVZZMlpmaGJMVk5UWnB2ZlpqOXEwSXBJZHM3RWpmanpQRVRLY2J2bkV0cW9mazZEbTdHTwo3ZHVzUU1aRVhjY0hmTFQxSHNiSWVkVTlWelhYMGw5UUl6SW85WWhjbGxrTTBsNTgyTzl6Q3ZYVGRhdzBGZ2dIClFKQ2kvc0J6QWdNQkFBRUNnZ0VBR0tCbDFmK1RvMjdnMTVZK1JzajFpUVhNSXdDNlBoZGhoM3RRMm5hYURVaTcKSmVRaUhHakpxNUR3UlFhdEU5Y1RPN2hKMjZkOVdBRG5NM251L1hqeThKaVNwTDdEQlZOZ2cwN29jOXZ6U054dApBbldtMFVWRXNjZmpQbDV1VTBwMEI2UW05UVpiL3RLNXFhM2d2TEgxSVdQc1hDbzZyUWpKWkZka3NvRStKRWtCClRLVUlUcFEwenlNTEppUFRQQmcrcFgxWU9ad1YwcllDSGV4bklYMkZsQW0xSGl0aDQ4d0E1eTkyS2RJbVFBN0IKcUZwU0dUNFFuS1k5eG4wa1NYUEE2RUtHL1ZSZ3FLUkZ3ZzVSZ0ZCeVlSVG1VMUtkVFdsSUk3dmFnVFFuUGwzRwpqYnJpdFFTVlZ1MzIwZlVPaGN4cVNlK2l3YVdETDZnWjFKWFJSakFXZ1FLQmdRRG9xTmVRc2lNZlNvN0FhK2VOCjJFSmZBVHR6c1Jxd1hxZlFJVW5CZjZiZ25PRzdsT0pGU25QN1gxYkFZUGU5ejRsOHZpSVU2a04wZ1JvZllCRTYKQVcwQmFyUlJkWnZOY0hFTGdXaElPRmxyUngweWUvRm5XNVVtRjI2elhZMGFtYzYvZ0h5RlBxM29QS2NkellsQgp0WDV6WlY2eGRrdFpLMjBYcGhzSDVURVpRUUtCZ1FEazBabnlDOG9GKzdXSllmVGFlQkdhTjA2YlYrY04ycUVpCmN1RkU3elFhZC9XNXpCVWtpc1lQdndpelMrRVgra0cwalp3aS9CaTBoV1V3dXpjVzFwdHRWUm91anp0ZUN5KzMKR0cvOE1aSmNyK1Juenp0MUxuS1Y4QlF5Q1Ava0VzMTIvZER5eUJCMlNFUURKRDNaT3JTaGcyYURVdVhpbExUbAppYUdoU0V3WXN3S0JnUUNBSGlIK3F5bk9IR2Q1ckxIcEdWS0xNSW1GanR4TWpRTktDRnF1TkZZMzBBdzZHS1YxClZLZURvQitNZHBsV0s4ZmhLbTVvS0F5WFJsU1ZQSGlnQVpMK09iMHNNbUJtZyttc1ZVbVFvMzhTSlNuOTErUzYKYnVNMkE2ZFJIRTRNZlBBdDRsb3ZvYkZ3ZHAzc09uZS8rR3EycnZhek1Kb1RjMmR5bzJTMU4wK1BRUUtCZ0NPTQp4UVFyL0xrdFFDa1dCUHFrU09mU3krMnFuSVUwZ0hCZnRNd0c5ZXRlMDlpSDhvajQzb2kzdjF4TDM2N2YvTEZXCmh2bVFmUzRldzNmc3ZrUllGMUhITlFnaXpMQnh3SG9MMitvc3NYYWhCVFZ6cHVNdjBqR2xXUjNrOUF5MU55TFQKa0ZFSDhEYlFSM0ROZ3FaclRvRUJiejNiOVVkY256WkNTZEJLOFRldEFvR0FEeHZOSTlLeVoyTVBUM1BEclBBVAppNDBkY1ZjT3ByS291d3hjSEVhUHd3SFNrZ3ZFZWdwTFVsM0tMZ2pJM0NGMlJ3bUtzZjdwMmxxVHJoN2J5L3BQCkc5WWN3cE1oYUc5anVYQnRzb3gybUdtMEk3S3ZXWXhnL0YyRmVpRlAwOW1BandUUEZSZjdpMFhCTXFCQVdreEQKZkdkWlFzSnh3OEx5KzhBTkxaRzRsRVU9Ci0tLS0tRU5EIFBSSVZBVEUgS0VZLS0tLS0=
cluster-issuer.yml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: ca-issuer
namespace: cert-manager
spec:
ca:
secretName: ca-issuer-certs
Apply manifests
kubectl apply -f cluster-issuer-secrets.yml
kubectl apply -f cluster-issuer.yml
Result
» kubectl apply -f cluster-issuer-secrets.yml
secret/ca-issuer-certs created
» kubectl apply -f cluster-issuer.yml
clusterissuer.cert-manager.io/ca-issuer created
» kubectl get secrets -n cert-manager
NAME TYPE DATA AGE
ca-issuer-certs Opaque 2 43s
cert-manager-webhook-ca Opaque 3 23h
» kubectl get clusterissuers.cert-manager.io -n cert-manager
NAME READY AGE
ca-issuer True 57s
3. Setup certificate in kubernetes
certificate.yml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: example-certificate
namespace: mtls
labels:
app.kubernetes.io/name: mtls
spec:
isCA: false
secretName: mtls-certs
duration: 9000h
renewBefore: 180h
usages:
- digital signature
- key encipherment
- client auth
privateKey:
algorithm: RSA
encoding: PKCS1
size: 2048
dnsNames:
- "localhost"
- "127.0.0.1"
issuerRef:
name: ca-issuer
kind: ClusterIssuer
group: cert-manager.io
Apply manifest
kubectl apply -f certificate.yml
Result
» kubectl apply -f certificate.yml
certificate.cert-manager.io/example-certificate created
» kubectl get certificates -n mtls
NAME READY SECRET AGE
example-certificate True mtls-certs 34s
» kubectl describe certificate example-certificate -n mtls
Name: example-certificate
Namespace: mtls
Labels: app.kubernetes.io/name=mtls
Annotations: <none>
API Version: cert-manager.io/v1
Kind: Certificate
Metadata:
Creation Timestamp: 2023-04-07T17:26:54Z
Generation: 1
Managed Fields:
API Version: cert-manager.io/v1
Fields Type: FieldsV1
fieldsV1:
f:status:
.:
f:conditions:
.:
k:{"type":"Ready"}:
.:
f:lastTransitionTime:
f:message:
f:observedGeneration:
f:reason:
f:status:
f:type:
f:notAfter:
f:notBefore:
f:renewalTime:
Manager: cert-manager-certificates-readiness
Operation: Update
Subresource: status
Time: 2023-04-07T17:26:54Z
API Version: cert-manager.io/v1
Fields Type: FieldsV1
fieldsV1:
f:metadata:
f:annotations:
.:
f:kubectl.kubernetes.io/last-applied-configuration:
f:labels:
.:
f:app.kubernetes.io/name:
f:spec:
.:
f:dnsNames:
f:duration:
f:isCA:
f:issuerRef:
.:
f:group:
f:kind:
f:name:
f:privateKey:
.:
f:algorithm:
f:encoding:
f:size:
f:renewBefore:
f:secretName:
f:usages:
Manager: kubectl-client-side-apply
Operation: Update
Time: 2023-04-07T17:26:54Z
Resource Version: 52466
UID: ea79b5b7-6ca3-4277-89a9-717e88352364
Spec:
Dns Names:
localhost
127.0.0.1
Duration: 9000h0m0s
Issuer Ref:
Group: cert-manager.io
Kind: ClusterIssuer
Name: ca-issuer
Private Key:
Algorithm: RSA
Encoding: PKCS1
Size: 2048
Renew Before: 180h0m0s
Secret Name: mtls-certs
Usages:
digital signature
key encipherment
client auth
Status:
Conditions:
Last Transition Time: 2023-04-07T17:26:54Z
Message: Certificate is up to date and has not expired
Observed Generation: 1
Reason: Ready
Status: True
Type: Ready
Not After: 2024-04-11T22:03:41Z
Not Before: 2023-04-02T22:03:41Z
Renewal Time: 2024-04-04T10:03:41Z
Events: <none>
» kubectl get secrets -n mtls
NAME TYPE DATA AGE
mtls-certs kubernetes.io/tls 3 4d19h
4. Generated certificate is stored in kubernetes secrets
» kubectl describe secret mtls-certs -n mtls
Name: mtls-certs
Namespace: mtls
Labels: <none>
Annotations: cert-manager.io/alt-names: localhost,127.0.0.1
cert-manager.io/certificate-name: example-certificate
cert-manager.io/common-name:
cert-manager.io/ip-sans:
cert-manager.io/issuer-group: cert-manager.io
cert-manager.io/issuer-kind: ClusterIssuer
cert-manager.io/issuer-name: ca-issuer
cert-manager.io/uri-sans:
Type: kubernetes.io/tls
Data
====
ca.crt: 1253 bytes
tls.crt: 1159 bytes
tls.key: 1675 bytes
GitHub project
All files which I used to generate certificate are stored in github repository.
References
- How to generate self signed certificate
- How to generate CA
- ClusterIssuer vs Issuer
- Base64 encoder
- Certificates generator
Photo by Muhammad Zaqy Al Fattah on Unsplash