Skip to content

Add a backend that requests Cert-Manager certificates #482

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 30 commits into from
Sep 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
99b2e30
Initial prototype for cert-manager integration
nightkr Jul 23, 2024
e690d25
Use PVC name as cert-manager secret, rather than pod name
nightkr Jul 23, 2024
9a114da
Move cert-manager integration into a separate backend
nightkr Jul 23, 2024
21111ed
Reorganize
nightkr Aug 1, 2024
0bae249
Cert-Manager: only set node label if volume has node scope
nightkr Aug 1, 2024
31a58a9
CRD docs
nightkr Aug 1, 2024
1b668b8
Fix CSI always being considered dirty
nightkr Aug 1, 2024
b442ae3
Reference docs
nightkr Aug 1, 2024
152cf7b
Update cert-manager guide to use cert-manager backend
nightkr Aug 1, 2024
fd89ce5
Fix rustdoc warnings
nightkr Aug 1, 2024
b140437
Regenerate CRDs
nightkr Aug 1, 2024
2e214c4
Allow overriding Cert-Manager lifetimes
nightkr Aug 1, 2024
3b09e2b
Merge branch 'main' into feature/cert-manager
nightkr Aug 1, 2024
3d1cc56
Changelog
nightkr Aug 1, 2024
79b5427
Merge branch 'feature/cert-manager' of github.com:stackabletech/secre…
nightkr Aug 1, 2024
dfd983b
Make pvc_name optional
nightkr Aug 5, 2024
8103440
Merge branch 'main' into feature/cert-manager
nightkr Aug 15, 2024
eef19a4
Update rust/operator-binary/src/backend/cert_manager.rs
nightkr Aug 16, 2024
313ca7f
Update rust/operator-binary/src/backend/mod.rs
nightkr Aug 16, 2024
696fa9e
Update rust/operator-binary/src/backend/mod.rs
nightkr Aug 16, 2024
4da6bbd
Update tests/templates/kuttl/cert-manager-tls/consumer.yaml
nightkr Aug 16, 2024
6f7db7b
Update rust/operator-binary/src/crd.rs
nightkr Aug 16, 2024
bbfd6b4
Align cert-manager CRDs better with upstream
nightkr Aug 28, 2024
f01deeb
Merge branch 'feature/cert-manager' of github.com:stackabletech/secre…
nightkr Aug 28, 2024
a27cd31
Regenerate CRD
nightkr Aug 28, 2024
6f0f76b
Quote scopes in errors
nightkr Aug 28, 2024
087eec7
Add context for certificate object errors
nightkr Aug 28, 2024
4ce7e8d
Merge branch 'main' into feature/cert-manager
nightkr Aug 28, 2024
13a1393
Make Clippy happy
nightkr Aug 28, 2024
af7b974
cargo fmt
nightkr Sep 9, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ All notable changes to this project will be documented in this file.
### Added

