diff --git a/CHANGELOG.md b/CHANGELOG.md index cd954c67..0c1da3e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +### Added + +- Improved CRD documentation ([#333]). + +[#333]: https://github.com/stackabletech/secret-operator/pull/333 + ## [23.11.0] - 2023-11-24 ### Added diff --git a/Cargo.lock b/Cargo.lock index 39ca3443..34a80234 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1622,71 +1622,62 @@ dependencies = [ [[package]] name = "opentelemetry" -version = "0.20.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9591d937bc0e6d2feb6f71a559540ab300ea49955229c347a517a28d27784c54" +checksum = "1e32339a5dc40459130b3bd269e9892439f55b33e772d2a9d402a789baaf4e8a" dependencies = [ - "opentelemetry_api", - "opentelemetry_sdk", + "futures-core", + "futures-sink", + "indexmap 2.0.2", + "js-sys", + "once_cell", + "pin-project-lite", + "thiserror", + "urlencoding", ] [[package]] name = "opentelemetry-jaeger" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "876958ba9084f390f913fcf04ddf7bbbb822898867bb0a51cc28f2b9e5c1b515" +checksum = "e617c66fd588e40e0dbbd66932fdc87393095b125d4459b1a3a10feb1712f8a1" dependencies = [ "async-trait", "futures-core", "futures-util", "opentelemetry", "opentelemetry-semantic-conventions", + "opentelemetry_sdk", "thrift", "tokio", ] [[package]] name = "opentelemetry-semantic-conventions" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73c9f9340ad135068800e7f1b24e9e09ed9e7143f5bf8518ded3d3ec69789269" +checksum = "f5774f1ef1f982ef2a447f6ee04ec383981a3ab99c8e77a1a7b30182e65bbc84" dependencies = [ "opentelemetry", ] -[[package]] -name = "opentelemetry_api" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a81f725323db1b1206ca3da8bb19874bbd3f57c3bcd59471bfb04525b265b9b" -dependencies = [ - "futures-channel", - "futures-util", - "indexmap 1.9.3", - "js-sys", - "once_cell", - "pin-project-lite", - "thiserror", - "urlencoding", -] - [[package]] name = "opentelemetry_sdk" -version = "0.20.0" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa8e705a0612d48139799fcbaba0d4a90f06277153e43dd2bdc16c6f0edd8026" +checksum = "968ba3f2ca03e90e5187f5e4f46c791ef7f2c163ae87789c8ce5f5ca3b7b7de5" dependencies = [ "async-trait", "crossbeam-channel", "futures-channel", "futures-executor", "futures-util", + "glob", "once_cell", - "opentelemetry_api", - "ordered-float 3.9.2", + "opentelemetry", + "ordered-float 4.2.0", "percent-encoding", "rand", - "regex", "thiserror", "tokio", "tokio-stream", @@ -1703,9 +1694,9 @@ dependencies = [ [[package]] name = "ordered-float" -version = "3.9.2" +version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1e1c390732d15f1d48471625cd92d154e66db2c56645e29a9cd26f4699f72dc" +checksum = "a76df7075c7d4d01fdcb46c912dd17fba5b60c78ea480b475f2b6ab6f666584e" dependencies = [ "num-traits", ] @@ -2500,8 +2491,8 @@ dependencies = [ [[package]] name = "stackable-operator" -version = "0.56.1" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=0.56.1#beeb39436024fa5f61d840402c26ee56fc5fbd29" +version = "0.58.1" +source = "git+https://github.com/stackabletech/operator-rs.git?tag=0.58.1#ab309d577e1937834f2adcbcd647822aa9c2ae43" dependencies = [ "chrono", "clap", @@ -2516,10 +2507,12 @@ dependencies = [ "lazy_static", "opentelemetry", "opentelemetry-jaeger", + "opentelemetry_sdk", "product-config", "rand", "regex", "schemars", + "semver", "serde", "serde_json", "serde_yaml", @@ -2532,12 +2525,13 @@ dependencies = [ "tracing", "tracing-opentelemetry", "tracing-subscriber", + "url", ] [[package]] name = "stackable-operator-derive" -version = "0.56.1" -source = "git+https://github.com/stackabletech/operator-rs.git?tag=0.56.1#beeb39436024fa5f61d840402c26ee56fc5fbd29" +version = "0.58.1" +source = "git+https://github.com/stackabletech/operator-rs.git?tag=0.58.1#ab309d577e1937834f2adcbcd647822aa9c2ae43" dependencies = [ "darling", "proc-macro2", @@ -3036,20 +3030,33 @@ dependencies = [ "tracing-core", ] +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + [[package]] name = "tracing-opentelemetry" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75327c6b667828ddc28f5e3f169036cb793c3f588d83bf0f262a7f062ffed3c8" +checksum = "c67ac25c5407e7b961fafc6f7e9aa5958fd297aada2d20fa2ae1737357e55596" dependencies = [ + "js-sys", "once_cell", "opentelemetry", "opentelemetry_sdk", "smallvec", "tracing", "tracing-core", - "tracing-log", + "tracing-log 0.2.0", "tracing-subscriber", + "web-time", ] [[package]] @@ -3067,7 +3074,7 @@ dependencies = [ "thread_local", "tracing", "tracing-core", - "tracing-log", + "tracing-log 0.1.3", ] [[package]] @@ -3265,6 +3272,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web-time" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57099a701fb3a8043f993e8228dc24229c7b942e2b009a1b962e54489ba1d3bf" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "which" version = "4.4.2" diff --git a/Cargo.toml b/Cargo.toml index 0eb9d6e0..5d484a9c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,7 +33,7 @@ serde_json = "1.0" serde_yaml = "0.9" snafu = "0.7" socket2 = { version = "0.5", features = ["all"] } -stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git", tag = "0.56.1", features = ["time"]} +stackable-operator = { git = "https://github.com/stackabletech/operator-rs.git", tag = "0.58.1", features = ["time"]} strum = { version = "0.25", features = ["derive"] } sys-mount = { version = "2.1", default-features = false } tempfile = "3.3" diff --git a/deploy/helm/secret-operator/crds/crds.yaml b/deploy/helm/secret-operator/crds/crds.yaml index 45ff58df..f5ac18db 100644 --- a/deploy/helm/secret-operator/crds/crds.yaml +++ b/deploy/helm/secret-operator/crds/crds.yaml @@ -22,8 +22,10 @@ spec: description: Auto-generated derived type for SecretClassSpec via `CustomResource` properties: spec: + description: A [SecretClass](https://docs.stackable.tech/home/nightly/secret-operator/secretclass) is a cluster-global Kubernetes resource that defines a category of secrets that the Secret Operator knows how to provision. properties: backend: + description: Each SecretClass is associated with a single [backend](https://docs.stackable.tech/home/nightly/secret-operator/secretclass#backend), which dictates the mechanism for issuing that kind of Secret. oneOf: - required: - k8sSearch @@ -33,15 +35,20 @@ spec: - kerberosKeytab properties: autoTls: + description: |- + The [`autoTls` backend](https://docs.stackable.tech/home/nightly/secret-operator/secretclass#backend-autotls) 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. properties: ca: + description: Configures the certificate authority used to issue Pod certificates. properties: autoGenerate: default: false - description: Whether a new certificate authority should be generated if it does not already exist + description: Whether a new certificate authority should be generated if it does not already exist. type: boolean secret: - description: SecretReference represents a Secret Reference. It has enough information to retrieve secret in any namespace + description: Reference (name and namespace) to a Kubernetes Secret object where the CA certificate and key is stored in the keys `ca.crt` and `ca.key` respectively. properties: name: description: name is unique within a namespace to reference a secret resource. @@ -55,14 +62,16 @@ spec: type: object maxCertificateLifetime: default: 15d - description: 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, so this setting takes precedence. + description: 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, so this setting takes precedence. The default value is 15 days. type: string required: - ca 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: searchNamespace: + description: Configures the namespace searched for Secret objects. oneOf: - required: - pod @@ -70,16 +79,20 @@ spec: - name properties: name: + description: The Secret objects are located in a single global namespace. Should be used for secrets that are provisioned by the cluster administrator. type: string pod: + description: The Secret objects are located in the same namespace as the Pod object. Should be used for Secrets that are provisioned by the application administrator. type: object type: object required: - searchNamespace type: object kerberosKeytab: + description: The [`kerberosKeytab` backend](https://docs.stackable.tech/home/nightly/secret-operator/secretclass#backend-kerberoskeytab) creates a Kerberos keytab file for a selected realm. The Kerberos KDC and administrator credentials must be provided by the administrator. properties: admin: + description: Kerberos admin configuration settings. oneOf: - required: - mit @@ -87,11 +100,13 @@ spec: - activeDirectory properties: activeDirectory: + description: Credentials should be provisioned in a Microsoft Active Directory domain. properties: ldapServer: + description: An AD LDAP server, such as the AD Domain Controller. This must match the server’s FQDN, or GSSAPI authentication will fail. type: string ldapTlsCaSecret: - description: SecretReference represents a Secret Reference. It has enough information to retrieve secret in any namespace + description: Reference (name and namespace) to a Kubernetes Secret object containing the TLS CA (in `ca.crt`) that the LDAP server’s certificate should be authenticated against. properties: name: description: name is unique within a namespace to reference a secret resource. @@ -101,7 +116,7 @@ spec: type: string type: object passwordCacheSecret: - description: SecretReference represents a Secret Reference. It has enough information to retrieve secret in any namespace + description: Reference (name and namespace) to a Kubernetes Secret object where workload passwords will be stored. This must not be accessible to end users. properties: name: description: name is unique within a namespace to reference a secret resource. @@ -111,8 +126,10 @@ spec: type: string type: object schemaDistinguishedName: + description: The root Distinguished Name (DN) for AD-managed schemas, typically `CN=Schema,CN=Configuration,{domain_dn}`. type: string userDistinguishedName: + description: The root Distinguished Name (DN) where service accounts should be provisioned, typically `CN=Users,{domain_dn}`. type: string required: - ldapServer @@ -122,15 +139,17 @@ spec: - userDistinguishedName type: object mit: + description: Credentials should be provisioned in a MIT Kerberos Admin Server. properties: kadminServer: + description: The hostname of the Kerberos Admin Server. This should be provided by the Kerberos administrator. type: string required: - kadminServer type: object type: object adminKeytabSecret: - description: SecretReference represents a Secret Reference. It has enough information to retrieve secret in any namespace + description: Reference (`name` and `namespace`) to a K8s Secret object where a keytab with administrative privileges is stored in the key `keytab`. properties: name: description: name is unique within a namespace to reference a secret resource. @@ -140,10 +159,13 @@ spec: type: string type: object adminPrincipal: + description: The admin principal. type: string kdc: + description: The hostname of the Kerberos Key Distribution Center (KDC). This should be provided by the Kerberos administrator. type: string realmName: + description: The name of the Kerberos realm. This should be provided by the Kerberos administrator. type: string required: - admin diff --git a/rust/operator-binary/src/crd.rs b/rust/operator-binary/src/crd.rs index 71f5070f..c7cd06ee 100644 --- a/rust/operator-binary/src/crd.rs +++ b/rust/operator-binary/src/crd.rs @@ -11,6 +11,8 @@ use stackable_operator::{ use crate::backend::tls::DEFAULT_MAX_CERT_LIFETIME; +/// A [SecretClass](DOCS_BASE_URL_PLACEHOLDER/secret-operator/secretclass) is a cluster-global Kubernetes resource +/// that defines a category of secrets that the Secret Operator knows how to provision. #[derive(CustomResource, Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[kube( group = "secrets.stackable.tech", @@ -24,6 +26,9 @@ use crate::backend::tls::DEFAULT_MAX_CERT_LIFETIME; )] #[serde(rename_all = "camelCase")] pub struct SecretClassSpec { + /// Each SecretClass is associated with a single + /// [backend](DOCS_BASE_URL_PLACEHOLDER/secret-operator/secretclass#backend), + /// which dictates the mechanism for issuing that kind of Secret. pub backend: SecretClassBackend, } @@ -31,33 +36,53 @@ pub struct SecretClassSpec { #[serde(rename_all = "camelCase")] #[allow(clippy::large_enum_variant)] pub enum SecretClassBackend { + /// The [`k8sSearch` backend](DOCS_BASE_URL_PLACEHOLDER/secret-operator/secretclass#backend-k8ssearch) + /// can be used to mount Secrets across namespaces into Pods. K8sSearch(K8sSearchBackend), + + /// The [`autoTls` backend](DOCS_BASE_URL_PLACEHOLDER/secret-operator/secretclass#backend-autotls) + /// 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. AutoTls(AutoTlsBackend), + + /// The [`kerberosKeytab` backend](DOCS_BASE_URL_PLACEHOLDER/secret-operator/secretclass#backend-kerberoskeytab) + /// creates a Kerberos keytab file for a selected realm. + /// The Kerberos KDC and administrator credentials must be provided by the administrator. KerberosKeytab(KerberosKeytabBackend), } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "camelCase")] pub struct K8sSearchBackend { + /// Configures the namespace searched for Secret objects. pub search_namespace: SearchNamespace, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "camelCase")] pub enum SearchNamespace { + /// The Secret objects are located in the same namespace as the Pod object. + /// Should be used for Secrets that are provisioned by the application administrator. Pod {}, + + /// The Secret objects are located in a single global namespace. + /// Should be used for secrets that are provisioned by the cluster administrator. Name(String), } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "camelCase")] pub struct AutoTlsBackend { + /// Configures the certificate authority used to issue Pod certificates. pub ca: AutoTlsCa, - #[serde(default = "default_max_certificate_lifetime")] /// 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, so this setting takes precedence. + /// The default value is 15 days. + #[serde(default = "default_max_certificate_lifetime")] pub max_certificate_lifetime: Duration, } @@ -68,8 +93,11 @@ fn default_max_certificate_lifetime() -> Duration { #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "camelCase")] pub struct AutoTlsCa { + /// Reference (name and namespace) to a Kubernetes Secret object where the CA certificate + /// and key is stored in the keys `ca.crt` and `ca.key` respectively. pub secret: SecretReference, - /// Whether a new certificate authority should be generated if it does not already exist + + /// Whether a new certificate authority should be generated if it does not already exist. #[serde(default)] pub auto_generate: bool, } @@ -77,24 +105,56 @@ pub struct AutoTlsCa { #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "camelCase")] pub struct KerberosKeytabBackend { + /// The name of the Kerberos realm. This should be provided by the Kerberos administrator. pub realm_name: Hostname, + + /// The hostname of the Kerberos Key Distribution Center (KDC). + /// This should be provided by the Kerberos administrator. pub kdc: Hostname, + + /// Kerberos admin configuration settings. pub admin: KerberosKeytabBackendAdmin, + + /// Reference (`name` and `namespace`) to a K8s Secret object where a + /// keytab with administrative privileges is stored in the key `keytab`. pub admin_keytab_secret: SecretReference, + + /// The admin principal. pub admin_principal: KerberosPrincipal, } #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "camelCase")] pub enum KerberosKeytabBackendAdmin { + /// Credentials should be provisioned in a MIT Kerberos Admin Server. #[serde(rename_all = "camelCase")] - Mit { kadmin_server: Hostname }, + Mit { + /// The hostname of the Kerberos Admin Server. + /// This should be provided by the Kerberos administrator. + kadmin_server: Hostname, + }, + + /// Credentials should be provisioned in a Microsoft Active Directory domain. #[serde(rename_all = "camelCase")] ActiveDirectory { + /// An AD LDAP server, such as the AD Domain Controller. + /// This must match the server’s FQDN, or GSSAPI authentication will fail. ldap_server: Hostname, + + /// Reference (name and namespace) to a Kubernetes Secret object containing + /// the TLS CA (in `ca.crt`) that the LDAP server’s certificate should be authenticated against. ldap_tls_ca_secret: SecretReference, + + /// Reference (name and namespace) to a Kubernetes Secret object where workload + /// passwords will be stored. This must not be accessible to end users. password_cache_secret: SecretReference, + + /// The root Distinguished Name (DN) where service accounts should be provisioned, + /// typically `CN=Users,{domain_dn}`. user_distinguished_name: String, + + /// The root Distinguished Name (DN) for AD-managed schemas, + /// typically `CN=Schema,CN=Configuration,{domain_dn}`. schema_distinguished_name: String, }, } diff --git a/rust/operator-binary/src/main.rs b/rust/operator-binary/src/main.rs index aaa72b79..22c126ff 100644 --- a/rust/operator-binary/src/main.rs +++ b/rust/operator-binary/src/main.rs @@ -53,6 +53,7 @@ struct SecretOperatorRun { mod built_info { include!(concat!(env!("OUT_DIR"), "/built.rs")); pub const TARGET: Option<&str> = option_env!("TARGET"); + pub const CARGO_PKG_VERSION: &str = env!("CARGO_PKG_VERSION"); } #[tokio::main] @@ -60,7 +61,7 @@ async fn main() -> anyhow::Result<()> { let opts = Opts::parse(); match opts.cmd { stackable_operator::cli::Command::Crd => { - crd::SecretClass::print_yaml_schema()?; + crd::SecretClass::print_yaml_schema(built_info::CARGO_PKG_VERSION)?; } stackable_operator::cli::Command::Run(SecretOperatorRun { csi_endpoint,