ci: authenticate artifactapi upload with a vault token (#189)
ci/woodpecker/push/deploy-fedora43 Pipeline was successful
ci/woodpecker/push/deploy-almalinux9 Pipeline was successful
ci/woodpecker/push/deploy-fedora42 Pipeline was successful
ci/woodpecker/push/deploy-fedora44 Pipeline was successful

artifactapi is about to enforce auth on file uploads (`ARTIFACTAPI_AUTH_UPLOADS`), and the deploy pipelines PUT rpms anonymously.

- mint an `artifactapi-writer` OIDC token via Vault k8s auth (role `woodpecker_artifactapi_writer`) using the step SA token
- fail the step if minting fails (`set -o pipefail`)
- send the token as `Authorization: Bearer` via a header file on each rpm PUT
- apply to the almalinux9, fedora42, fedora43 and fedora44 deploy pipelines

Reviewed-on: #189
Co-authored-by: unkin-agent <unkin-agent@unkin.net>
Co-committed-by: unkin-agent <unkin-agent@unkin.net>
This commit was merged in pull request #189.
This commit is contained in:
2026-10-25 23:07:55 +11:00
committed by BenVincent
parent f4e9e52af3
commit c333ea078d
4 changed files with 32 additions and 4 deletions
+8 -1
View File
@@ -43,6 +43,13 @@ steps:
- |
HOST="https://artifactapi.k8s.syd1.au.unkin.net"
REPO="rpm-vendor-el9"
set -o pipefail
VAULT="https://vault.service.consul:8200"
AUTH=$$(mktemp)
VT=$$(jq -n --rawfile jwt /var/run/secrets/kubernetes.io/serviceaccount/token '{role:"woodpecker_artifactapi_writer",jwt:$$jwt}' \
| curl -sf -d @- "$$VAULT/v1/auth/k8s/au/syd1/login" | jq -er .auth.client_token) || exit 1
printf 'X-Vault-Token: %s\n' "$$VT" | curl -sf -H @- "$$VAULT/v1/identity/oidc/token/artifactapi-writer" \
| jq -er '"Authorization: Bearer " + .data.token' > "$$AUTH" || exit 1
for rpm in $(find /woodpecker/src/git.unkin.net/unkin/rpmbuilder/ -type f -name "*.rpm"); do
FILE=$$(basename "$$rpm")
# artifactapi has no HEAD route (405); probe the served Packages path.
@@ -51,7 +58,7 @@ steps:
echo "$$FILE already exists in $$REPO; skipping"
continue
fi
curl -f -X PUT "$$HOST/api/v2/remotes/$$REPO/files/$$FILE" -H "Content-Type: application/x-rpm" --data-binary @"$$rpm"
curl -f -X PUT "$$HOST/api/v2/remotes/$$REPO/files/$$FILE" -H "Content-Type: application/x-rpm" -H @"$$AUTH" --data-binary @"$$rpm"
done
backend_options:
kubernetes:
+8 -1
View File
@@ -43,6 +43,13 @@ steps:
- |
HOST="https://artifactapi.k8s.syd1.au.unkin.net"
REPO="rpm-vendor-f42"
set -o pipefail
VAULT="https://vault.service.consul:8200"
AUTH=$$(mktemp)
VT=$$(jq -n --rawfile jwt /var/run/secrets/kubernetes.io/serviceaccount/token '{role:"woodpecker_artifactapi_writer",jwt:$$jwt}' \
| curl -sf -d @- "$$VAULT/v1/auth/k8s/au/syd1/login" | jq -er .auth.client_token) || exit 1
printf 'X-Vault-Token: %s\n' "$$VT" | curl -sf -H @- "$$VAULT/v1/identity/oidc/token/artifactapi-writer" \
| jq -er '"Authorization: Bearer " + .data.token' > "$$AUTH" || exit 1
for rpm in $(find /woodpecker/src/git.unkin.net/unkin/rpmbuilder/ -type f -name "*.rpm"); do
FILE=$$(basename "$$rpm")
# artifactapi has no HEAD route (405); probe the served Packages path.
@@ -51,7 +58,7 @@ steps:
echo "$$FILE already exists in $$REPO; skipping"
continue
fi
curl -f -X PUT "$$HOST/api/v2/remotes/$$REPO/files/$$FILE" -H "Content-Type: application/x-rpm" --data-binary @"$$rpm"
curl -f -X PUT "$$HOST/api/v2/remotes/$$REPO/files/$$FILE" -H "Content-Type: application/x-rpm" -H @"$$AUTH" --data-binary @"$$rpm"
done
backend_options:
kubernetes:
+8 -1
View File
@@ -43,6 +43,13 @@ steps:
- |
HOST="https://artifactapi.k8s.syd1.au.unkin.net"
REPO="rpm-vendor-f43"
set -o pipefail
VAULT="https://vault.service.consul:8200"
AUTH=$$(mktemp)
VT=$$(jq -n --rawfile jwt /var/run/secrets/kubernetes.io/serviceaccount/token '{role:"woodpecker_artifactapi_writer",jwt:$$jwt}' \
| curl -sf -d @- "$$VAULT/v1/auth/k8s/au/syd1/login" | jq -er .auth.client_token) || exit 1
printf 'X-Vault-Token: %s\n' "$$VT" | curl -sf -H @- "$$VAULT/v1/identity/oidc/token/artifactapi-writer" \
| jq -er '"Authorization: Bearer " + .data.token' > "$$AUTH" || exit 1
for rpm in $(find /woodpecker/src/git.unkin.net/unkin/rpmbuilder/ -type f -name "*.rpm"); do
FILE=$$(basename "$$rpm")
# artifactapi has no HEAD route (405); probe the served Packages path.
@@ -51,7 +58,7 @@ steps:
echo "$$FILE already exists in $$REPO; skipping"
continue
fi
curl -f -X PUT "$$HOST/api/v2/remotes/$$REPO/files/$$FILE" -H "Content-Type: application/x-rpm" --data-binary @"$$rpm"
curl -f -X PUT "$$HOST/api/v2/remotes/$$REPO/files/$$FILE" -H "Content-Type: application/x-rpm" -H @"$$AUTH" --data-binary @"$$rpm"
done
backend_options:
kubernetes:
+8 -1
View File
@@ -43,6 +43,13 @@ steps:
- |
HOST="https://artifactapi.k8s.syd1.au.unkin.net"
REPO="rpm-vendor-f44"
set -o pipefail
VAULT="https://vault.service.consul:8200"
AUTH=$$(mktemp)
VT=$$(jq -n --rawfile jwt /var/run/secrets/kubernetes.io/serviceaccount/token '{role:"woodpecker_artifactapi_writer",jwt:$$jwt}' \
| curl -sf -d @- "$$VAULT/v1/auth/k8s/au/syd1/login" | jq -er .auth.client_token) || exit 1
printf 'X-Vault-Token: %s\n' "$$VT" | curl -sf -H @- "$$VAULT/v1/identity/oidc/token/artifactapi-writer" \
| jq -er '"Authorization: Bearer " + .data.token' > "$$AUTH" || exit 1
for rpm in $(find /woodpecker/src/git.unkin.net/unkin/rpmbuilder/ -type f -name "*.rpm"); do
FILE=$$(basename "$$rpm")
# artifactapi has no HEAD route (405); probe the served Packages path.
@@ -51,7 +58,7 @@ steps:
echo "$$FILE already exists in $$REPO; skipping"
continue
fi
curl -f -X PUT "$$HOST/api/v2/remotes/$$REPO/files/$$FILE" -H "Content-Type: application/x-rpm" --data-binary @"$$rpm"
curl -f -X PUT "$$HOST/api/v2/remotes/$$REPO/files/$$FILE" -H "Content-Type: application/x-rpm" -H @"$$AUTH" --data-binary @"$$rpm"
done
backend_options:
kubernetes: