Skip to content
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

Add descriptions #499

Merged
merged 1 commit into from
Sep 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
31 changes: 17 additions & 14 deletions docs/modules/secret-operator/pages/cert-manager.adoc
Original file line number Diff line number Diff line change
@@ -1,34 +1,37 @@
= Cert-Manager Integration
= Cert-Manager integration
:description: Integrate Cert-Manager with Stackable Secret Operator to manage certificates. Follow steps for configuration, creating SecretClass, and using certificates in Pods.
:cert-manager: https://cert-manager.io/
:letsencrypt: https://letsencrypt.org/

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].
{cert-manager}[Cert-Manager] is a common tool to manage certificates in Kubernetes, especially when backed by an external Certificate Authority (CA) such as {letsencrypt}[Let\'s Encrypt].

The Stackable Secret Operator supports requesting certificates from Cert-Manager.

[#caveats]
== Caveats

Cert-Manager is designed to manage relatively long-lived certificates that are stored in Kubernetes Secrets. By contrast,
the Stackable Secret Operator is designed to generate temporary short-lived certificates.
Cert-Manager is designed to manage relatively long-lived certificates that are stored in Kubernetes Secrets.
By contrast, the Stackable Secret Operator is designed to generate temporary short-lived certificates.

This has a couple of repercussions:

- Longer-lived certificates mean that a leaked certificate has potential to be abused for longer.
- Application teams may have access to read Secrets in their respective applications' Namespaces.
* Longer-lived certificates mean that a leaked certificate has potential to be abused for longer.
* Application teams may have access to read Secrets in their respective applications' Namespaces.

Where possible, we recommend using the xref:secretclass.adoc#backend-autotls[`autoTls` backend] instead.
Where possible, it is recommended using the xref:secretclass.adoc#backend-autotls[`autoTls` backend] instead.

[#issuer]
== Configuring Cert-Manager

NOTE: We recommend using the xref:secretclass.adoc#backend-autotls[`autoTls` backend] instead for self-signed PKIs. We use Cert-Manager's CA issuer here to show the broader concepts.
NOTE: Using the xref:secretclass.adoc#backend-autotls[`autoTls` backend] instead for self-signed PKIs is recommended.
The Cert-Manager's CA issuer is used in these examples to illustrate the broader concepts.

To do this, you will first need to teach Cert-Manager how to create your certificates.

In a production setup this will likely use an external CA such as ACME or OpenBao/Vault. However, to make this guide self-contained, Cert-Manager will create
a self-signed CA certificate instead.
In a production setup this will likely use an external CA such as ACME or OpenBao/Vault.
However, to make this guide self-contained, Cert-Manager will create a self-signed CA certificate instead.

[source,yaml]
----
Expand All @@ -39,8 +42,8 @@ include::example$cert-manager/issuer.yaml[]
[#secretclass]
== Creating a SecretClass

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].
The Stackable Secret Operator needs to know how to request the certificates from Cert-Manager.
Do this by creating a xref:secretclass.adoc[] using the xref:secretclass.adoc#backend-certmanager[`experimentalCertManager` backend].

[source,yaml]
----
Expand All @@ -53,7 +56,7 @@ include::example$cert-manager/secretclass.yaml[]
[#pod]
== Using the certificate

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

[source,yaml]
----
Expand Down
1 change: 1 addition & 0 deletions docs/modules/secret-operator/pages/index.adoc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
= Stackable Secret Operator
:description: Stackable Secret Operator enhances Kubernetes Secrets by provisioning Pods with TLS certificates, Kerberos keytabs, and tokens.
:github: https://github.com/stackabletech/secret-operator/
:crd: {crd-docs-base-url}/secret-operator/{crd-docs-version}/

Expand Down
7 changes: 3 additions & 4 deletions docs/modules/secret-operator/pages/installation.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@

There are two ways to run the Stackable Secret Operator:

1. Helm managed Docker container deployment on Kubernetes

2. Build from source
. Helm managed Docker container deployment on Kubernetes
. Build from source

== Prerequisites

Expand All @@ -14,7 +13,7 @@ You will need:
* kubectl
* Helm

Resource sizing depends on cluster type(s), usage and scope, but as a starting point we recommend a minimum of the following resources for this operator:
Resource sizing depends on cluster type(s), usage and scope, but as a starting point a minimum of the following resources is recommended for this operator:

* 0.2 cores (e.g. i5 or similar)
* 256MB RAM
Expand Down
13 changes: 8 additions & 5 deletions docs/modules/secret-operator/pages/openshift.adoc
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
= Running on OpenShift
:description: Install Stackable Secret Operator on OpenShift via OperatorHub or Helm. Manual upgrades and cleanup are required due to OLM limitations.
:operatorhub: https://docs.openshift.com/container-platform/4.16/operators/understanding/olm-understanding-operatorhub.html

== Installation methods

The Secret Operator can be installed using either using Helm or via the Operator Hub.

It is not possible to mix the two because they are incompatible. This means that once an operator has been installed via the Operator Hub, it cannot be upgraded with Helm or vice versa.
The Secret Operator can be installed using either Helm or the {operatorhub}[OperatorHub].

It is not possible to mix the two because they are incompatible.
This means that once an operator has been installed via the Operator Hub, it cannot be upgraded with Helm or vice versa.

== Operator Hub Installation

This operator can be installed from RedHat's Operator Hub.

Unfortunately there are some things you need to be aware of when upgrading or uninstalling the operator from the Operator Hub.
Unfortunately there are some things you need to be aware of when upgrading or uninstalling the operator from the OperatorHub.

Due to limitations of the Operator Lifecycle Manager (OLM) you cannot enable automatic updates of the Stackable Secret Operator. Upgrading to a new version requires you to uninstall the existing version of the operator and then manually remove the following resources:
Due to limitations of the Operator Lifecycle Manager (OLM) you cannot enable automatic updates of the Stackable Secret Operator.
Upgrading to a new version requires you to uninstall the existing version of the operator and then manually remove the following resources:

* SecretClass: tls
* ServiceAccount: secret-operator-service-account
Expand Down
29 changes: 16 additions & 13 deletions docs/modules/secret-operator/pages/scope.adoc
Original file line number Diff line number Diff line change
@@ -1,31 +1,34 @@
= Scope
:description: Stackable Secret Operator supports scopes for secrets like node, pod, and service, adding context like IP, pod names, and DNS to credentials.

Secrets often cover some specific aspect of a workload. For example:
Secrets often cover some specific aspect of a workload.
For example:

* A Kerberos credential may be bound to one node IP
* An internal TLS certificate's `subjectAlternateName` section must match the `Pod` object's name and service
* A Kerberos credential may be bound to one node IP.
* An internal TLS certificate's `subjectAlternateName` section must match the Pod object's name and service.

To solve this, the Stackable Secret Operator has a concept of "scopes", which allow a xref:volume.adoc[] to selectively
include this extra context. The exact effect of the scope depends on which xref:secretclass.adoc#backend[`backend`] is used.
To solve this, the Stackable Secret Operator has a concept of "scopes", which allow a xref:volume.adoc[] to selectively include this extra context.
The exact effect of the scope depends on which xref:secretclass.adoc#backend[`backend`] is used.

== Supported Scopes

[#node]
=== `node`

The `node` scope is resolved to the name of the Kubernetes Node object that the Pod is running on. This will typically
be the DNS name of the node.
The `node` scope is resolved to the name of the Kubernetes Node object that the Pod is running on.
This will typically be the DNS name of the node.

[#pod]
=== `pod`

The `pod` scope is resolved to the name of the Kubernetes Pod. This allows the secret to differentiate between StatefulSet replicas.
The `pod` scope is resolved to the name of the Kubernetes Pod.
This allows the secret to differentiate between StatefulSet replicas.

[#service]
=== `service`

The `service` scope allows Pod objects to specify custom scopes. This should typically correspond to Service objects that the
Pod participate in.
The `service` scope allows Pod objects to specify custom scopes.
This should typically correspond to Service objects that the Pod participate in.

[#listener-volume]
=== `listener-volume`
Expand All @@ -43,6 +46,6 @@ note:: The `listener-volume` scope also implies the xref:#node[] scope for xref:
For example, a TLS certificate provisioned by the xref:secretclass.adoc#backend-autotls[`autoTls`] backend, with the scopes
xref:#node[] and xref:#pod[] would contain the following values in its `subjectAlternateName` (SAN) extension field:

- The node's IP address
- The node's fully qualified domain name (`my-node.example.com`)
- The pod's fully qualified domain name (`my-pod.my-service.my-namespace.svc.cluster.local`)
* The node's IP address
* The node's fully qualified domain name (`my-node.example.com`)
* The pod's fully qualified domain name (`my-pod.my-service.my-namespace.svc.cluster.local`)
57 changes: 31 additions & 26 deletions docs/modules/secret-operator/pages/secretclass.adoc
Original file line number Diff line number Diff line change
@@ -1,74 +1,78 @@
= `SecretClass`
= SecretClass
:description: A SecretClass in Kubernetes defines secret categories, handling certificate provision and secret management via multiple backends.
:cert-manager: https://cert-manager.io/

A `SecretClass` is a cluster-global Kubernetes resource that defines a category of secrets that the Secret Operator knows how to provision.
A _SecretClass_ is a cluster-global Kubernetes resource that defines a category of secrets that the Secret Operator knows how to provision.

This is intended to provide an abstraction between how the secret is used ("I need a certificate for my cluster's TLS PKI") and how
it is provisioned (automatically and generated by the operator's internal CA, provisioned by the cluster administrator, or provisioned by an
external service such as Hashicorp Vault).

A `SecretClass` looks like this:
A SecretClass looks like this:

[source,yaml]
----
include::example$secretclass-tls.yaml[]
----
<1> Backends are mutually exclusive, only one may be used by each `SecretClass`
<1> Backends are mutually exclusive, only one may be used by each SecretClass
<2> Configures and selects the xref:#backend-autotls[] backend
<3> Configures and selects the xref:#backend-k8ssearch[] backend

[#backend]
== Backend

Each `SecretClass` is a associated with a single backend, which dictates the mechanism for issuing that kind of secret.
Each SecretClass is a associated with a single backend, which dictates the mechanism for issuing that kind of secret.

Check notice on line 24 in docs/modules/secret-operator/pages/secretclass.adoc

View workflow job for this annotation

GitHub Actions / LanguageTool

[LanguageTool] docs/modules/secret-operator/pages/secretclass.adoc#L24

Use “an” instead of ‘a’ if the following word starts with a vowel sound, e.g. ‘an article’, ‘an hour’. (EN_A_VS_AN) Suggestions: `an` URL: https://languagetool.org/insights/post/indefinite-articles/ Rule: https://community.languagetool.org/rule/show/EN_A_VS_AN?lang=en-US Category: MISC
Raw output
docs/modules/secret-operator/pages/secretclass.adoc:24:20: Use “an” instead of ‘a’ if the following word starts with a vowel sound, e.g. ‘an article’, ‘an hour’. (EN_A_VS_AN)
 Suggestions: `an`
 URL: https://languagetool.org/insights/post/indefinite-articles/ 
 Rule: https://community.languagetool.org/rule/show/EN_A_VS_AN?lang=en-US
 Category: MISC

[#backend-autotls]
=== `autoTls`

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

Issues a TLS certificate signed by the Secret Operator. The certificate authority can be provided by the administrator, or managed automatically
by the Secret Operator.
Issues a TLS certificate signed by the Secret Operator.
The certificate authority can be provided by the administrator, or managed automatically by the Secret Operator.

A new certificate and keypair will be generated and signed for each `Pod`, keys or certificates are never reused.
A new certificate and keypair will be generated and signed for each Pod, keys or certificates are never reused.

CAUTION: Attributes of the certificate (such as the expiration date, fingerprint, or serial number) will be regenerated for each
`Pod`, and should not be expected to be stable.
Pod, and should not be expected to be stable.

xref:scope.adoc[Scopes] are used to populate the claims (such as `subjectAlternateName`) of the provisioned certificates.

==== Certificate lifetime

We generally aim to use as short-lived certificates as possible.
By default the Secret Operator will generally aim to use as short-lived certificates as possible.
Short lifetime periods require frequent restarts of services, which may be totally unnoticeable for some products,
annoying for others or fatal for products with a single point of failure and no recovery from outages (e.g. Trino coordinator).

We have spent a considerate amount of time thinking about this issue and decided on the following compromises:
This choice was made deliberately after a considerate amount of time was spent thinking about this issue.
The following compromises were made:

. To enforce security constraints, cluster administrators can set a maximum allowed certificate lifetime
on the SecretClass issuing the certificates (defaults to `15d`).
. We default to a certificate lifetime of `24h`.
. To enforce security constraints, cluster administrators can set a maximum allowed certificate lifetime on the SecretClass issuing the certificates (defaults to `15d`).
. The certificate lifetime is `24h`.
. Pods consuming the certificate can request a longer lifetime or shutdown expiration buffer via annotations
on the xref:volume.adoc[Volume]. If they request a longer lifetime than the SecretClass allows,
it will be shortened to the maximum allowed lifetime.
. To avoid stampeding herds during restarts and spread out the load, certificate durations are lowered by up to 20%.
. The Pods will be evicted `6h` before the certificate expires, to ensure that no Pods are left running with expired secrets. Consumers can override this buffer using Volume annotations.
. The Pods will be evicted `6h` before the certificate expires, to ensure that no Pods are left running with expired secrets.
Consumers can override this buffer using Volume annotations.
This buffer must be long enough that the product is guaranteed to gracefully shut down.

Most of our product operators will not set any specific certificate lifetime, so the default applies.
Most Stackable product operators will not set any specific certificate lifetime, so the default applies.
In case an operator sets a higher lifetime, a tracking issue must be created to document and track the steps to reduce the certificate lifetime.

Users can use podOverrides to extend the certificate lifetime by adding volume annotations. We might add native support for customizing certificate lifetimes in the future to the Stacklet CRDs.
Users can use xref:concepts:overrides.adoc#pod-overrides[podOverrides] to extend the certificate lifetime by adding volume annotations.
Native support for customizing certificate lifetimes in Stacklet CRDs might be added in the future.

==== Certificate Authority rotation

Certificate authorities also have a limited lifetime, and need to be rotated before they expire to avoid cluster disruption.

If configured to provision its own CA (`autoTls.ca.autoGenerate`), the Secret Operator will create CA certificates that are valid for 2 years (`autoTls.ca.caCertificateLifetime`),
and initiate rotation once less than half of that time remains.
If configured to provision its own CA (`autoTls.ca.autoGenerate`), the Secret Operator will create CA certificates that are valid for 2 years (`autoTls.ca.caCertificateLifetime`), and initiate rotation once less than half of that time remains.

To avoid disruption and let the new CA propagate through the cluster, the Secret Operator will prefer using the oldest CA that will last for the entire lifetime of the issued certificate.

NOTE: Expired CA certificates will currently not be deleted automatically. They should be cleaned up manually.
NOTE: Expired CA certificates will currently not be deleted automatically.
They should be cleaned up manually.

==== Reference

Expand Down Expand Up @@ -99,11 +103,11 @@

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

Injects a TLS certificate issued by https://cert-manager.io/[Cert-Manager].
Injects a TLS certificate issued by {cert-manager}[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.
NOTE: This backend requires {cert-manager}[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).

Expand Down Expand Up @@ -135,7 +139,8 @@

Creates a Kerberos keytab file for a selected realm. The Kerberos KDC and administrator credentials must be provided by the administrator.

IMPORTANT: Only MIT Kerberos (krb5) and Active Directory are currently supported. Heimdal is not supported.
IMPORTANT: Only MIT Kerberos (krb5) and Active Directory are currently supported.
Heimdal is not supported.

Principals will be created dynamically if they do not already exist.

Expand All @@ -146,15 +151,15 @@
[#ad-principal-conflicts]
===== Principal Conflicts

We recommend that each Active Directory domain should only be used by a single Kubernetes cluster.
Each Active Directory domain should be used by only a single Kubernetes cluster.

This is because each pod, service, and node may be provisioned a principal matching its hostname, and principal names must be unique within a single AD domain.
The Stackable Secret Operator will cache and reuse these credentials within a single Kubernetes cluster, but will not share them across multiple clusters.

If the same AD domain _is_ shared between multiple Kubernetes clusters, the following _must_ be unique across the AD domain:

- The Kubernetes Nodes' names and fully qualified domain names
- The Kubernetes Namespaces' names (only Namespaces that use Kerberos)
* The Kubernetes Nodes' names and fully qualified domain names
* The Kubernetes Namespaces' names (only Namespaces that use Kerberos)

[#ad-samaccountname]
===== Custom `samAccountName` generation
Expand Down
20 changes: 10 additions & 10 deletions docs/modules/secret-operator/pages/security.adoc
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
= Security
:description: The Secret Operator requires root privileges to manage secrets securely and avoid writing sensitive data to disk. Running in unprivileged mode is discouraged.

== Container privileges

By default, the Secret Operator runs as a set of privileged root containers. This is done for three reasons:
By default, the Secret Operator runs as a set of privileged root containers.
This is done for three reasons:

1. We need to run as root to have permission to create the Unix domain socket hosting the Container Storage interface (CSI)
driver. The Kubelet communicates with the CSI driver over this socket.
2. We need to run as root to have permission to write secret material into the pods' volume paths, as directed
by the CSI.
3. We need to run as a privileged container in order to be able to mount the volume folders as RAM disks, in order to avoid
spilling secret material onto disk.
1. The operator needs to run as root to have permission to create the Unix domain socket hosting the Container Storage interface (CSI) driver.
The Kubelet communicates with the CSI driver over this socket.
2. The operator needs to run as root to have permission to write secret material into the pods' volume paths, as directed by the CSI.
3. The operator needs to run as a privileged container in order to be able to mount the volume folders as RAM disks, in order to avoid spilling secret material onto disk.

Running as root is currently a hard requirement. Secret Operator _can_ run in an unprivileged container (by passing
`--set securityContext.privileged=false` to `helm upgrade`), but doing so is strongly discouraged, and users
should be aware that it means that secret material will be written to disk.
Running as root is currently a hard requirement.
Secret Operator _can_ run in an unprivileged container (by passing `--set securityContext.privileged=false` to `helm upgrade`),

Check notice on line 15 in docs/modules/secret-operator/pages/security.adoc

View workflow job for this annotation

GitHub Actions / LanguageTool

[LanguageTool] docs/modules/secret-operator/pages/security.adoc#L15

If a new sentence starts here, add a space and start with an uppercase letter. (LC_AFTER_PERIOD[1]) Suggestions: ` Privileged`, ` privileged` Rule: https://community.languagetool.org/rule/show/LC_AFTER_PERIOD?lang=en-US&subId=1 Category: CASING
Raw output
docs/modules/secret-operator/pages/security.adoc:15:90: If a new sentence starts here, add a space and start with an uppercase letter. (LC_AFTER_PERIOD[1])
 Suggestions: ` Privileged`, ` privileged`
 Rule: https://community.languagetool.org/rule/show/LC_AFTER_PERIOD?lang=en-US&subId=1
 Category: CASING
but doing so is strongly discouraged, and users should be aware that it means that secret material will be written to disk.
Loading
Loading