feat: sanitize ECS snapshot tag keys and add per-BSL/VSL credential support - #66
Conversation
…upport
## Tag sanitization (fixes InvalidTagKey.Malformed)
Alibaba Cloud ECS rejects tag keys containing '/' or other characters
outside [a-zA-Z0-9_\-.]. Velero passes standard keys like
'velero.io/backup' and 'kubernetes.io/cluster/<name>' that trigger this
error on every snapshot backup.
- Add sanitizeTagKey() that replaces invalid chars with '_', skips keys
with forbidden prefixes (aliyun, acs:, http://, https://), and
truncates to 128 chars
- Apply sanitization in getTags() and getTagsForCluster()
- Fix dedup in getTags() to track emitted sanitized keys (not raw keys)
to avoid collision when two raw keys map to the same sanitized key
- Add legacyVolumeAZTagKey constant and check both old (slash) and new
(underscore) key in determineVolumeAZ() so existing snapshots restore
to the correct AZ after upgrade
## Per-location credential support
Add three optional BSL/VSL config keys — accessKeyId, accessKeySecret,
and stsToken — that allow per-location credentials to be specified
directly in the location config. When accessKeyId and accessKeySecret
are both present they take priority over all other credential sources
for that location.
Velero v1.10+ also supports spec.credential on BSL/VSL objects, which
references a Kubernetes Secret. Velero mounts the secret and injects
credentialsFile into the plugin config. The plugin reads this via the
existing credentialsFile config key path — no extra code needed. This
enables independent credentials for BSL and VSL on the same deployment.
Both approaches are fully backward compatible: the existing auth methods
(env vars, credentialsFile, RAM role, ECS metadata) are preserved and
used when neither credential source is present.
Add unit tests covering all new code paths.
Signed-off-by: Noman Uddin <noman.uddin@live.com>
52606a8 to
939a0f7
Compare
|
Thanks for the PR! I authored #67 which has already been merged into master. However, that fix intentionally only filters out the acs: prefix — these are system-reserved tags that the ECS backend silently adds to volumes/snapshots (e.g. acs:ecs:createdBy) and are known to be rejected by Create* APIs.
|
|
Also, I've submitted #68 which takes a different approach to the per-location credential isolation problem. Would appreciate your thoughts on it. The key difference is in how The root cause of the isolation issue is that
My concern with the inline config keys approach is that it adds a parallel credential path while the underlying For your second issue (per-BSL/VSL credentials): could you check if #68 addresses your scenario? It uses Velero's standard |
Fixes #64
Problem
1. InvalidTagKey.Malformed on volume backups
Velero passes tag keys such as
velero.io/backupandvelero.io/pvwhencalling
CreateSnapshot. ECS disks may also carry CSI-assigned tags likekubernetes.io/created-for/pvc/name. All of these contain/which isrejected by the Alibaba Cloud ECS tag key validation, causing every volume
backup to fail with
InvalidTagKey.Malformed.2. No per-location credential support
BSL and VSL share the same process-wide env vars, making it impossible to
use different credentials for object store (BSL) and volume snapshots (VSL)
on the same Velero deployment — e.g. a static access key for BSL
alongside an ECS instance RAM role for VSL.
Solution
1. Tag key sanitization (
volume_snapshotter.go)Add
sanitizeTagKey()which:[a-zA-Z0-9_\-\.]with_aliyun,acs:,http://,https://)Applied in
getTags()for both Velero-supplied and volume-copied tags.Also fixes
originalVolumeAZTagKeyconstant which itself contained a/.2. Per-BSL/VSL credential support (
common.go)Add three optional config keys for BackupStorageLocation and VolumeSnapshotLocation:
accessKeyIdaccessKeySecretstsTokenTwo credential patterns are now supported:
Shared credential (existing): a single Kubernetes Secret used for both BSL and VSL,
passed via
--secret-fileorspec.credential— works for most cases.Per-location credential (new): set
spec.credentialon each BSL/VSL to referencea separate Kubernetes Secret (same approach as the AWS plugin). Velero v1.10+ mounts
each secret and injects
credentialsFileinto the plugin config per location.Alternatively, set
accessKeyId+accessKeySecretdirectly in the BSL/VSL configwhen a Kubernetes Secret is not available.
All existing auth methods (env vars,
credentialsFile, RAM role) are fully preservedas fallback: fully backward compatible.
Testing
sanitizeTagKeycovering all edge casesLocal kind cluster validation (Velero 1.11.0, linux/amd64)
spec.credentialon each locationNote on tag sanitization validation: The
sanitizeTagKey()logic is covered by 11 unittests. End-to-end validation on real ECS snapshots is pending deployment to a live cluster
— the fix addresses the
InvalidTagKey.Malformederrors observed in production logs where328+ errors were recorded per backup run.
I noticed PR #65 addresses a similar issue by filtering out tags with forbidden prefixes (
acs:,aliyun,http://,https://). This PR takes a different and more complete approach:velero.io/backup,velero.io/pv) would also be silently discarded since they contain/which is invalid._rather than dropping the tag entirely. This means Velero's own metadata tags are preserved asvelero.io_backup,velero.io_pvetc., keeping the snapshot traceable back to the originating backup.The two fixes are complementary: happy to coordinate or consolidate if the maintainers prefer a single PR.