diff --git a/app/_mesh_policies/meshidentity/examples/acmpca-provider.yaml b/app/_mesh_policies/meshidentity/examples/acmpca-provider.yaml new file mode 100644 index 0000000000..1c3c4d865e --- /dev/null +++ b/app/_mesh_policies/meshidentity/examples/acmpca-provider.yaml @@ -0,0 +1,28 @@ +title: 'MeshIdentity with AWS Private CA' +tools: + - kubernetes +description: 'Sign workload certificates with an AWS Private CA (ACM PCA).' +min_version: + mesh: '2.14' +weight: 810 +requirements: + - "A [MeshService](/mesh/meshservice/) resource must be configured in your mesh." + - "An active AWS Private CA whose template allows certificates with a SPIFFE URI SAN." + - "AWS credentials available to the control plane through the standard AWS credential chain (IRSA recommended on EKS), with `acm-pca:IssueCertificate`, `acm-pca:GetCertificate`, and `acm-pca:GetCertificateAuthorityCertificate` permissions." +namespace: kong-mesh-system +config: + type: MeshIdentity + name: identity-acmpca + mesh: default + spec: + selector: + dataplane: + matchLabels: {} + provider: + type: Extension + extension: + name: acmpca + config: + arn: arn:aws:acm-pca:eu-central-1:123456789012:certificate-authority/12345678-1234-1234-1234-123456789012 + certificateParameters: + expiry: 24h diff --git a/app/_mesh_policies/meshidentity/examples/certmanager-provider.yaml b/app/_mesh_policies/meshidentity/examples/certmanager-provider.yaml new file mode 100644 index 0000000000..1cd69e56aa --- /dev/null +++ b/app/_mesh_policies/meshidentity/examples/certmanager-provider.yaml @@ -0,0 +1,36 @@ +title: 'MeshIdentity with cert-manager' +tools: + - kubernetes +description: 'Issue workload certificates through a cert-manager ClusterIssuer.' +min_version: + mesh: '2.14' +weight: 820 +requirements: + - "A [MeshService](/mesh/meshservice/) resource must be configured in your mesh." + - "[cert-manager](https://cert-manager.io/) installed in the cluster with a CA `ClusterIssuer` named `ca-issuer`." + - "A {{site.mesh_product_name}} `Secret` named `meshidentity-certmanager-ca` holding the issuing CA certificate, used for `MeshTrust` auto-creation." +namespace: kong-mesh-system +config: + type: MeshIdentity + name: identity-certmanager + mesh: default + spec: + selector: + dataplane: + matchLabels: {} + provider: + type: Extension + extension: + name: certmanager + config: + issuerRef: + name: ca-issuer + kind: ClusterIssuer + group: cert-manager.io + caCert: + type: Secret + secretRef: + kind: Secret + name: meshidentity-certmanager-ca + certificateParameters: + expiry: 24h diff --git a/app/_mesh_policies/meshidentity/examples/vault-provider.yaml b/app/_mesh_policies/meshidentity/examples/vault-provider.yaml new file mode 100644 index 0000000000..664207015e --- /dev/null +++ b/app/_mesh_policies/meshidentity/examples/vault-provider.yaml @@ -0,0 +1,47 @@ +title: 'MeshIdentity with HashiCorp Vault' +tools: + - kubernetes +description: 'Issue workload certificates from a HashiCorp Vault PKI secrets engine using token authentication.' +min_version: + mesh: '2.14' +weight: 830 +requirements: + - "A [MeshService](/mesh/meshservice/) resource must be configured in your mesh." + - "A Vault PKI secrets engine mounted at `kong-mesh-pki-default` with a `dataplanes` role allowing the mesh trust domain." + - "A {{site.mesh_product_name}} `Secret` named `vault-token` holding a Vault token authorized to issue from the PKI role." +namespace: kong-mesh-system +config: + type: MeshIdentity + name: identity-vault + mesh: default + spec: + selector: + dataplane: + matchLabels: {} + provider: + type: Extension + extension: + name: vault + config: + connection: + type: Server + server: + address: https://vault.vault.svc:8200 + tls: + caCert: + type: Secret + secretRef: + kind: Secret + name: vault-ca + auth: + type: Token + token: + type: Secret + secretRef: + kind: Secret + name: vault-token + pki: + mount: kong-mesh-pki-default + role: dataplanes + certificateParameters: + expiry: 24h diff --git a/app/_mesh_policies/meshidentity/index.md b/app/_mesh_policies/meshidentity/index.md index c3e8274779..402bd3c428 100644 --- a/app/_mesh_policies/meshidentity/index.md +++ b/app/_mesh_policies/meshidentity/index.md @@ -108,7 +108,7 @@ The following key fields define how identities are issued and applied: * [`selector`](#selector): Which data plane proxies this identity applies to. * [`spiffeID`](#spiffeid): How the SPIFFE ID is constructed (trust domain and path). -* [`provider`](#provider): Which system issues the certificates (`Bundled` or `Spire`). +* [`provider`](#provider): Which system issues the certificates (`Bundled`, `Spire`, or an external CA through the `Extension` provider). ### Selector @@ -249,3 +249,263 @@ This field is required and must specify one of the supported provider types: * `Bundled`: Certificates are issued by {{site.mesh_product_name}}'s control plane, either autogenerated or supplied by the user. * `Spire`: Certificates are issued directly by a SPIRE Agent through SDS. +* `Extension`: Certificates are issued by an external certificate authority. {{site.mesh_product_name}} ships the following extension providers: [HashiCorp Vault](#hashicorp-vault), [cert-manager](#cert-manager), and [AWS Private CA](#aws-private-ca). + +When using an `Extension` provider, set `provider.type` to `Extension`, choose the provider with `provider.extension.name`, and configure it under `provider.extension.config`. +All extension providers are SPIFFE compliant: {{site.mesh_product_name}} generates a certificate signing request for the workload's SPIFFE ID and the external CA signs it. +The control plane can also create the matching [`MeshTrust`](/mesh/policies/meshtrust/) from the provider's CA chain. Set `meshTrustCreation: Disabled` to manage `MeshTrust` resources yourself. + +{:.note} +> Secrets referenced through `secretRef` are {{site.mesh_product_name}} [`Secret`](/mesh/secure-deployment/secrets/) resources stored in the control plane namespace and labeled with `kuma.io/mesh`. Every secure data source field also accepts `file`, `envVar`, or `insecureInline` (development only) instead of `secretRef`. + +#### HashiCorp Vault {% new_in 2.14 %} + +The `vault` extension provider issues workload certificates from a [Vault PKI secrets engine](https://developer.hashicorp.com/vault/docs/secrets/pki). + +Prerequisites: + +* A mounted PKI secrets engine. The default mount path is `kong-mesh-pki-`. +* A PKI role (default `dataplanes`) that allows the mesh trust domain, for example permitting SANs that match `spiffe:///*`. +* A Vault policy that grants the control plane access to the role: + +```hcl +path "kong-mesh-pki-default/issue/dataplanes" { capabilities = ["create", "update"] } +path "kong-mesh-pki-default/ca_chain" { capabilities = ["read"] } +path "kong-mesh-pki-default/ca/pem" { capabilities = ["read"] } +``` + +The control plane supports three authentication methods (`Token`, `TLS`, and `AWS`) and can connect either directly to a Vault server or to a local Vault Agent. +The following example authenticates with a static token stored as a {{site.mesh_product_name}} `Secret`: + +```yaml +apiVersion: kuma.io/v1alpha1 +kind: MeshIdentity +metadata: + name: identity-vault + namespace: {{site.mesh_namespace}} + labels: + kuma.io/mesh: default +spec: + selector: + dataplane: + matchLabels: {} + provider: + type: Extension + extension: + name: vault + config: + connection: + type: Server + server: + address: https://vault.vault.svc:8200 + tls: + caCert: + type: Secret + secretRef: + kind: Secret + name: vault-ca + auth: + type: Token + token: + type: Secret + secretRef: + kind: Secret + name: vault-token + pki: + mount: kong-mesh-pki-default + role: dataplanes + certificateParameters: + expiry: 24h +``` + +Rotating the token is non-disruptive: update the `value` of the referenced `Secret` and the control plane uses the new token on the next certificate issuance. + +To authenticate with a TLS client certificate, set `auth.type` to `TLS` and provide `clientCert` and `clientKey`: + +```yaml + connection: + type: Server + server: + address: https://vault.vault.svc:8200 + auth: + type: TLS + tls: + clientCert: + type: Secret + secretRef: { kind: Secret, name: vault-client-cert } + clientKey: + type: Secret + secretRef: { kind: Secret, name: vault-client-key } +``` + +To use Vault's AWS auth method, set `auth.type` to `AWS`. Credentials come from the standard AWS credential chain (environment, instance profile, or IRSA), so no secret is stored in the mesh: + +```yaml + connection: + type: Server + server: + address: https://vault.example.com:8200 + auth: + type: AWS + aws: + type: IAM + role: kong-mesh + mount: aws +``` + +To delegate authentication to a [Vault Agent](https://developer.hashicorp.com/vault/docs/agent-and-proxy/agent) sidecar, set `connection.type` to `Agent` and omit `auth`: + +```yaml + connection: + type: Agent + agent: + address: http://127.0.0.1:8100 + pki: + mount: kong-mesh-pki-default +``` + +The following table describes the `vault` configuration fields: + +{% table %} +columns: + - title: Field + key: field + - title: Description + key: description +rows: + - field: "`connection.type`" + description: "`Server` for a direct connection or `Agent` for a local Vault Agent." + - field: "`connection.namespace`" + description: "Vault namespace (Vault Enterprise only)." + - field: "`connection.server.address`" + description: "URL of the Vault server." + - field: "`connection.server.tls.caCert`" + description: "CA certificate used to verify Vault's TLS certificate." + - field: "`connection.server.tls.skipVerify`" + description: "Disable TLS verification. Development only." + - field: "`connection.server.auth.type`" + description: "Authentication method: `Token`, `TLS`, or `AWS`." + - field: "`pki.mount`" + description: "PKI mount path. Defaults to `kong-mesh-pki-`." + - field: "`pki.role`" + description: "PKI role used to issue certificates. Defaults to `dataplanes`." + - field: "`pki.certificateParameters.expiry`" + description: "Requested certificate lifetime (default `24h`). Capped by the PKI role `max_ttl`." + - field: "`meshTrustCreation`" + description: "`Enabled` (default) or `Disabled`." +{% endtable %} + +#### cert-manager {% new_in 2.14 %} + +The `certmanager` extension provider issues workload certificates through a [cert-manager](https://cert-manager.io/) `Issuer` or `ClusterIssuer`. This provider works on Kubernetes only. + +Prerequisites: + +* cert-manager installed in the cluster. +* An `Issuer` or `ClusterIssuer` that can sign certificates with a URI SAN containing the workload's SPIFFE ID. A CA issuer is the common choice. + +cert-manager does not expose the issuing CA to the mesh automatically, so provide its CA certificate (as a {{site.mesh_product_name}} `Secret`) for `MeshTrust` auto-creation: + +```yaml +apiVersion: kuma.io/v1alpha1 +kind: MeshIdentity +metadata: + name: identity-certmanager + namespace: {{site.mesh_namespace}} + labels: + kuma.io/mesh: default +spec: + selector: + dataplane: + matchLabels: {} + provider: + type: Extension + extension: + name: certmanager + config: + issuerRef: + name: ca-issuer + kind: ClusterIssuer + group: cert-manager.io + caCert: + type: Secret + secretRef: + kind: Secret + name: meshidentity-certmanager-ca + certificateParameters: + expiry: 24h +``` + +If you omit `caCert`, set `meshTrustCreation: Disabled` and create the `MeshTrust` resource manually. + +The following table describes the `certmanager` configuration fields: + +{% table %} +columns: + - title: Field + key: field + - title: Description + key: description +rows: + - field: "`issuerRef.name`" + description: "Name of the `Issuer` or `ClusterIssuer`. Required." + - field: "`issuerRef.kind`" + description: "`Issuer` or `ClusterIssuer`. Defaults to `Issuer`." + - field: "`issuerRef.group`" + description: "API group of the issuer. Defaults to `cert-manager.io`." + - field: "`caCert`" + description: "Issuing CA certificate, used for `MeshTrust` auto-creation." + - field: "`certificateParameters.expiry`" + description: "Requested certificate lifetime (default `24h`)." + - field: "`meshTrustCreation`" + description: "`Enabled` (default, requires `caCert`) or `Disabled`." +{% endtable %} + +#### AWS Private CA {% new_in 2.14 %} + +The `acmpca` extension provider signs workload certificates with an [AWS Private CA](https://docs.aws.amazon.com/privateca/latest/userguide/PcaWelcome.html). + +Prerequisites: + +* An active AWS Private CA whose template allows certificates with a SPIFFE URI SAN. +* AWS credentials available to the control plane through the standard AWS credential chain (environment variables, instance profile, or IRSA — IRSA is recommended on EKS). The AWS region is taken from the CA ARN, so no separate region setting is required. +* IAM permissions on the control plane identity: `acm-pca:IssueCertificate`, `acm-pca:GetCertificate`, and `acm-pca:GetCertificateAuthorityCertificate`. + +```yaml +apiVersion: kuma.io/v1alpha1 +kind: MeshIdentity +metadata: + name: identity-acmpca + namespace: {{site.mesh_namespace}} + labels: + kuma.io/mesh: default +spec: + selector: + dataplane: + matchLabels: {} + provider: + type: Extension + extension: + name: acmpca + config: + arn: arn:aws:acm-pca:eu-central-1:123456789012:certificate-authority/12345678-1234-1234-1234-123456789012 + certificateParameters: + expiry: 24h +``` + +The following table describes the `acmpca` configuration fields: + +{% table %} +columns: + - title: Field + key: field + - title: Description + key: description +rows: + - field: "`arn`" + description: "ARN of the AWS Private CA. Required. The AWS region is parsed from this value." + - field: "`certificateParameters.expiry`" + description: "Requested certificate lifetime (default `24h`)." + - field: "`meshTrustCreation`" + description: "`Enabled` (default) or `Disabled`. When enabled, the control plane fetches the CA chain and builds the `MeshTrust`." +{% endtable %}