smallstep / helm-charts Goto Github PK
View Code? Open in Web Editor NEWHelm packages for Kubernetes
License: Apache License 2.0
Helm packages for Kubernetes
License: Apache License 2.0
Current helm chart renders deployments/pods as running as root. Furthermore capabilities are not dropped.
I see no need for the container to run as root or have special capabilities.
For example add security context to the deployments:
spec:
securityContext:
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
and for each container's securityContext:
securityContext:
capabilities:
drop:
- all
readOnlyRootFilesystem: true
runAsNonRoot: true
The readOnlyRootFilesystem will require mounting of a data volume for the database files. This field may be optional.
Release "certificate-authority-test" does not exist. Installing it now.
Error: unable to build kubernetes objects from release manifest: error validating "": error validating data: [ValidationError(Ingress.spec.rules[0].http.paths[0].backend): unknown field "serviceName" in io.k8s.api.networking.v1.IngressBackend, ValidationError(Ingress.spec.rules[0].http.paths[0].backend): unknown field "servicePort" in io.k8s.api.networking.v1.IngressBackend, ValidationError(Ingress.spec.rules[1].http.paths[0].backend): unknown field "serviceName" in io.k8s.api.networking.v1.IngressBackend, ValidationError(Ingress.spec.rules[1].http.paths[0].backend): unknown field "servicePort" in io.k8s.api.networking.v1.IngressBackend]
serviceName
and servicePort
are not valid attributes of backend
helm-charts/step-certificates/templates/ingress.yaml
Lines 39 to 40 in 8504f80
Refactor ingress template to create a compliant Ingress object.
Example minimal structure:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minimal-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- http:
paths:
- path: /testpath
pathType: Prefix
backend:
service:
name: test
port:
number: 80
Curious if it would be possible to support Azure KeyVault-stored keys. I produced a helm values.yam'
locally, utilizing step ca init --helm
noted here with the --kms=azurekms
flag set, which appears to produce a reasonably valid values.yaml containing the public root & intermediate certs, and confirmed keys were created in kv. I then deployed this to my local cluster.
On container startup, the step-certificates
container errors out with the following:
error reading azurekms:name=INTERMEDIATE-DEV-HELM;vault=kv-*******?version=86489f7b8fa9489b8f3d397350be9656
I imagine this has something to do with how step-certificates
is getting bootstrapped and/or the lack of authentication w/ Azure within that container.
I'm going to poke around more at the implementation on the step-certificates
side of things and see if I can figure things out, but any advice would be appreciated. I'd be happy to contribute docs / implementation for this if it is currently unsupported.
After deploying the server in kubernetes with custom CA, couldn't make it work because of the error below.
Kubernetes 1.20.0
step-certificates: 0.15.15
Deploy the step-certificates helm-chart with inject block with your root CA certs and keys.
Getting an specific error about db not configured.
{"duration":"95.261µs","duration-ns":95261,"fields.time":"2021-06-23T20:08:14Z","level":"info","method":"GET","msg":"","name":"ca","path":"/acme/acme/directory","protocol":"HTTP/1.1","referer":"","remote-address":"192.168.143.76","request-id":"c39p9bh1gp8uen3ofb3g","response":"{\"newNonce\":\"https://tls.glo.helena/acme/acme/new-nonce\",\"newAccount\":\"https://tls.glo.helena/acme/acme/new-account\",\"newOrder\":\"https://tls.glo.helena/acme/acme/new-order\",\"revokeCert\":\"https://tls.glo.helena/acme/acme/revoke-cert\",\"keyChange\":\"https://tls.glo.helena/acme/acme/key-change\"}","size":292,"status":200,"time":"2021-06-23T20:08:14Z","user-agent":"cert-manager/v1.4.0 (clean) golang.org/x/crypto/acme","user-id":""}
2021/06/23 20:08:14 /usr/local/go/src/net/http/server.go:3137: http: panic serving 192.168.143.76:42764: runtime error: invalid memory address or nil pointer dereference
goroutine 26294 [running]:
net/http.(*conn).serve.func1(0xc0001f85a0)
/usr/local/go/src/net/http/server.go:1824 +0x153
panic(0x10a1380, 0x1aae900)
/usr/local/go/src/runtime/panic.go:971 +0x499
github.com/smallstep/certificates/acme/api.(*Handler).addNonce.func1(0x7f9246bb4f98, 0xc000716f20, 0xc00070e900)
/src/acme/api/middleware.go:65 +0x62
github.com/smallstep/certificates/acme/api.(*Handler).lookupProvisioner.func1(0x7f9246bb4f98, 0xc000716f20, 0xc00070e800)
/src/acme/api/middleware.go:308 +0x2a2
github.com/smallstep/certificates/acme/api.(*Handler).baseURLFromRequest.func1(0x7f9246bb4f98, 0xc000716f20, 0xc00070e700)
/src/acme/api/middleware.go:58 +0x17c
net/http.HandlerFunc.ServeHTTP(0xc00029f660, 0x7f9246bb4f98, 0xc000716f20, 0xc00070e700)
/usr/local/go/src/net/http/server.go:2069 +0x44
github.com/go-chi/chi.(*Mux).routeHTTP(0xc00046f320, 0x7f9246bb4f98, 0xc000716f20, 0xc00070e700)
/go/pkg/mod/github.com/go-chi/[email protected]+incompatible/mux.go:425 +0x28b
net/http.HandlerFunc.ServeHTTP(0xc00029f620, 0x7f9246bb4f98, 0xc000716f20, 0xc00070e700)
/usr/local/go/src/net/http/server.go:2069 +0x44
github.com/go-chi/chi.(*Mux).ServeHTTP(0xc00046f320, 0x7f9246bb4f98, 0xc000716f20, 0xc00070e700)
/go/pkg/mod/github.com/go-chi/[email protected]+incompatible/mux.go:70 +0x50c
github.com/go-chi/chi.(*Mux).Mount.func1(0x7f9246bb4f98, 0xc000716f20, 0xc00070e700)
/go/pkg/mod/github.com/go-chi/[email protected]+incompatible/mux.go:292 +0x122
net/http.HandlerFunc.ServeHTTP(0xc000427e60, 0x7f9246bb4f98, 0xc000716f20, 0xc00070e700)
/usr/local/go/src/net/http/server.go:2069 +0x44
github.com/go-chi/chi.(*Mux).routeHTTP(0xc00046f200, 0x7f9246bb4f98, 0xc000716f20, 0xc00070e700)
/go/pkg/mod/github.com/go-chi/[email protected]+incompatible/mux.go:425 +0x28b
net/http.HandlerFunc.ServeHTTP(0xc00029f0f0, 0x7f9246bb4f98, 0xc000716f20, 0xc00070e700)
/usr/local/go/src/net/http/server.go:2069 +0x44
github.com/go-chi/chi.(*Mux).ServeHTTP(0xc00046f200, 0x7f9246bb4f98, 0xc000716f20, 0xc00070e600)
/go/pkg/mod/github.com/go-chi/[email protected]+incompatible/mux.go:82 +0x2d1
github.com/smallstep/certificates/logging.(*LoggerHandler).ServeHTTP(0xc000300bd0, 0x14140a0, 0xc0004e69a0, 0xc00070e600)
/src/logging/handler.go:49 +0xe2
github.com/smallstep/certificates/logging.RequestID.func1.1(0x14140a0, 0xc0004e69a0, 0xc00070e500)
/src/logging/context.go:38 +0x20c
net/http.HandlerFunc.ServeHTTP(0xc000300c00, 0x14140a0, 0xc0004e69a0, 0xc00070e500)
/usr/local/go/src/net/http/server.go:2069 +0x44
net/http.serverHandler.ServeHTTP(0xc0001c4540, 0x14140a0, 0xc0004e69a0, 0xc00070e500)
/usr/local/go/src/net/http/server.go:2887 +0xa3
net/http.(*conn).serve(0xc0001f85a0, 0x14184f8, 0xc0003084c0)
/usr/local/go/src/net/http/server.go:1952 +0x8cd
created by net/http.(*Server).Serve
/usr/local/go/src/net/http/server.go:3013 +0x39b
2021/06/23 20:08:14 /usr/local/go/src/net/http/server.go:3137: http: panic serving 192.168.143.76:42766: runtime error: invalid memory address or nil pointer dereference
goroutine 26260 [running]:
net/http.(*conn).serve.func1(0xc0005a8280)
/usr/local/go/src/net/http/server.go:1824 +0x153
panic(0x10a1380, 0x1aae900)
/usr/local/go/src/runtime/panic.go:971 +0x499
github.com/smallstep/certificates/acme/api.(*Handler).addNonce.func1(0x7f9246bb4f98, 0xc000096c00, 0xc0005ce500)
/src/acme/api/middleware.go:65 +0x62
github.com/smallstep/certificates/acme/api.(*Handler).lookupProvisioner.func1(0x7f9246bb4f98, 0xc000096c00, 0xc0005ce400)
/src/acme/api/middleware.go:308 +0x2a2
github.com/smallstep/certificates/acme/api.(*Handler).baseURLFromRequest.func1(0x7f9246bb4f98, 0xc000096c00, 0xc0005ce300)
/src/acme/api/middleware.go:58 +0x17c
net/http.HandlerFunc.ServeHTTP(0xc00029f660, 0x7f9246bb4f98, 0xc000096c00, 0xc0005ce300)
/usr/local/go/src/net/http/server.go:2069 +0x44
github.com/go-chi/chi.(*Mux).routeHTTP(0xc00046f320, 0x7f9246bb4f98, 0xc000096c00, 0xc0005ce300)
/go/pkg/mod/github.com/go-chi/[email protected]+incompatible/mux.go:425 +0x28b
net/http.HandlerFunc.ServeHTTP(0xc00029f620, 0x7f9246bb4f98, 0xc000096c00, 0xc0005ce300)
/usr/local/go/src/net/http/server.go:2069 +0x44
github.com/go-chi/chi.(*Mux).ServeHTTP(0xc00046f320, 0x7f9246bb4f98, 0xc000096c00, 0xc0005ce300)
/go/pkg/mod/github.com/go-chi/[email protected]+incompatible/mux.go:70 +0x50c
github.com/go-chi/chi.(*Mux).Mount.func1(0x7f9246bb4f98, 0xc000096c00, 0xc0005ce300)
/go/pkg/mod/github.com/go-chi/[email protected]+incompatible/mux.go:292 +0x122
net/http.HandlerFunc.ServeHTTP(0xc000427e60, 0x7f9246bb4f98, 0xc000096c00, 0xc0005ce300)
/usr/local/go/src/net/http/server.go:2069 +0x44
github.com/go-chi/chi.(*Mux).routeHTTP(0xc00046f200, 0x7f9246bb4f98, 0xc000096c00, 0xc0005ce300)
/go/pkg/mod/github.com/go-chi/[email protected]+incompatible/mux.go:425 +0x28b
net/http.HandlerFunc.ServeHTTP(0xc00029f0f0, 0x7f9246bb4f98, 0xc000096c00, 0xc0005ce300)
/usr/local/go/src/net/http/server.go:2069 +0x44
github.com/go-chi/chi.(*Mux).ServeHTTP(0xc00046f200, 0x7f9246bb4f98, 0xc000096c00, 0xc0005ce200)
/go/pkg/mod/github.com/go-chi/[email protected]+incompatible/mux.go:82 +0x2d1
github.com/smallstep/certificates/logging.(*LoggerHandler).ServeHTTP(0xc000300bd0, 0x14140a0, 0xc000586700, 0xc0005ce200)
/src/logging/handler.go:49 +0xe2
github.com/smallstep/certificates/logging.RequestID.func1.1(0x14140a0, 0xc000586700, 0xc0005ce100)
/src/logging/context.go:38 +0x20c
net/http.HandlerFunc.ServeHTTP(0xc000300c00, 0x14140a0, 0xc000586700, 0xc0005ce100)
/usr/local/go/src/net/http/server.go:2069 +0x44
net/http.serverHandler.ServeHTTP(0xc0001c4540, 0x14140a0, 0xc000586700, 0xc0005ce100)
/usr/local/go/src/net/http/server.go:2887 +0xa3
net/http.(*conn).serve(0xc0005a8280, 0x14184f8, 0xc0000307c0)
/usr/local/go/src/net/http/server.go:1952 +0x8cd
created by net/http.(*Server).Serve
/usr/local/go/src/net/http/server.go:3013 +0x39b
2021/06/23 20:08:14 /usr/local/go/src/net/http/server.go:3137: http: panic serving 192.168.143.76:42768: runtime error: invalid memory address or nil pointer dereference
goroutine 26305 [running]:
net/http.(*conn).serve.func1(0xc0002db900)
/usr/local/go/src/net/http/server.go:1824 +0x153
panic(0x10a1380, 0x1aae900)
/usr/local/go/src/runtime/panic.go:971 +0x499
github.com/smallstep/certificates/acme/api.(*Handler).addNonce.func1(0x7f9246bb4f98, 0xc000096da0, 0xc0005ce900)
/src/acme/api/middleware.go:65 +0x62
github.com/smallstep/certificates/acme/api.(*Handler).lookupProvisioner.func1(0x7f9246bb4f98, 0xc000096da0, 0xc0005ce800)
/src/acme/api/middleware.go:308 +0x2a2
github.com/smallstep/certificates/acme/api.(*Handler).baseURLFromRequest.func1(0x7f9246bb4f98, 0xc000096da0, 0xc0005ce700)
/src/acme/api/middleware.go:58 +0x17c
net/http.HandlerFunc.ServeHTTP(0xc00029f660, 0x7f9246bb4f98, 0xc000096da0, 0xc0005ce700)
/usr/local/go/src/net/http/server.go:2069 +0x44
github.com/go-chi/chi.(*Mux).routeHTTP(0xc00046f320, 0x7f9246bb4f98, 0xc000096da0, 0xc0005ce700)
/go/pkg/mod/github.com/go-chi/[email protected]+incompatible/mux.go:425 +0x28b
net/http.HandlerFunc.ServeHTTP(0xc00029f620, 0x7f9246bb4f98, 0xc000096da0, 0xc0005ce700)
/usr/local/go/src/net/http/server.go:2069 +0x44
github.com/go-chi/chi.(*Mux).ServeHTTP(0xc00046f320, 0x7f9246bb4f98, 0xc000096da0, 0xc0005ce700)
/go/pkg/mod/github.com/go-chi/[email protected]+incompatible/mux.go:70 +0x50c
github.com/go-chi/chi.(*Mux).Mount.func1(0x7f9246bb4f98, 0xc000096da0, 0xc0005ce700)
/go/pkg/mod/github.com/go-chi/[email protected]+incompatible/mux.go:292 +0x122
net/http.HandlerFunc.ServeHTTP(0xc000427e60, 0x7f9246bb4f98, 0xc000096da0, 0xc0005ce700)
/usr/local/go/src/net/http/server.go:2069 +0x44
github.com/go-chi/chi.(*Mux).routeHTTP(0xc00046f200, 0x7f9246bb4f98, 0xc000096da0, 0xc0005ce700)
/go/pkg/mod/github.com/go-chi/[email protected]+incompatible/mux.go:425 +0x28b
net/http.HandlerFunc.ServeHTTP(0xc00029f0f0, 0x7f9246bb4f98, 0xc000096da0, 0xc0005ce700)
/usr/local/go/src/net/http/server.go:2069 +0x44
github.com/go-chi/chi.(*Mux).ServeHTTP(0xc00046f200, 0x7f9246bb4f98, 0xc000096da0, 0xc0005ce600)
/go/pkg/mod/github.com/go-chi/[email protected]+incompatible/mux.go:82 +0x2d1
github.com/smallstep/certificates/logging.(*LoggerHandler).ServeHTTP(0xc000300bd0, 0x14140a0, 0xc00081c000, 0xc0005ce600)
/src/logging/handler.go:49 +0xe2
github.com/smallstep/certificates/logging.RequestID.func1.1(0x14140a0, 0xc00081c000, 0xc000814000)
/src/logging/context.go:38 +0x20c
net/http.HandlerFunc.ServeHTTP(0xc000300c00, 0x14140a0, 0xc00081c000, 0xc000814000)
/usr/local/go/src/net/http/server.go:2069 +0x44
net/http.serverHandler.ServeHTTP(0xc0001c4540, 0x14140a0, 0xc00081c000, 0xc000814000)
/usr/local/go/src/net/http/server.go:2887 +0xa3
net/http.(*conn).serve(0xc0002db900, 0x14184f8, 0xc000810000)
/usr/local/go/src/net/http/server.go:1952 +0x8cd
created by net/http.(*Server).Serve
/usr/local/go/src/net/http/server.go:3013 +0x39b
Already know what is the problem, in the helm chart is missing the db config, I created a PR to the helm chart adding this.
When one specifies a custom value for ca.dns
in the values, it results in a cert that doesn't work inside the cluster or when running step ca
inside the container. This is due to the SAN not containing all the right dns/ip entries:
error getting the provisioners: client GET https://internalca-step-certificates.default.svc.cluster.local/provisioners?limit=100 failed: Get "https://internalca-step-certificates.default.svc.cluster.local/provisioners?limit=100": x509: certificate is valid for ca.example.com, not internalca-step-certificates.default.svc.cluster.local
Suggest changing relevant _helpers.tpl:
helm-charts/step-certificates/templates/_helpers.tpl
Lines 58 to 64 in 6b75678
Changing line 62 to:
{{- printf "%s,%s.%s.svc.cluster.local,127.0.0.1" .Values.ca.dns (include "step-certificates.fullname" .) .Release.Namespace -}}
Any issues if I submit a PR?
Alternative is to document issue and have user to construct full SAN string manually.
Thanks!
Edit: Full disclosure, as mentioned before, I'm brand new to working with helm charts, so I don't know if that's the right syntax, but its what "smelled right".
In step-certificate statefulSet declaration, there is a allowPrivilegeEscalation declared in the securityContext on pod level.
This is invalid, this property is invalid in a podSecurityContext object : https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.16/#podsecuritycontext-v1-core
Under Helm 3, this prevents the chart from being deployed.
I would like to see an option to statically declare a NodePort when setting service.type = NodePort
Bug: Omitting ca.kms.type
in step-certificates
chart causes bootstrapping to fail
v1.22.7+k3s1
v2.3.3+07ac038
v3.8.0+gd141386
step-certificates
Chart: 1.18.1
Omitting ca.kms.type
from the values.yaml
file for the step-certificates
chart causes the following lines to be generated in the step-certificates-bootstrap
ConfigMap:
step ca init \
--name "Smallstep" \
--dns "ca.k3s.lan" \
--address ":9000" \
--provisioner "admin" \
--with-ca-url "https://step-certificates.default.svc.cluster.local" \
--password-file "$TMP_CA_PASSWORD" \
--provisioner-password-file "$TMP_CA_PROVISIONER_PASSWORD"
The surplus newline (caused by not specifying ca.kms.type
) between --password-file
and --provisioner-password-file
appears to cause --provisioner-password-file
to not be passed to step ca init
.
Instead, the following error is presented at the end of the step-certificates
Job execution: /home/step/bootstrap/bootstrap.sh: line 59: --provisioner-password-file: not found
which causes the job to generate the following event: BackoffLimitExceeded: Job has reached the specified backoff limit
No surplus newline between --password-file
and --provisioner-password-file
for the step ca init
command & bootstrapping successful
Surplus newline between --password-file
and --provisioner-password-file
for the step ca init
command & bootstrapping unsuccessful
Bootstrapping appears to be successful, however the /home/step/bootstrap/bootstrap.sh: line 59: --provisioner-password-file: not found
error makes Kubernetes think that the job failed
The values files allows to configure the cluster domain name via .Values.autocert.clusterDomain.
However, there is still a cluster.local hardcoded in _helpers.tpl :
This prevents autocert from starting if the cluster name has been customized
Hi, I've deployed the CA to a k8s cluster without LoadBalancer/Ingress
Is there a way to connect to the CA via kube port-forward
locally? I repeatedly higgintg unexpected EOF
or tcp: x509: certificate is valid for <release-name>.<namespace>.svc.cluster.local, not localhost
I'm using step-certificates
chart to deploy Smallstep CA to k8s and use it to issue certificates using ACME protocol. Once deployed, I can find ACME directory listing at the address: https://ca.example.com/acme/acme/directory
and the ACME endpoints there look like this:
{
"newNonce": "https://ca.example.com:9000/acme/acme/new-nonce",
"newAccount": "https://ca.example.com:9000/acme/acme/new-account",
"newOrder": "https://ca.example.com:9000/acme/acme/new-order",
"revokeCert": "https://ca.example.com:9000/acme/acme/revoke-cert",
"keyChange": "https://ca.example.com:9000/acme/acme/key-change"
}
As you can see the URLs have the port number :9000
. This causes a connection problem, since clients can't access this service at port ca.example.com:9000
on k8s Ingress. Chart sets ingress to point to 443
port of the smallstep Service object, and Service is set to map 443
to 9000
(https://github.com/smallstep/helm-charts/blob/master/step-certificates/values.yaml#L25-L28)
I have tried changing ca.address
(https://github.com/smallstep/helm-charts/blob/master/step-certificates/values.yaml#L35) to :443
, but with this value Pod creation fails, since it is unable to bind to port 443
because step
user doesn't have permission to bind to ports less than 1024. Solution would be to add CAP_NET_BIND_SERVICE
but I would like to avoid that.
Is there an option in Chart to control how ACME directory endpoints/links are constructed?
My ca.json
looks like this:
"root": "/home/step/certs/root_ca.crt",
"federatedRoots": [],
"crt": "/home/step/certs/intermediate_ca.crt",
"key": "/home/step/secrets/intermediate_ca_key",
"address": ":9000",
"dnsNames": [
"ca.example.com"
],
"logger": {
"format": "text"
},
"db": {
"type": "badger",
"dataSource": "/home/step/db"
},
"authority": {
"provisioners": [
{
"type": "jwk",
"name": "admin",
"key": {
"deliberatly": "removed"
},
"encryptedKey": "secret"
},
{
"type": "ACME",
"name": "acme"
}
]
},
"tls": {
"cipherSuites": [
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305",
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"
],
"minVersion": 1.2,
"maxVersion": 1.2,
"renegotiation": false
}
}
Currently if we enable inject when using the helm chart for step-certificates, I'm forced to include SSH keys. I don't need to use SSH keys in my environment, so can this be changed so that we do not need them with using inject?
In the docs, it indicates that the ingress.hosts
component of values is an array of "Step CA ingress hostNAMES (YAML)". This would lead someone to believe it's just hostnames.
If you just attempt to use hostnames, it'll report during helm install that it can't serialize since it's not an object. So I went down the road of providing an object.
hosts:
- host: ca.mydomain.com
http:
paths:
path: /
If I try the above or even the full configuration, I always get back error validating data: ValidationError(Ingress.spec.rules[0].http): missing required field "paths" in io.k8s.api.networking.v1beta1.HTTPIngressRuleValue
Is there something simple I'm missing? It might be helpful to provide a sample for ingress configuration. I already have an ingress controller bound to my AWS certificates etc I've set in the annotations, but I can't get it to depoy
The version of the step-cli used in the Docker Hub version of the step-ca-bootstrap image is so old that it doesn't understand ACME provisioner. Could do with a refresh ;)
(On a related note, I've created a PR which allows for a post-init hook script to be executed - my use case is to add an ACME provider upon installation:
#15
... for that to work I had to locally re-build the step-ca-bootstrap image so that it understood what ACME is).
Currently, it seems impossible to add provisioners during bootstrapping and, because the ca.json
is stored inside a configmap, we cannot add them easily by running step ca provisionner add
inside the pod.
I think it could be great if we can manage theses providers directly through your HELM chart values. I have seen this issue about adding a CRUD API for provisionner and, for me, managing them through HELM is not incompatible with issue because it allow us to manage provisioners "as code" (and can be updated when the API will be available).
About the implementation, I think it wouldn't be difficult and can be managed using HELM hooks, kubectl to update the configmaps and to restart all step-certificates
pods.
What do you think about that ?
Thanks to @opencommits to pointing this out.
Should be updated to use:
ssh_user_ca_key.pub: {{ .Values.inject.certificates.ssh_user_ca }}
It is unclear from the documentation what the preferred way to make post-deployment configuration changes to the CA is. When using the "inject" method it appears that editing the values and "upgrading" the Helm chart doesn't result in the updated configuration being applied.
Investigating it seems that:
Deleting the pod to force it to restart picks up the new configuration. Ideally, editing the Helm values and upgrading the chart would result in the updated configuration being "live".
Description
Startup fails with "bad flag syntax: ---disable-approval-check" error when deploying "0.6.0" version of step-issuer chart with "deployment.args.disableApprovalCheck" set to true.
Possible solution
Remove third "-" in:
I think you could accomplish what you would like with the bootstrapping by using a pre-install Helm hook.
Perhaps even better may be a before-upgrade hook that inspects and ensures there is a secret created if someone deletes it or similar for robustness though.
If you go for helm hooks, I suggest using the before-hook-creation
deletion policy that can be applied with this kind of annotation:
"helm.sh/hook-delete-policy": before-hook-creation"
Hi, I have opened MR #10
It should properly use value from Values before including CluterRole and ClusterRoleBinding
Integrate https://github.com/helm/chart-releaser-action to automatically create the helm repo, instead of doing it manually.
Instead of just helm install step-certificates
.
Hi guys,
I want to add this step in the helm chart: "step ca provisioner add acme --type ACME".
Is it simply adding at the field: postInitHook: "step ca provisioner add acme --type ACME"?
Ater deployment I see contents that the ACME protocol is added but with not many info, other then:
"type": "ACME"
"name": "acme-smallstep"
Is this correct?
It seems that there is some info missing.
https://github.com/smallstep/certificates/blob/master/docs/provisioners.md
Kind regards,
Dinant
used links:
helm-charts/step-certificates/templates/configmaps.yaml
Lines 115 to 117 in 6b75678
Deploying step-ca with ca.json from injected values, the "y" value for a JWK provisioner is missing in the rendered chart
Set inject.enabled: true in values.yaml and deploy with helm.
Sample config:
inject:
enabled: true
config:
files:
ca.json:
root: /home/step/certs/root_ca.crt
federateRoots: []
crt: /home/step/certs/intermediate_ca.crt
key: /home/step/secrets/intermediate_ca_key
address: 0.0.0.0:9000
dnsNames:
- ca.example.lan
- myexampleca.ca.svc.cluster.local
- 127.0.0.1
logger:
format: json
db:
type: mysql
dataSource: stepca:...snip...@tcp(mysql.mysql.svc.cluster.local:3306)/
database: stepca
authority:
claims:
minTLSCertDuration: 5m
maxTLSCertDuration: 8760h
defaultTLSCertDuration: 2160h
disableRenewal: false
minHostSSHCertDuration: 5m
maxHostSSHCertDuration: 1680h
defaultHostSSHCertDuration: 720h
minUserSSHCertDuration: 5m
maxUserSSHCertDuration: 24h
defaultUserSSHCertDuration: 24h
provisioners:
- type: ACME
name: acme
forceCN: true
claims: {}
- type: JWK
name: [email protected]
key:
use: "sig"
kty: "EC"
kid: "...snip..."
crv: "P-256"
alg: "ES256"
x: "...snip..."
y: "...snip..."
encryptedKey: "...snip..."
claims:
enableSSHCA: true
disableRenewal: false
allowRenewalAfterExpiry: false
options:
x509: {}
ssh: {}
tls:
cipherSuites:
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_AES_128_GCM_SHA256
minVersion: 1.2
maxVersion: 1.3
renegotiation: false
defaults.json:
ca-url: https://myexampleca.ca.svc.cluster.local
ca-config: /home/step/config/ca.json
fingerprint: fingerprint
root: /home/step/certs/root_ca.crt
templates:
x509_leaf.tpl: |
{
"subject": {{ toJson .Subject }},
"sans": {{ toJson .SANs }},
{{- if typeIs "*rsa.PublicKey" .Insecure.CR.PublicKey }}
"keyUsage": ["keyEncipherment", "digitalSignature"],
{{- else }}
"keyUsage": ["digitalSignature"],
{{- end }}
"extKeyUsage": ["serverAuth", "clientAuth"]
}
ssh.tpl: |
{
"type": {{ toJson .Type }},
"keyId": {{ toJson .KeyID }},
"principals": {{ toJson .Principals }},
"extensions": {{ toJson .Extensions }},
"criticalOptions": {{ toJson .CriticalOptions }}
}
JWK provisioner should be configured correctly.
the configmap created doesn't have the "y" value.
adding the missing key manually after the configmap is created allow step-ca pod to start
In my use case, I'm managing step-certificates through ArgoCD, so I would want to avoid having to connect to the cluster to restart step-certificates pod on a config change. For it, I'm using reloader, which needs to have an annotation to allow a pod to restart on a secret or a configmap change. So the need to be able to set annotations from the values file.
step-certificates cant be setup in airgapped enviroments as the busybox Images are hardcoded
helm-charts/step-certificates/templates/tests/test-connection.yaml
Lines 10 to 14 in e09b6ed
helm-charts/step-certificates/templates/ca.yaml
Lines 24 to 27 in e09b6ed
The helm chart does not provide the capability to configure a registration authority for the Smallstep Certificate Manager service
Need support for
--issuer-password-file
to provide a password file when starting up the CA as a registration authority.inject.secrets
to specify the certificate_issuer.password
inject.secrets
to specify the certificate_issuer.key
in PEM format.
inject.certificates
to specify the certificate_issuer_certificate
in PEM format.
If you K8s is completely airgapped step-issuer is not able to start because the image of the kube-rbac-proxy is hardcoded in templates and you cannot override the image repository to a private container-registry.
There doesn't seem to be any way to have the Helm installation CA able to do ssh certs.
Using microk8s I'm able to install it, but get this result trying to create an ssh host cert:
➜ ~ step ssh certificate --host `hostname` ssh_host_ecdsa_key
✔ Provisioner: admin (JWK) [kid: yldB0QKmseHyvSCUwfmU87iKkp4GY-q9UeOB008ILwY]
✔ Please enter the password to decrypt the provisioner key: ��������������������������������
✔ CA: https://127.0.0.1:30537
Not Implemented
Is there a workaround to connect to the CA and do a fresh step ca init
?
After going to instal step-certificates helm chart with a member of our community we've identified a few things that we can improve:
,
as \,
in ca.dns if multiple SANs are used.When trying to deploy step-certificates
helm with Inject enabled, I get the following error:
Error opening database of Type badger with source /home/step/db: error opening Badger database: manifest has unsupported version: 7 (we support 4).
Please see https://github.com/dgraph-io/badger/blob/master/README.md#i-see-manifest-has-unsupported-version-x-we-support-y-error on how to fix this.
If I leave Inject disabled I don't get the error.
Here is my values.yaml:
affinity: {}
autocert:
enabled: false
bootstrap:
configmaps: true
enabled: true
image:
pullPolicy: IfNotPresent
repository: cr.step.sm/smallstep/step-ca-bootstrap
tag: latest
secrets: true
ca:
address: ':9000'
bootstrap:
postInitHook: ''
db:
accessModes:
- ReadWriteOnce
enabled: true
persistent: true
size: 10Gi
storageClass: nfsv3
dns: null
name: Step Certificates
password: null
provisioner:
name: admin
password: null
runAsRoot: false
url: null
fullnameOverride: ''
image:
initContainerRepository: 'busybox:latest'
pullPolicy: IfNotPresent
repository: cr.step.sm/smallstep/step-ca
tag: ''
ingress:
annotations: {}
enabled: false
hosts: []
tls: []
inject:
certificates:
certificate_issuer: ''
intermediate_ca: |
<snipped>
root_ca: |
<snipped>
ssh_host_ca: ''
ssh_user_ca: ''
config:
files:
ca.json:
address: '0.0.0.0:9000'
authority:
claims:
defaultHostSSHCertDuration: 720h
defaultTLSCertDuration: 24h
defaultUserSSHCertDuration: 24h
disableRenewal: false
maxHostSSHCertDuration: 1680h
maxTLSCertDuration: 24h
maxUserSSHCertDuration: 24h
minHostSSHCertDuration: 5m
minTLSCertDuration: 5m
minUserSSHCertDuration: 5m
provisioners:
- claims: {}
forceCN: false
name: devtest
type: ACME
crt: /home/step/certs/intermediate_ca.crt
db:
dataSource: /home/step/db
type: badger
badgerFileLoadingMode: MemoryMap
dnsNames:
- step-ca.example.domain.com
- step-ca-dev.example.domain.com
- step-ca.step-ca.svc.cluster.local
- 127.0.0.1
federateRoots: []
key: /home/step/secrets/intermediate_ca_key
logger:
format: json
root: /home/step/certs/root_ca.crt
tls:
cipherSuites:
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_AES_128_GCM_SHA256
maxVersion: 1.3
minVersion: 1.2
renegotiation: false
defaults.json:
ca-config: /home/step/config/ca.json
ca-url: 'https://step-ca.example.domain.com:9000'
fingerprint: <snipped>
root: /home/step/certs/root_ca.crtt
templates:
ssh.tpl: |
{
"type": {{ toJson .Type }},
"keyId": {{ toJson .KeyID }},
"principals": {{ toJson .Principals }},
"extensions": {{ toJson .Extensions }},
"criticalOptions": {{ toJson .CriticalOptions }}
}
x509_leaf.tpl: |
{
"subject": {{ toJson .Subject }},
"sans": {{ toJson .SANs }},
{{- if typeIs "*rsa.PublicKey" .Insecure.CR.PublicKey }}
"keyUsage": ["keyEncipherment", "digitalSignature"],
{{- else }}
"keyUsage": ["digitalSignature"],
{{- end }}
"extKeyUsage": ["serverAuth", "clientAuth"]
}
enabled: true
secrets:
ca_password: <snipped>
certificate_issuer:
enabled: false
key: ''
password: ''
provisioner_password: <snipped>
ssh:
enabled: false
host_ca_key: ''
user_ca_key: ''
x509:
enabled: true
intermediate_ca_key: |
<snipped>
root_ca_key: ''
kind: StatefulSet
linkedca:
secretKeyRef:
key: null
name: null
token: null
nameOverride: ''
nodeSelector: {}
replicaCount: 1
resources: {}
service:
nodePort: ''
port: 443
targetPort: 9000
type: ClusterIP
tolerations: []
Using chart versionv0.17.2
$kubectl version
Client Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.1", GitCommit:"632ed300f2c34f6d6d15ca4cef3d3c7073412212", GitTreeState:"clean", BuildDate:"2021-08-19T15:45:37Z", GoVersion:"go1.16.7", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"21", GitVersion:"v1.21.4+rke2r2", GitCommit:"3cce4a82b44f032d0cd1a1790e6d2f5a55d20aae", GitTreeState:"clean", BuildDate:"2021-08-29T22:29:54Z", GoVersion:"go1.16.6b7", Compiler:"gc", Platform:"linux/amd64"}
The persistent volume is an NFSv3 volume provisioned by https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner
I've effectively run out of ideas, as running without Inject
enabled, step-certificates
starts as expected.
This service annotation has a typo - should be .Values.service.port
(as defined here):
apiVersion: v1
kind: Service
metadata:
name: "{{ template "step-issuer.fullname" . }}"
namespace: {{ .Release.Namespace }}
annotations:
prometheus.io/port: "{{ .Values.service.ports }}"
Additionally, the defined port is incorrect - by default, the manager metrics endpoint is 8080
:
- image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
name: manager
args: [
"--metrics-addr=127.0.0.1:8080",
Otherwise kube-rbac-proxy
may experience errors like this:
2022/09/29 04:50:52 http: TLS handshake error from x.x.x.x:57116: remote error: tls: bad certificate
This can be reproduced by trying to scrape the metrics endpoint from any Prometheus server (i.e. cost-analyzer).
kube-rbac-proxy
should startup and show no errors; Prometheus should be able to scrape the step-issuer metrics endpoint.
kube-rbac-proxy
may experience errors like this:
2022/09/29 04:50:52 http: TLS handshake error from x.x.x.x:57116: remote error: tls: bad certificate
We can add a new Helm value specifically for the Prometheus scrape port so that the Service annotations are correct and the metrics endpoint is properly exposed.
imagePullPolicy
is not present in step-issuer
templates despite being defined in .Values.image.pullPolicy
N/A
N/A
N/A
N/A
The Dockerfile has hardcoded download to adm64 kubectl executable:
A check on the architecture could maybe be implemented to download the correct executable.
Furthermore, the base image should be updated to step-issuer:0.15.0 to support arm
It wasn't obvious that the answer you provide to What IP and port will your new CA bind to?
when running step ca init --helm
must match the value provided for service.targetPort
and their defaults differ (the former defaults to :443
and the latter defaults to 9000
).
In my case, I need to set extra environment variables with Azure credentials to avoid attaching certain roles to the whole Kubernetes node. Also one might need to set labels, annotations (as in #83), provide extra arguments to the binary, mount extra volumes etc.
Usually, Helm charts provide a way to inject these using values, for example see traefik, nginx charts.
It would be great if step-certificates chart provided a way to manipulate pod template without the need to fork and modify the chart.
When deploying this Helm chart on k8s v1.21 following warning is shown.
W0728 10:09:32.586335 58397 warnings.go:70] networking.k8s.io/v1beta1 Ingress is deprecated in v1.19+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
W0728 10:09:33.108795 58397 warnings.go:70] networking.k8s.io/v1beta1 Ingress is deprecated in v1.19+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress
To continue support on k8s v1.22 we need to update the ingress from networking.k8s.io/v1beta
to the networking.k8s.io/v1
api.
To continue supporting older k8s versions we can therefore use a conditional statement in the ingress definition to do the following:
>= v1.19
» use networking.k8s.io/v1
< v1.19
» use networking.k8s.io/v1beta
As far I can see this only requires a change in the ingress definition, the values file probably just needs some documentation explaining when to use what format.
Will be opening a PR with some minor documentation updates I noticed when getting things setup:
stepIssuer.created
stepIssuer.caBundler
base64
output, producing a multi-line block, which isn't compatible with this chart)Add support for specifying the ingress class of the ingress.
Right now this can only be specified via the kubernetes.io/ingress.class
annotation that has been deprecated since Kubernetes 1.18.
It would be preferrable to have a ingress class field in the ingress that renders either as annotation or as spec.ingressClassname
.
Chart uses default ingress. If the cluster does not define a default ingress or the annotation will be unsupported by ingress-controllers specification ot the ingress will fail.
The merge of the configuration injection pull request is not published to the helm chart repository.
Bumping chart version to deploy changes.
When an upgrade occurs the ClusterRole and ClusterRoleBinding for autocert are removed. They should still be present to allow autocert to create secrets.
Hey, first off, awesome work! Thank you all for all your hard work!
I'm brand new to helm/kube. If this is a PEBKAC issue, please point me in the right direction and feel free to close the ticket.
I've gotten step-ca up and running in my k3s cluster, got ingress working through my traefik controller. Dope.
What I cant seem to figure out is how to add provisioners (in this case acme
). Obviously I get the default JWK
provisioner, but I can't seem to figure out how to add more. Or for that matter, make any configurations that would normally be done using the cli after the helm install
completes.
I've been roughly following along the tutorial on smallstep's blog.
values.yaml
with regards to provisioners (other than name
and password
).step ca provisioner add acme --type ACME
config
filesystem is RO, also this doesn't feel like the right answer anyways.We strongly recommend using the
step ca provisioner add [...]
utility to generate provisioners in your ca.json configuration. We often encode fields differently in the JSON than you might expect. And you can always modify the JSON configuration manually after using the utility.
I'm left with modifying the helm chart manually prior to deployment. And if that's the route I need to go, so be it. Though, even this seems like the wrong answer; what if later I decided I need another provisioner? Do I re-deploy the app from scratch? Am I stuck maintaining a fork of the helm-charts repo just so I can configure the application?
If there's something I'm missing, or there's a better way. Please let me know. Thanks!
Backup/restore of the Badger database to keep the ACME registrations when re-installing step-certificates in Kubernetes.
Secondary objective: support migration of database from Badger v1.6 to v2 by backing up existing v1.6 database and restore to v2 database.
Currently it is not easy to get access to the Badger database inside the step-certificates pod. The step-certificate container must be stopped to be able to take a backup as Badger does not support backup of a database in use.
This could be done by stopping the pod and mounting the PVC into another pod, however, that is cumbersome in a GitOps setup.
Add an init-container that takes a backup of the database. Then it is possible to extract the backup file by using kubectl cp
or VolumeSnapshot
.
A Kubernetes job or similar cronjob outside of the cluster can then request the pod to restart daily and copy the backup file from the new pod. Note, however, that part will not be part of this solution.
Changes required:
Helm values, where badger can be enabled.
ca:
db:
backupRestore:
badger:
enabled: true
image:
backupRestoreRepository: step-certificates-badger:latest
where we need to find a proper name for the image or embed the content into step-ca cli image.
ca.db.type
in Helm chart to select proper version of badger.I have a working setup (without encryption and multi-version support) and I can create a pull-request.
Enhance Helm chart to support insert of any init-container configuration from values into the Statefulset template.
Thereby the backup/restore will not be part of this Helm chart and left to the user to configure.
Here's my ideal world:
Currently I am using ansible to automate my deployments to Kubernetes and I am getting to the point where the bootstrap approach just isn't flexible enough for me.
I am going to try and contribute some tweaks that enable power users to control their configuration without needing to use the bootstrap in a series of PRs.
The helm chart launches a bootstrap job that ends up creating configmaps for sensitive material. It is a best practice in k8s to use secrets for sensitive material over configmaps.
Hi
When I triying step ca provisioner add iamss --type ACME
in the pod to create new provisioner, show me
"error opening /home/step/config/ca.json: open /home/step/config/ca.json: read-only file system"
Cannot move secrets outside chart values and provision them in separately before chart install.
Even after setting bootstrap:secrets:false chart installation fails with -
Error: rendered manifests contain a resource that already exists. Unable to continue with install: existing resource conflict: namespace: step-certificates, name: step-certificates-ca-password, existing_kind: /v1, Kind=Secret, new_kind: /v1, Kind=Secret
The step-ca chart reference a sub-chart but the dependencies isn't defined in the chart.
autocert:
enabled: false
Will only works if you checked out the chart on your local computer or if you have package the chart yourself. Something like this should be in the chart.yaml.
# Chart.yaml
dependencies:
- name: smallstep/autocert
version: "1.12.3"
repository: "https://smallstep.github.io/helm-charts"
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.