k8s_name=kind-$(date +"%y%m%d%H%M")
cat <<EOF | kind create cluster --config -
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: ${k8s_name}
nodes:
- role: control-plane
EOF
k8s_name_tlspk=$(tr "-" "_" <<< ${k8s_name})
jsctl clusters connect ${k8s_name_tlspk}
jsctl operator deploy --auto-registry-credentials
sleep 2 && kubectl -n jetstack-secure wait --for=condition=Available=True --all deployments --timeout=-1s
sleep 5 && jsctl operator installations apply --auto-registry-credentials --cert-manager-replicas 1
sleep 2 && kubectl -n jetstack-secure wait --for=condition=Available=True --all deployments --timeout=-1s
helm repo add smallstep https://smallstep.github.io/helm-charts && helm repo update
helm -n smallstep install step-certificates smallstep/step-certificates --create-namespace --wait
helm -n smallstep install step-issuer smallstep/step-issuer --create-namespace --wait
The approver-policy component is mandated in TLSPK but, by default, it is only able to support issuers from the cert-manager.io
and jetstack.io
apiGroups.
All external issuers are ignored since they fall outside this condition (e.g. certmanager.step.sm
).
This is a permissions issue which is raised here).
In the meantime you can address this limitation with the following tactical fix.
Open the manifest, in whatever EDITOR you have configured, as follows.
kubectl edit clusterrole js-operator-approver-policy-permissions
... then add the following element to the list of rules:
rules:
- apiGroups:
- certmanager.step.sm
resourceNames:
- stepissuers.certmanager.step.sm/*
- stepclusterissuers.certmanager.step.sm/*
resources:
- signers
verbs:
- approve
Saving the file will apply those changes.
ca_bundle=$(kubectl -n smallstep get configmaps/step-certificates-certs -o jsonpath="{.data['root_ca\.crt']}" | base64 | tr -d \\n)
kid=$(kubectl -n smallstep get configmaps/step-certificates-config -o jsonpath="{.data['ca\.json']}"| jq '.authority.provisioners[0].key.kid' --raw-output)
cat << EOF | kubectl apply -f -
apiVersion: certmanager.step.sm/v1beta1
kind: StepClusterIssuer
metadata:
name: step-issuer
spec:
url: https://step-certificates.smallstep.svc.cluster.local
caBundle: ${ca_bundle}
provisioner:
name: admin
kid: ${kid}
passwordRef:
name: step-certificates-provisioner-password
namespace: smallstep
key: password
EOF
cat << EOF | kubectl apply -f -
apiVersion: policy.cert-manager.io/v1alpha1
kind: CertificateRequestPolicy
metadata:
name: certificate-request-policy-smallstep
spec:
allowed:
commonName:
value: '*'
dnsNames:
values:
- '*'
selector:
issuerRef:
group: certmanager.step.sm
kind: StepClusterIssuer
name: step-issuer
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: certificate-request-policy-smallstep:rbac
rules:
- apiGroups: ["policy.cert-manager.io"]
resources: ["certificaterequestpolicies"]
verbs: ["use"]
resourceNames: ["certificate-request-policy-smallstep"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: certificate-request-policy-tlspc:rbac
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: certificate-request-policy-smallstep:rbac
subjects:
- kind: Group
name: system:authenticated
apiGroup: rbac.authorization.k8s.io
EOF
kubectl create namespace tests
cat << EOF | kubectl -n tests apply -f -
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: www.smallstep-demo.com
spec:
secretName: www-smallstep-demo-com-tls
commonName: www.smallstep-demo.com
dnsNames:
- www.smallstep-demo.com
issuerRef:
group: certmanager.step.sm
kind: StepClusterIssuer
name: step-issuer
EOF
TODO need to confirm what is actually produced, since you get tls.key
but no tls.crt
in the secret. Also, the secretName: www-smallstep-demo-com-tls
directive is not observed (secret name is suffixed with randon chars).
kubectl -n tests describe $(kubectl -n tests get secret -oname | head -1)
kind delete cluster --name ${k8s_name}
jsctl clusters delete ${k8s_name_tlspk} --force
Remember to mop up dangling service account for the cluster in TLSPK