ci: authenticate to AWS via GitHub OIDC using the role_arn credential path (#1582)

This repo is public and held a long-lived AWS access key as repository secrets
(set 2023-11-22). It is replaced with short-lived credentials from the GitHub OIDC
provider; no AWS key and no account id remain in the repo.

create-test-db.js wrote {access_key_id, secret_access_key, aws_region} into the test
database as the aws speech credential, which sends speech-utils' getAwsAuthToken down
its access-key branch and calls GetSessionToken -- rejected by AWS for session
credentials. The role_arn branch calls AssumeRole instead, which accepts them, and is
already plumbed through db-utils.js, call-session.js and stt-task.js. The pinned
speech-utils 0.2.30 already supports it, so no dependency change is needed.

Fork pull requests receive neither secrets nor an OIDC token, so the credentials step
is guarded by a condition; the AWS tests then skip for forks exactly as they do today.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Dave Horton
2026-08-26 13:53:14 -04:00
committed by GitHub
co-authored by Claude Opus 5
parent db18b558ce
commit a6663198da
5 changed files with 37 additions and 9 deletions
+14 -1
View File
@@ -5,6 +5,7 @@ const {encrypt} = require('../lib/utils/encrypt-decrypt');
const {
GCP_JSON_KEY,
AWS_ACCESS_KEY_ID,
AWS_ROLE_ARN,
AWS_SECRET_ACCESS_KEY,
AWS_REGION,
MICROSOFT_REGION,
@@ -32,7 +33,19 @@ test('creating schema', (t) => {
t.pass('adding google credentials');
sql.push(`UPDATE speech_credentials SET credential='${google_credential}' WHERE vendor='google';`);
}
if (AWS_ACCESS_KEY_ID && AWS_SECRET_ACCESS_KEY) {
// Prefer role_arn. Under GitHub OIDC the ambient credentials are temporary, and
// speech-utils' getAwsAuthToken calls GetSessionToken on its access-key branch --
// which AWS rejects for session credentials. The role_arn branch calls AssumeRole
// instead, which works with temporary credentials.
if (AWS_ROLE_ARN) {
const aws_credential = encrypt(JSON.stringify({
role_arn: AWS_ROLE_ARN,
aws_region: AWS_REGION
}));
t.pass('adding aws credentials (role_arn)');
sql.push(`UPDATE speech_credentials SET credential='${aws_credential}' WHERE vendor='aws';`);
}
else if (AWS_ACCESS_KEY_ID && AWS_SECRET_ACCESS_KEY) {
const aws_credential = encrypt(JSON.stringify({
access_key_id: AWS_ACCESS_KEY_ID,
secret_access_key: AWS_SECRET_ACCESS_KEY,
+2 -1
View File
@@ -7,6 +7,7 @@ const {provisionCallHook} = require('./utils')
const {
GCP_JSON_KEY,
AWS_ACCESS_KEY_ID,
AWS_ROLE_ARN,
AWS_SECRET_ACCESS_KEY,
SONIOX_API_KEY,
DEEPGRAM_API_KEY,
@@ -190,7 +191,7 @@ test('\'gather\' test - microsoft', async(t) => {
});
test('\'gather\' test - aws', async(t) => {
if (!AWS_ACCESS_KEY_ID || !AWS_SECRET_ACCESS_KEY) {
if (!AWS_ROLE_ARN && (!AWS_ACCESS_KEY_ID || !AWS_SECRET_ACCESS_KEY)) {
t.pass('skipping aws tests');
return t.end();
}
+3 -2
View File
@@ -6,7 +6,8 @@ const clearModule = require('clear-module');
const {provisionCallHook} = require('./utils')
const {
GCP_JSON_KEY,
AWS_ACCESS_KEY_ID,
AWS_ACCESS_KEY_ID,
AWS_ROLE_ARN,
AWS_SECRET_ACCESS_KEY,
MICROSOFT_REGION,
MICROSOFT_API_KEY,
@@ -103,7 +104,7 @@ test('\'transcribe\' test - microsoft', async(t) => {
});
test('\'transcribe\' test - aws', async(t) => {
if (!AWS_ACCESS_KEY_ID || !AWS_SECRET_ACCESS_KEY) {
if (!AWS_ROLE_ARN && (!AWS_ACCESS_KEY_ID || !AWS_SECRET_ACCESS_KEY)) {
t.pass('skipping aws tests');
return t.end();
}