Summary
The linode object-storage provider sources the two halves of the S3 credential asymmetrically: secretAccessKey is read from the obj-secrets Secret (great — an operator can populate it via ESO and rotate freely), but accessKeyId is inlined from git settings. Because Linode OBJ keys rotate as a pair, this forces any operator that rotates keys to write the new accessKeyId back into the values git repo on every rotation — carrying a non-secret identifier through git solely because its paired secret is handled cleanly.
Request: let accessKeyId also be sourced from obj-secrets (or a native Secret), symmetric with secretAccessKey.
Current behavior (apl-core v6.0.0)
From the templating:
values/loki/loki-raw.gotmpl
AWS_ACCESS_KEY_ID: {{ $obj.linode.accessKeyId }} # inlined from env/settings/obj.yaml (git)
AWS_SECRET_ACCESS_KEY: '{{ "{{ .secretAccessKey | toString }}" }}'
- secretKey: secretAccessKey
remoteRef:
key: obj-secrets # from the obj-secrets Secret (ESO-friendly)
property: provider_linode_secretAccessKey
values/harbor/harbor-raw.gotmpl does the same (S3_STORAGE_ACCOUNT / REGISTRY_STORAGE_S3_ACCESSKEY ← {{ $obj.linode.accessKeyId }}; secret ← obj-secrets.provider_linode_secretAccessKey).
And env/settings/obj.yaml (AplObjectStorage) carries spec.provider.linode.accessKeyId as a plain setting (schema additionalProperties: false, so the secret half is deliberately kept out).
Why it's a problem
A managed-App-Platform operator that provisions and rotates the OBJ access keys out-of-band (our case: Linode Landing Zone) can deliver secretAccessKey into obj-secrets via ESO/OpenBao and rotate with zero git writes — exactly right. But because accessKeyId is git-inlined and a rotation mints a new pair, the operator must also push the new accessKeyId into the values repo each rotation to keep it paired. That forces a git-sync reconciler holding a Contents: write token — a lot of moving parts to carry a non-secret identifier that changes on the same cadence as the secret already handled cleanly.
Proposed options
- Extend the
obj-secrets contract: add a provider_linode_accessKeyId property and template AWS_ACCESS_KEY_ID from it (mirroring secretAccessKey). Operators populate one Secret with both keys via ESO; no git writes on rotation.
- Optional secret ref: add
spec.provider.linode.accessKeyIdSecretRef (nativeSecrets-style). When set, source accessKeyId from the referenced Secret; otherwise fall back to the inline settings value (fully backward compatible).
Either makes the two halves of the credential rotate together through one ESO-managed Secret, and lets external operators drop the git-write token + reconciler they otherwise need only for the access-key id.
Environment
- apl-core
v6.0.0 (managed App Platform / apl-operator 1.16.0)
- Provider:
linode; consumers observed: Loki, Harbor (same pattern in gitea/keycloak/kubeflow-pipelines -raw.gotmpl)
Summary
The
linodeobject-storage provider sources the two halves of the S3 credential asymmetrically:secretAccessKeyis read from theobj-secretsSecret (great — an operator can populate it via ESO and rotate freely), butaccessKeyIdis inlined from git settings. Because Linode OBJ keys rotate as a pair, this forces any operator that rotates keys to write the newaccessKeyIdback into the values git repo on every rotation — carrying a non-secret identifier through git solely because its paired secret is handled cleanly.Request: let
accessKeyIdalso be sourced fromobj-secrets(or a native Secret), symmetric withsecretAccessKey.Current behavior (apl-core v6.0.0)
From the templating:
values/loki/loki-raw.gotmplAWS_ACCESS_KEY_ID: {{ $obj.linode.accessKeyId }} # inlined from env/settings/obj.yaml (git) AWS_SECRET_ACCESS_KEY: '{{ "{{ .secretAccessKey | toString }}" }}' - secretKey: secretAccessKey remoteRef: key: obj-secrets # from the obj-secrets Secret (ESO-friendly) property: provider_linode_secretAccessKeyvalues/harbor/harbor-raw.gotmpldoes the same (S3_STORAGE_ACCOUNT/REGISTRY_STORAGE_S3_ACCESSKEY←{{ $obj.linode.accessKeyId }}; secret ←obj-secrets.provider_linode_secretAccessKey).And
env/settings/obj.yaml(AplObjectStorage) carriesspec.provider.linode.accessKeyIdas a plain setting (schemaadditionalProperties: false, so the secret half is deliberately kept out).Why it's a problem
A managed-App-Platform operator that provisions and rotates the OBJ access keys out-of-band (our case: Linode Landing Zone) can deliver
secretAccessKeyintoobj-secretsvia ESO/OpenBao and rotate with zero git writes — exactly right. But becauseaccessKeyIdis git-inlined and a rotation mints a new pair, the operator must also push the newaccessKeyIdinto the values repo each rotation to keep it paired. That forces a git-sync reconciler holding aContents: writetoken — a lot of moving parts to carry a non-secret identifier that changes on the same cadence as the secret already handled cleanly.Proposed options
obj-secretscontract: add aprovider_linode_accessKeyIdproperty and templateAWS_ACCESS_KEY_IDfrom it (mirroringsecretAccessKey). Operators populate one Secret with both keys via ESO; no git writes on rotation.spec.provider.linode.accessKeyIdSecretRef(nativeSecrets-style). When set, sourceaccessKeyIdfrom the referenced Secret; otherwise fall back to the inline settings value (fully backward compatible).Either makes the two halves of the credential rotate together through one ESO-managed Secret, and lets external operators drop the git-write token + reconciler they otherwise need only for the access-key id.
Environment
v6.0.0(managed App Platform / apl-operator1.16.0)linode; consumers observed: Loki, Harbor (same pattern in gitea/keycloak/kubeflow-pipelines-raw.gotmpl)