- Active Directory's `samAccountName` generation can now be customized ([#454]).
- Added experimental cert-manager backend ([#482]).

### Fixed

- Fixed Kerberos keytab provisioning reusing its credential cache ([#490]).

[#454]: https://github.com/stackabletech/secret-operator/pull/454
[#482]: https://github.com/stackabletech/secret-operator/pull/482
[#490]: https://github.com/stackabletech/secret-operator/pull/490

## [24.7.0] - 2024-07-24
Expand Down
39 changes: 39 additions & 0 deletions deploy/helm/secret-operator/crds/crds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ spec:
- k8sSearch
- required:
- autoTls
- required:
- experimentalCertManager
- required:
- kerberosKeytab
properties:
Expand Down Expand Up @@ -79,6 +81,43 @@ spec:
required:
- ca
type: object
experimentalCertManager:
description: |-
The [`experimentalCertManager` backend][1] injects a TLS certificate issued by [cert-manager](https://cert-manager.io/).

A new certificate will be requested the first time it is used by a Pod, it will be reused after that (subject to cert-manager renewal rules).

[1]: https://docs.stackable.tech/home/nightly/secret-operator/secretclass#backend-certmanager
properties:
defaultCertificateLifetime:
default: 1d
description: |-
The default lifetime of certificates.

Defaults to 1 day. This may need to be increased for external issuers that impose rate limits (such as Let's Encrypt).
type: string
issuer:
description: A reference to the cert-manager issuer that the certificates should be requested from.
properties:
kind:
description: |-
The kind of the issuer, Issuer or ClusterIssuer.

If Issuer then it must be in the same namespace as the Pods using it.
enum:
- Issuer
- ClusterIssuer
type: string
name:
description: The name of the issuer.
type: string
required:
- kind
- name
type: object
required:
- issuer
type: object
k8sSearch:
description: The [`k8sSearch` backend](https://docs.stackable.tech/home/nightly/secret-operator/secretclass#backend-k8ssearch) can be used to mount Secrets across namespaces into Pods.
properties:
Expand Down
12 changes: 10 additions & 2 deletions deploy/helm/secret-operator/templates/roles.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ volumes:
- projected
- hostPath
- emptyDir
{{ end }}
{{ end }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
Expand Down Expand Up @@ -104,6 +104,14 @@ rules:
- podlisteners
verbs:
- get
- apiGroups:
- cert-manager.io
resources:
- certificates
verbs:
- get
- patch
- create
{{ if .Capabilities.APIVersions.Has "security.openshift.io/v1" }}
- apiGroups:
- security.openshift.io
Expand All @@ -113,4 +121,4 @@ rules:
- securitycontextconstraints
verbs:
- use
{{ end }}
{{ end }}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ spec:
metadata:
annotations:
secrets.stackable.tech/class: tls-cert-manager # <2>
secrets.stackable.tech/scope: service=my-app # <3>
secrets.stackable.tech/scope: node,service=my-app # <3>
spec:
storageClassName: secrets.stackable.tech
accessModes:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ metadata:
name: tls-cert-manager # <1>
spec:
backend:
k8sSearch:
searchNamespace:
pod: {} # <2>
experimentalCertManager:
issuer:
kind: Issuer # <2>
name: secret-operator-demonstration # <3>
34 changes: 9 additions & 25 deletions docs/modules/secret-operator/pages/cert-manager.adoc
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
= Cert-Manager Integration

WARNING: The Cert-Manager backend is experimental, and subject to change.

https://cert-manager.io/[Cert-Manager] is a common tool to manage certificates in Kubernetes, especially when backed by an external
Certificate Authority (CA) such as https://letsencrypt.org/[Let\'s Encrypt].

The Stackable Secret Operator does not currently support managing Cert-Manager certificates directly, but it can be configured to consume certificates generated by it.
The Stackable Secret Operator supports requesting certificates from Cert-Manager.

[#caveats]
== Caveats
Expand Down Expand Up @@ -37,46 +39,28 @@ include::example$cert-manager/issuer.yaml[]
[#secretclass]
== Creating a SecretClass

The Stackable Secret Operator needs to know how to find the certificates created by Cert-Manager. We do this by creating
a xref:secretclass.adoc[] using the xref:secretclass.adoc#backend-k8ssearch[`k8sSearch` backend], which can find arbitrary
Kubernetes Secret objects that have the correct labels.
The Stackable Secret Operator needs to know how to request the certificates from Cert-Manager. We do this by creating
a xref:secretclass.adoc[] using the xref:secretclass.adoc#backend-certmanager[`experimentalCertManager` backend].

[source,yaml]
----
include::example$cert-manager/secretclass.yaml[]
----
<1> Both certificates and Pods will reference this name, to ensure that the correct certificates are found
<2> This informs the Secret Operator that certificates will be found in the same namespace as the Pod using it

[#certificate]
== Requesting a certificate

You can now use Cert-Manager to provision your first certificate. Use labels to inform the Stackable Secret Operator
about which xref:scope.adoc[scopes] the certificate fulfills. Which scopes must be provisioned is going to depend
on the design of the workload. This guide assumes the xref:scope.adoc#service[service] scope.

[source,yaml]
----
include::example$cert-manager/certificate.yaml[]
----
<1> The Certificate name is irrelevant for the Stackable Secret Operator's, but must be unique (within the Namespace)
<2> The Secret name must also be unique within the Namespace
<3> This tells the Stackable Secret Operator that this secret corresponds to the SecretClass created xref:#secretclass[before]
<4> This secret fulfils the xref:scope.adoc#service[service] scope for `my-app`
<5> The list of DNS names that this certificate should apply to.
<6> The Cert-Manager Issuer that should sign this certificate, as created xref:#issuer[before]
<2> This guide uses a namespaced Issuer, rather than a cluster-scoped ClusterIssuer
<3> The Cert-Manager Issuer that should sign these certificates, as created xref:#issuer[before]

[#pod]
== Using the certificate

Finally, we can create and expose a Pod that consumes the certificate!
Finally, we can create and expose a Pod that requests and uses the certificate!

[source,yaml]
----
include::example$cert-manager/pod.yaml[]
----
<1> A secret xref:volume.adoc[volume] is created, where the certificate will be exposed to the app
<2> The volume references the SecretClass defined xref:#secretclass[before]
<3> The app is designated the scope xref:scope#service[`service=my-app`], matching the xref:#certificate[certificate's scope]
<3> The app requires the certificate to be valid for the scopes xref:scope.adoc#node[`node`] and xref:scope.adoc#service[`service=my-app`]
<4> nginx is configured to use the mounted certificate
<5> nginx is exposed as a Kubernetes Service
34 changes: 34 additions & 0 deletions docs/modules/secret-operator/pages/secretclass.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,40 @@ spec:
`autoTls.ca.caCertificateLifetime` :: The lifetime of the certificate authority's root certificate.
`autoTls.maxCertificateLifetime`:: Maximum lifetime the created certificates are allowed to have. In case consumers request a longer lifetime than allowed by this setting, the lifetime will be the minimum of both.

[#backend-certmanager]
=== `experimentalCertManager`

*Format*: xref:#format-tls-pem[]

Injects a TLS certificate issued by https://cert-manager.io/[Cert-Manager].

WARNING: This backend is experimental, and subject to change.

NOTE: This backend requires https://cert-manager.io/[Cert-Manager] to already be installed and configured.

A new certificate will be requested the first time it is used by a Pod, it will be reused after that (subject to Cert-Manager's renewal rules).

Node-scoped requests will cause a Pod to become "sticky" to the Node that it was first scheduled to (like xref:#backend-k8ssearch[], but unlike xref:#backend-autotls[]).

==== Reference

[source,yaml]
----
spec:
backend:
experimentalCertManager:
issuer:
kind: Issuer
name: secret-operator-demonstration
defaultCertificateLifetime: 1d
----

`experimentalCertManager`:: Declares that the `experimentalCertManager` backend is used.
`experimentalCertManager.issuer`:: The reference to the Cert-Manager issuer that should issue the certificates.
`experimentalCertManager.issuer.kind`:: The kind of the Cert-Manager issuer, either Issuer or ClusterIssuer. Note that Issuer must be in the same namespace as the Pod requesting the secret.
`experimentalCertManager.issuer.name`:: The name of the Issuer or ClusterIssuer to be used.
`experimentalCertManager.defaultCertificateLifetime`:: The default duration of the certificates. This may need to be increased for backends that impose stricter rate limits, such as https://letsencrypt.org/[Let's Encrypt].

[#backend-kerberoskeytab]
=== `kerberosKeytab`

Expand Down
12 changes: 12 additions & 0 deletions docs/modules/secret-operator/pages/volume.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,18 @@ shortened by a random amount between 0 and 4.8 hours, leaving a certificate that

Jittering may be disabled by setting the jitter factor to 0.

=== `secrets.stackable.tech/backend.cert-manager.cert.lifetime`

*Required*: false

*Default value*: `1d` (configured by xref:secretclass.adoc#backend-certmanager[the backend])

*Backends*: xref:secretclass.adoc#backend-autotls[]

The lifetime of the created certificate.

The format is documented in xref:concepts:duration.adoc[].

=== `secrets.stackable.tech/kerberos.service.names`

*Required*: false
Expand Down
2 changes: 1 addition & 1 deletion rust/operator-binary/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ fn main() {
let out_dir = PathBuf::from(std::env::var("OUT_DIR").expect("OUT_DIR is required"));
tonic_build::configure()
.file_descriptor_set_path(out_dir.join("file_descriptor_set.bin"))
.compile(&["csi.proto"], &["vendor/csi"])
.compile(&["vendor/csi/csi.proto"], &["vendor/csi"])
.unwrap();
built::write_built_file().unwrap();
}
Loading
Loading