NAME
IO::K8s::ExternalSecrets - external-secrets CRD resource map provider for IO::K8s
VERSION
version 1.108
SYNOPSIS
my $k8s = IO::K8s->new(with => ['IO::K8s::ExternalSecrets']);
my $store = $k8s->new_object('SecretStore',
metadata => { name => 'aws-store', namespace => 'default' },
spec => {
provider => {
aws => {
service => 'SecretsManager',
region => 'eu-west-1',
auth => { jwt => { serviceAccountRef => { name => 'my-sa' } } },
},
},
},
);
my $es = $k8s->new_object('ExternalSecret',
metadata => { name => 'db-creds', namespace => 'default' },
spec => {
secretStoreRef => { name => 'aws-store', kind => 'SecretStore' },
target => { name => 'db-creds' },
data => [ { secretKey => 'password', remoteRef => { key => 'prod/db/password' } } ],
},
);
print $es->to_yaml;
DESCRIPTION
Resource map provider for external-secrets Custom Resource Definitions. Registers 25 resource_map entries: six Kinds in external-secrets.io and 19 Kinds in generators.external-secrets.io/v1alpha1 (see "Included Kinds (generators.external-secrets.io/v1alpha1)" below), matching upstream external-secrets v2.10.0.
generators.external-secrets.io is a separate upstream API group (Go package apis/generators/v1alpha1, not apis/externalsecrets/*) from the two above, despite sharing both the v1alpha1 version string and, in this distribution, the V1alpha1 Perl namespace with PushSecret's own group -- the same one-provider/two-groups layout IO::K8s::CertManager already uses for cert-manager.io/v1 + acme.cert-manager.io/v1. Each class's own api_version carries the distinction, not a path segment.
Every Kind is modeled to full depth: spec (and, where upstream declares one, status) is a typed object graph of further IO::K8s::ExternalSecrets::V1::* / IO::K8s::ExternalSecrets::V1alpha1::* classes, one per upstream Go structure, named after the upstream Go types (github.com/external-secrets/external-secrets/apis/externalsecrets/v1 and .../v1alpha1). Embedded core Kubernetes types are referenced, not re-modeled -- e.g. a condition list reuses a shipped Core::V1/Meta::V1 condition-shaped class rather than a per-Kind copy (D5's reuse_core), and several small cross-provider reference structs -- IO::K8s::ExternalSecrets::V1::SecretKeySelector (external-secrets' own, cross-namespace-capable variant, not Core::V1::SecretKeySelector), IO::K8s::ExternalSecrets::V1::ServiceAccountSelector, IO::K8s::ExternalSecrets::V1::CAProvider -- are the literal same upstream Go type referenced from dozens of places (every provider's own auth block, for the first two) rather than one copy per backend.
SecretStore and ClusterSecretStore embed the identical upstream SecretStoreSpec/SecretStoreStatus Go types (verified byte-identical schema before writing these classes) and so share the very same IO::K8s::ExternalSecrets::V1::SecretStoreSpec class -- including its provider field, IO::K8s::ExternalSecrets::V1::SecretStoreProvider, a 43-member union of every backend the CRD's MinProperties=1/ MaxProperties=1 validation restricts to exactly one of (AWS, Azure Key Vault, HashiCorp Vault, GCP Secret Manager, Kubernetes, Akeyless, and so on -- see "Included Kinds (external-secrets.io/v1)" below for the full list), each backend's own auth/reference structs modeled to full depth in turn. ClusterExternalSecret similarly embeds the literal same ExternalSecretSpec Go type ExternalSecret uses for its own spec (as spec.externalSecretSpec), so IO::K8s::ExternalSecrets::V1::ExternalSecretSpec and everything below it (ExternalSecretData, ExternalSecretTarget, IO::K8s::ExternalSecrets::V1::ExternalSecretTemplate, ...) is one shared tree of classes reachable from both Kinds. ClusterPushSecret mirrors that: it embeds the literal same PushSecretSpec Go type PushSecret uses for its own spec (as spec.pushSecretSpec), so IO::K8s::ExternalSecrets::V1alpha1::PushSecretSpec and everything below it is shared rather than re-modeled; its own wrapper fields (namespaceSelectors, pushSecretMetadata, pushSecretName, refreshTime) live on IO::K8s::ExternalSecrets::V1alpha1::ClusterPushSecretSpec. Its status.conditions reuses the same IO::K8s::Api::Core::V1::NamespaceCondition class PushSecretStatus already reuses for the identical PushSecretStatusCondition Go type.
Scope (D9): ClusterSecretStore, ClusterExternalSecret, ClusterPushSecret and ClusterGenerator are cluster-scoped upstream (spec.scope: Cluster) and do not compose IO::K8s::Role::Namespaced; ExternalSecret, SecretStore and PushSecret are namespaced upstream and do.
Served versions: the CRD manifest at this pin still ships a deprecated external-secrets.io/v1beta1 track for ExternalSecret, SecretStore and ClusterSecretStore (and a deprecated v1beta1 for ClusterExternalSecret), but every one of those entries is served: false in the manifest -- an API server at this upstream version would reject a request naming it. Only the served version of each Kind is modeled: v1 for ExternalSecret, SecretStore, ClusterSecretStore and ClusterExternalSecret; v1alpha1 for PushSecret and ClusterPushSecret, neither of which has graduated to v1 at this pin.
Not loaded by default -- opt in via the with constructor parameter of IO::K8s or by calling $k8s->add('IO::K8s::ExternalSecrets') at runtime.
Included Kinds (external-secrets.io/v1)
ExternalSecret, SecretStore, ClusterSecretStore, ClusterExternalSecret
SecretStore/ClusterSecretStore's spec.provider backends: AWS, AzureKV, Akeyless, BitwardenSecretsManager, Vault, OVHcloud, GCPSM, Oracle, IBM, YandexCertificateManager, YandexLockbox, Github, GitLab, OnePassword, OnePasswordSDK, Webhook, Kubernetes, CRD, Fake, Senhasegura, Scaleway, Doppler, Previder, Onboardbase, KeeperSecurity, Conjur, Delinea, SecretServer, Chef, Pulumi, Fortanix, PasswordDepot, Passbolt, DVLS, Infisical, Beyondtrust, BeyondtrustWorkloadCredentials, CloudruSM, Volcengine, Ngrok, Barbican, NebiusMysterybox, OpenBao.
Included Kinds (external-secrets.io/v1alpha1)
PushSecret, ClusterPushSecret
Included Kinds (generators.external-secrets.io/v1alpha1)
ClusterGenerator (cluster-scoped), ACRAccessToken, BeyondtrustWorkloadCredentialsDynamicSecret, CloudsmithAccessToken, ECRAuthorizationToken, Fake, GCRAccessToken, GeneratorState, GithubAccessToken, GitlabDeployToken, Grafana, MFA, Password, QuayAccessToken, SSHKey, STSSessionToken, UUID, VaultDynamicSecret, Webhook.
Where an upstream schema was verified byte-identical to an existing external-secrets.io/v1 provider structure, the generator reuses that same class rather than a private copy: VaultDynamicSecret's provider is the literal same IO::K8s::ExternalSecrets::V1::VaultProvider SecretStore's Vault backend uses, and BeyondtrustWorkloadCredentialsDynamicSecret's provider is the literal same IO::K8s::ExternalSecrets::V1::BeyondtrustWorkloadCredentialsProvider. ECRAuthorizationToken and STSSessionToken both reuse IO::K8s::ExternalSecrets::V1::AWSAuth for their auth field. GeneratorState reuses IO::K8s::Api::Core::V1::NamespaceCondition for status.conditions, the same way PushSecretStatus does. A handful of generator-only fields narrow the usual cross-namespace SecretKeySelector down to a same-namespace, two-field IO::K8s::ExternalSecrets::V1alpha1::SecretRef (Grafana's auth.basic.password/auth.token, Webhook's secrets[].secretRef).
ClusterGenerator is modeled as the cluster-scoped generator union. Its spec.generator has 17 members, each reusing the corresponding standalone Kind's Spec class; GeneratorState is controller state rather than a generator plugin and is not a union member.
SEE ALSO
external-secrets documentation
external-secrets API reference
SUPPORT
Issues
Please report bugs and feature requests on GitHub at https://github.com/pplu/io-k8s-p5/issues.
CONTRIBUTING
Contributions are welcome! Please fork the repository and submit a pull request.
AUTHORS
Torsten Raudssus <getty@cpan.org>
Jose Luis Martinez Torres <jlmartin@cpan.org>
COPYRIGHT AND LICENSE
This software is Copyright (c) 2018-2026 by Jose Luis Martinez Torres <jlmartin@cpan.org>.
This is free software, licensed under:
The Apache License, Version 2.0, January 2004