apiVersion: apiextensions.crossplane.io/v1 kind: CompositeResourceDefinition metadata: name: xbaseapplicationinfrastructures.scubbo.org spec: group: scubbo.org names: kind: xBaseApplicationInfrastructure plural: xbaseapplicationinfrastructures claimNames: kind: BaseAppInfra plural: baseappinfras versions: - name: v1alpha1 served: true referenceable: true schema: openAPIV3Schema: type: object properties: spec: type: object properties: appName: type: string --- # Sources for the Vault resources are here: # https://developer.hashicorp.com/vault/tutorials/kubernetes/vault-secrets-operator#configure-vault apiVersion: apiextensions.crossplane.io/v1 kind: Composition metadata: name: base-application-infrastructure spec: compositeTypeRef: apiVersion: scubbo.org/v1alpha1 kind: xBaseApplicationInfrastructure resources: - name: vault-role base: apiVersion: kubernetes.vault.upbound.io/v1alpha1 kind: AuthBackendRole spec: providerConfigRef: name: vault-provider-config forProvider: audience: vault boundServiceAccountNames: - default tokenMaxTtl: 86400 tokenTtl: 86400 patches: - type: FromCompositeFieldPath # https://docs.crossplane.io/latest/concepts/composite-resources/#claim-namespace-label fromFieldPath: metadata.labels["crossplane.io/claim-namespace"] toFieldPath: spec.forProvider.boundServiceAccountNamespaces transforms: - type: string string: type: Format fmt: "[\"%s\"]" - type: convert convert: toType: array format: json - type: FromCompositeFieldPath fromFieldPath: spec.appName toFieldPath: spec.forProvider.roleName transforms: - type: string string: type: Format fmt: "vault-secrets-operator-%s-role" - type: FromCompositeFieldPath fromFieldPath: spec.appName toFieldPath: spec.forProvider.tokenPolicies transforms: - type: string string: type: Format fmt: "[\"vault-secrets-operator-%s-policy\"]" - type: convert convert: toType: array format: json - name: vault-secrets-mount base: apiVersion: vault.vault.upbound.io/v1alpha1 kind: Mount spec: providerConfigRef: name: vault-provider-config forProvider: type: kv-v2 patches: - type: FromCompositeFieldPath fromFieldPath: spec.appName toFieldPath: spec.forProvider.path transforms: - type: string string: type: Format fmt: "app-%s-kv" - type: FromCompositeFieldPath fromFieldPath: spec.appName toFieldPath: spec.forProvider.description transforms: - type: string string: type: Format fmt: "KV storage for app %s" - name: vault-policy base: apiVersion: vault.vault.upbound.io/v1alpha1 kind: Policy spec: providerConfigRef: name: vault-provider-config forProvider: {} patches: - type: FromCompositeFieldPath fromFieldPath: spec.appName toFieldPath: spec.forProvider.name transforms: - type: string string: type: Format fmt: "vault-secrets-operator-%s-policy" - type: FromCompositeFieldPath fromFieldPath: spec.appName toFieldPath: spec.forProvider.policy transforms: - type: string string: type: Format fmt: "path \"app-%s-kv/*\" {capabilities=[\"read\"]}" # Note that this is an `Object` created by provider-kubernetes, not by provider-vault - name: vault-auth base: apiVersion: kubernetes.crossplane.io/v1alpha2 kind: Object spec: providerConfigRef: name: kubernetes-provider forProvider: manifest: apiVersion: secrets.hashicorp.com/v1beta1 kind: VaultAuth spec: method: kubernetes mount: kubernetes # Hard-coded - this is what I used in my setup, but this could be customizable kubernetes: serviceAccount: default audiences: - vault patches: # The Vault Role created earlier in this Composition - type: FromCompositeFieldPath fromFieldPath: spec.appName toFieldPath: spec.forProvider.manifest.spec.kubernetes.role transforms: - type: string string: type: Format fmt: "vault-secrets-operator-%s-role" - type: FromCompositeFieldPath fromFieldPath: spec.appName toFieldPath: spec.forProvider.manifest.metadata.name transforms: - type: string string: type: Format fmt: "vault-auth-%s" - type: FromCompositeFieldPath fromFieldPath: metadata.labels["crossplane.io/claim-namespace"] toFieldPath: spec.forProvider.manifest.metadata.namespace