Skip to content

test(aws): add real credential provider coverage #2

test(aws): add real credential provider coverage

test(aws): add real credential provider coverage #2

Workflow file for this run

# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
name: AWS V4 Live Test
on:
push:
branches:
- main
pull_request:
branches:
- main
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
cancel-in-progress: true
env:
RUST_LOG: DEBUG
RUST_BACKTRACE: full
AWS_REGION: ${{ vars.REQSIGN_AWS_LIVE_REGION }}
AWS_DEFAULT_REGION: ${{ vars.REQSIGN_AWS_LIVE_REGION }}
permissions: {}
jobs:
check_live_test:
runs-on: ubuntu-latest
outputs:
enabled: ${{ steps.check.outputs.enabled }}
steps:
- name: Check whether AWS live tests are trusted
id: check
shell: bash
run: |
if [[ "${{ github.event_name }}" == "push" || "${{ github.event_name }}" == "workflow_dispatch" || ( "${{ github.event_name }}" == "pull_request" && "${{ github.event.pull_request.head.repo.fork }}" == "false" && "${{ github.actor }}" != "dependabot[bot]" ) ]]; then
echo "enabled=true" >> "$GITHUB_OUTPUT"
else
echo "enabled=false" >> "$GITHUB_OUTPUT"
fi
test_hosted_providers:
needs: check_live_test
if: needs.check_live_test.outputs.enabled == 'true'
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Get a GitHub OIDC token
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const token = await core.getIDToken('sts.amazonaws.com');
core.setSecret(token);
require('fs').writeFileSync('/tmp/reqsign-aws-role-token', token, { mode: 0o600 });
- name: Assume the reqsign live-test role
env:
ROLE_ARN: ${{ vars.REQSIGN_AWS_LIVE_ROLE_ARN }}
ROLE_SESSION_NAME: reqsign-hosted-${{ github.run_id }}
shell: bash
run: |
credentials="$(aws sts assume-role-with-web-identity \
--role-arn "$ROLE_ARN" \
--role-session-name "$ROLE_SESSION_NAME" \
--web-identity-token "$(tr -d '\n' < /tmp/reqsign-aws-role-token)" \
--query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]' \
--output text)"
read -r access_key secret_key session_token <<< "$credentials"
test -n "$access_key" && test -n "$secret_key" && test -n "$session_token"
echo "::add-mask::$access_key"
echo "::add-mask::$secret_key"
echo "::add-mask::$session_token"
{
echo "AWS_ACCESS_KEY_ID=$access_key"
echo "AWS_SECRET_ACCESS_KEY=$secret_key"
echo "AWS_SESSION_TOKEN=$session_token"
} >> "$GITHUB_ENV"
- name: Test StaticCredentialProvider
working-directory: services/aws-v4
env:
REQSIGN_AWS_V4_TEST_STATIC: on
REQSIGN_AWS_V4_VALIDATE_CREDENTIALS: on
run: cargo test test_static_credential_provider_live --no-fail-fast -- --nocapture
- name: Test EnvCredentialProvider
working-directory: services/aws-v4
env:
REQSIGN_AWS_V4_TEST_ENV: on
REQSIGN_AWS_V4_VALIDATE_CREDENTIALS: on
run: cargo test test_env_credential_provider --no-fail-fast -- --nocapture
- name: Test DefaultCredentialProvider
working-directory: services/aws-v4
env:
REQSIGN_AWS_V4_TEST_DEFAULT: on
REQSIGN_AWS_V4_VALIDATE_CREDENTIALS: on
run: cargo test test_default_credential_provider_live --no-fail-fast -- --nocapture
- name: Create an ephemeral shared profile
shell: bash
run: |
test_home="$(mktemp -d)"
credentials_file="$test_home/credentials"
config_file="$test_home/config"
{
printf '[reqsign-live]\n'
printf 'aws_access_key_id = %s\n' "$AWS_ACCESS_KEY_ID"
printf 'aws_secret_access_key = %s\n' "$AWS_SECRET_ACCESS_KEY"
printf 'aws_session_token = %s\n' "$AWS_SESSION_TOKEN"
} > "$credentials_file"
{
printf '[profile reqsign-live]\n'
printf 'region = %s\n' "$AWS_REGION"
} > "$config_file"
chmod 600 "$credentials_file" "$config_file"
{
echo "REQSIGN_PROFILE_TEST_HOME=$test_home"
echo "REQSIGN_PROFILE_CREDENTIALS=$credentials_file"
echo "REQSIGN_PROFILE_CONFIG=$config_file"
} >> "$GITHUB_ENV"
- name: Test ProfileCredentialProvider
working-directory: services/aws-v4
env:
REQSIGN_AWS_V4_TEST_PROFILE: on
REQSIGN_AWS_V4_VALIDATE_CREDENTIALS: on
run: |
export AWS_PROFILE=reqsign-live
export AWS_SHARED_CREDENTIALS_FILE="$REQSIGN_PROFILE_CREDENTIALS"
export AWS_CONFIG_FILE="$REQSIGN_PROFILE_CONFIG"
cargo test test_profile_credential_provider --no-fail-fast -- --nocapture
- name: Create an ephemeral credential_process profile
shell: bash
run: |
process_home="$(mktemp -d)"
process_helper="$process_home/credential-process.py"
process_config="$process_home/config"
cp services/aws-v4/tests/mocks/credential_process_helper.py "$process_helper"
chmod 700 "$process_helper"
{
printf '[profile reqsign-live-process]\n'
printf 'credential_process = python3 %s\n' "$process_helper"
printf 'region = %s\n' "$AWS_REGION"
} > "$process_config"
chmod 600 "$process_config"
echo "REQSIGN_PROCESS_TEST_HOME=$process_home" >> "$GITHUB_ENV"
echo "REQSIGN_PROCESS_CONFIG=$process_config" >> "$GITHUB_ENV"
- name: Test ProcessCredentialProvider
working-directory: services/aws-v4
env:
REQSIGN_AWS_V4_TEST_PROCESS: on
REQSIGN_AWS_V4_VALIDATE_CREDENTIALS: on
run: |
export REQSIGN_AWS_PROCESS_ACCESS_KEY_ID="$AWS_ACCESS_KEY_ID"
export REQSIGN_AWS_PROCESS_SECRET_ACCESS_KEY="$AWS_SECRET_ACCESS_KEY"
export REQSIGN_AWS_PROCESS_SESSION_TOKEN="$AWS_SESSION_TOKEN"
export AWS_PROFILE=reqsign-live-process
export AWS_CONFIG_FILE="$REQSIGN_PROCESS_CONFIG"
cargo test test_process_credential_provider --no-fail-fast -- --nocapture
- name: Test AssumeRoleCredentialProvider and granter
working-directory: services/aws-v4
env:
REQSIGN_AWS_V4_TEST_ASSUME_ROLE: on
REQSIGN_AWS_V4_VALIDATE_CREDENTIALS: on
REQSIGN_AWS_V4_ASSUME_ROLE_ARN: ${{ vars.REQSIGN_AWS_LIVE_ASSUME_ROLE_ARN }}
run: cargo test test_assume_role --no-fail-fast -- --nocapture
- name: Get a fresh GitHub OIDC token
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const token = await core.getIDToken('sts.amazonaws.com');
core.setSecret(token);
require('fs').writeFileSync('/tmp/reqsign-web-identity-token', token, { mode: 0o600 });
- name: Test AssumeRoleWithWebIdentityCredentialProvider
working-directory: services/aws-v4
env:
REQSIGN_AWS_V4_TEST_WEB_IDENTITY: on
REQSIGN_AWS_V4_VALIDATE_CREDENTIALS: on
AWS_ROLE_ARN: ${{ vars.REQSIGN_AWS_LIVE_ROLE_ARN }}
AWS_ROLE_SESSION_NAME: reqsign-web-${{ github.run_id }}
AWS_WEB_IDENTITY_TOKEN_FILE: /tmp/reqsign-web-identity-token
run: cargo test test_assume_role_with_web_identity_credential_provider --no-fail-fast -- --nocapture
- name: Test CognitoIdentityCredentialProvider
working-directory: services/aws-v4
env:
REQSIGN_AWS_V4_TEST_COGNITO: on
REQSIGN_AWS_V4_VALIDATE_CREDENTIALS: on
AWS_COGNITO_IDENTITY_POOL_ID: ${{ vars.REQSIGN_AWS_LIVE_COGNITO_POOL_ID }}
run: cargo test test_cognito_identity_credential_provider --no-fail-fast -- --nocapture
- name: Test S3AccessGrantsGranter
working-directory: services/aws-v4
env:
REQSIGN_AWS_V4_TEST_S3_ACCESS_GRANTS: on
REQSIGN_AWS_V4_VALIDATE_CREDENTIALS: on
REQSIGN_AWS_V4_ACCOUNT_ID: ${{ vars.REQSIGN_AWS_LIVE_ACCOUNT_ID }}
REQSIGN_AWS_V4_S3_ACCESS_GRANTS_BUCKET: ${{ vars.REQSIGN_AWS_LIVE_TEST_BUCKET }}
REQSIGN_AWS_V4_S3_ACCESS_GRANTS_PREFIX: access-grants/
run: cargo test test_s3_access_grants_granter_live --no-fail-fast -- --nocapture
- name: Test S3ExpressSessionProvider and granter
working-directory: services/aws-v4
env:
REQSIGN_AWS_V4_TEST_S3_EXPRESS: on
REQSIGN_AWS_V4_S3_EXPRESS_BUCKET: ${{ vars.REQSIGN_AWS_LIVE_S3_EXPRESS_BUCKET }}
AWS_REGION: ${{ vars.REQSIGN_AWS_LIVE_S3_EXPRESS_REGION }}
run: cargo test test_s3_express --no-fail-fast -- --nocapture
- name: Test request signing against S3
working-directory: services/aws-v4
env:
REQSIGN_AWS_V4_TEST: on
REQSIGN_AWS_V4_REGION: ${{ vars.REQSIGN_AWS_LIVE_REGION }}
REQSIGN_AWS_V4_SERVICE: s3
REQSIGN_AWS_V4_URL: https://${{ vars.REQSIGN_AWS_LIVE_TEST_BUCKET }}.s3.${{ vars.REQSIGN_AWS_LIVE_REGION }}.amazonaws.com
run: |
export REQSIGN_AWS_V4_ACCESS_KEY="$AWS_ACCESS_KEY_ID"
export REQSIGN_AWS_V4_SECRET_KEY="$AWS_SECRET_ACCESS_KEY"
export REQSIGN_AWS_V4_SESSION_TOKEN="$AWS_SESSION_TOKEN"
cargo test signing:: --no-fail-fast -- --nocapture
- name: Remove signing test objects
if: always()
env:
TEST_BUCKET: ${{ vars.REQSIGN_AWS_LIVE_TEST_BUCKET }}
run: aws s3api delete-object --bucket "$TEST_BUCKET" --key put_object_test >/dev/null 2>&1 || true
- name: Remove ephemeral credential files
if: always()
shell: bash
run: |
if [[ -n "${REQSIGN_PROFILE_TEST_HOME:-}" ]]; then
rm -rf -- "$REQSIGN_PROFILE_TEST_HOME"
fi
if [[ -n "${REQSIGN_PROCESS_TEST_HOME:-}" ]]; then
rm -rf -- "$REQSIGN_PROCESS_TEST_HOME"
fi
rm -f -- /tmp/reqsign-aws-role-token /tmp/reqsign-web-identity-token
build_live_image:
needs: check_live_test
if: needs.check_live_test.outputs.enabled == 'true'
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
outputs:
image: ${{ steps.image.outputs.image }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Get a GitHub OIDC token
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const token = await core.getIDToken('sts.amazonaws.com');
core.setSecret(token);
require('fs').writeFileSync('/tmp/reqsign-aws-role-token', token, { mode: 0o600 });
- name: Assume the reqsign live-test role
env:
ROLE_ARN: ${{ vars.REQSIGN_AWS_LIVE_ROLE_ARN }}
ROLE_SESSION_NAME: reqsign-image-${{ github.run_id }}
shell: bash
run: |
credentials="$(aws sts assume-role-with-web-identity \
--role-arn "$ROLE_ARN" \
--role-session-name "$ROLE_SESSION_NAME" \
--web-identity-token "$(tr -d '\n' < /tmp/reqsign-aws-role-token)" \
--query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]' \
--output text)"
read -r access_key secret_key session_token <<< "$credentials"
test -n "$access_key" && test -n "$secret_key" && test -n "$session_token"
echo "::add-mask::$access_key"
echo "::add-mask::$secret_key"
echo "::add-mask::$session_token"
{
echo "AWS_ACCESS_KEY_ID=$access_key"
echo "AWS_SECRET_ACCESS_KEY=$secret_key"
echo "AWS_SESSION_TOKEN=$session_token"
} >> "$GITHUB_ENV"
- name: Build and push the live-test image
id: image
env:
ECR_REPOSITORY_URI: ${{ vars.REQSIGN_AWS_LIVE_ECR_REPOSITORY }}
IMAGE_TAG: sha-${{ github.sha }}
shell: bash
run: |
repository_name="${ECR_REPOSITORY_URI#*/}"
if ! aws ecr describe-images --repository-name "$repository_name" --image-ids "imageTag=$IMAGE_TAG" >/dev/null 2>&1; then
aws ecr get-login-password | docker login --username AWS --password-stdin "${ECR_REPOSITORY_URI%/*}"
docker build --platform linux/amd64 --file .github/aws-live-tests/Dockerfile --tag "$ECR_REPOSITORY_URI:$IMAGE_TAG" .
docker push "$ECR_REPOSITORY_URI:$IMAGE_TAG"
fi
echo "image=$ECR_REPOSITORY_URI:$IMAGE_TAG" >> "$GITHUB_OUTPUT"
test_ecs_provider:
needs:
- check_live_test
- build_live_image
if: needs.check_live_test.outputs.enabled == 'true'
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- name: Get a GitHub OIDC token
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const token = await core.getIDToken('sts.amazonaws.com');
core.setSecret(token);
require('fs').writeFileSync('/tmp/reqsign-aws-role-token', token, { mode: 0o600 });
- name: Assume the reqsign live-test role
env:
ROLE_ARN: ${{ vars.REQSIGN_AWS_LIVE_ROLE_ARN }}
ROLE_SESSION_NAME: reqsign-ecs-${{ github.run_id }}
shell: bash
run: |
credentials="$(aws sts assume-role-with-web-identity \
--role-arn "$ROLE_ARN" \
--role-session-name "$ROLE_SESSION_NAME" \
--web-identity-token "$(tr -d '\n' < /tmp/reqsign-aws-role-token)" \
--query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]' \
--output text)"
read -r access_key secret_key session_token <<< "$credentials"
test -n "$access_key" && test -n "$secret_key" && test -n "$session_token"
echo "::add-mask::$access_key"
echo "::add-mask::$secret_key"
echo "::add-mask::$session_token"
{
echo "AWS_ACCESS_KEY_ID=$access_key"
echo "AWS_SECRET_ACCESS_KEY=$secret_key"
echo "AWS_SESSION_TOKEN=$session_token"
} >> "$GITHUB_ENV"
- name: Register and run the Fargate task
env:
IMAGE_URI: ${{ needs.build_live_image.outputs.image }}
CLUSTER: ${{ vars.REQSIGN_AWS_LIVE_ECS_CLUSTER }}
EXECUTION_ROLE_ARN: ${{ vars.REQSIGN_AWS_LIVE_ECS_EXECUTION_ROLE_ARN }}
TASK_ROLE_ARN: ${{ vars.REQSIGN_AWS_LIVE_ECS_TASK_ROLE_ARN }}
LOG_GROUP: ${{ vars.REQSIGN_AWS_LIVE_ECS_LOG_GROUP }}
SUBNET_ID: ${{ vars.REQSIGN_AWS_LIVE_SUBNET_ID }}
SECURITY_GROUP_ID: ${{ vars.REQSIGN_AWS_LIVE_SECURITY_GROUP_ID }}
shell: bash
run: |
container_definitions="$(jq -n \
--arg image "$IMAGE_URI" \
--arg region "$AWS_REGION" \
--arg log_group "$LOG_GROUP" \
'[{
name: "reqsign-live-test",
image: $image,
essential: true,
command: ["test_ecs_credential_provider", "--nocapture"],
environment: [
{name: "AWS_REGION", value: $region},
{name: "REQSIGN_AWS_V4_TEST_ECS", value: "on"},
{name: "REQSIGN_AWS_V4_VALIDATE_CREDENTIALS", value: "on"},
{name: "RUST_LOG", value: "info"}
],
logConfiguration: {
logDriver: "awslogs",
options: {
"awslogs-group": $log_group,
"awslogs-region": $region,
"awslogs-stream-prefix": "ecs"
}
}
}]')"
task_definition_arn="$(aws ecs register-task-definition \
--family reqsign-live-test \
--requires-compatibilities FARGATE \
--network-mode awsvpc \
--runtime-platform cpuArchitecture=X86_64,operatingSystemFamily=LINUX \
--cpu 256 \
--memory 512 \
--execution-role-arn "$EXECUTION_ROLE_ARN" \
--task-role-arn "$TASK_ROLE_ARN" \
--container-definitions "$container_definitions" \
--query 'taskDefinition.taskDefinitionArn' \
--output text)"
echo "TASK_DEFINITION_ARN=$task_definition_arn" >> "$GITHUB_ENV"
task_arn="$(aws ecs run-task \
--cluster "$CLUSTER" \
--task-definition "$task_definition_arn" \
--launch-type FARGATE \
--network-configuration "awsvpcConfiguration={subnets=[$SUBNET_ID],securityGroups=[$SECURITY_GROUP_ID],assignPublicIp=ENABLED}" \
--started-by "reqsign-${GITHUB_RUN_ID}" \
--query 'tasks[0].taskArn' \
--output text)"
test "$task_arn" != "None"
echo "TASK_ARN=$task_arn" >> "$GITHUB_ENV"
aws ecs wait tasks-stopped --cluster "$CLUSTER" --tasks "$task_arn"
task_json="$(aws ecs describe-tasks --cluster "$CLUSTER" --tasks "$task_arn")"
printf '%s\n' "$task_json" | jq '{stoppedReason: .tasks[0].stoppedReason, containers: [.tasks[0].containers[] | {name, exitCode, reason}]}'
task_id="${task_arn##*/}"
log_stream="ecs/reqsign-live-test/$task_id"
for _ in {1..12}; do
if aws logs get-log-events --log-group-name "$LOG_GROUP" --log-stream-name "$log_stream" --start-from-head --query 'events[].message' --output text; then
break
fi
sleep 5
done
test "$(printf '%s\n' "$task_json" | jq -r '.tasks[0].containers[0].exitCode')" = "0"
- name: Clean up the Fargate task
if: always()
env:
CLUSTER: ${{ vars.REQSIGN_AWS_LIVE_ECS_CLUSTER }}
shell: bash
run: |
if [[ -n "${TASK_ARN:-}" ]]; then
last_status="$(aws ecs describe-tasks --cluster "$CLUSTER" --tasks "$TASK_ARN" --query 'tasks[0].lastStatus' --output text 2>/dev/null || true)"
if [[ "$last_status" == "RUNNING" || "$last_status" == "PENDING" || "$last_status" == "PROVISIONING" || "$last_status" == "ACTIVATING" ]]; then
aws ecs stop-task --cluster "$CLUSTER" --task "$TASK_ARN" --reason "GitHub Actions cleanup" >/dev/null
fi
fi
if [[ -n "${TASK_DEFINITION_ARN:-}" ]]; then
aws ecs deregister-task-definition --task-definition "$TASK_DEFINITION_ARN" >/dev/null
fi
test_imds_provider:
needs:
- check_live_test
- build_live_image
if: needs.check_live_test.outputs.enabled == 'true'
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- name: Get a GitHub OIDC token
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const token = await core.getIDToken('sts.amazonaws.com');
core.setSecret(token);
require('fs').writeFileSync('/tmp/reqsign-aws-role-token', token, { mode: 0o600 });
- name: Assume the reqsign live-test role
env:
ROLE_ARN: ${{ vars.REQSIGN_AWS_LIVE_ROLE_ARN }}
ROLE_SESSION_NAME: reqsign-imds-${{ github.run_id }}
shell: bash
run: |
credentials="$(aws sts assume-role-with-web-identity \
--role-arn "$ROLE_ARN" \
--role-session-name "$ROLE_SESSION_NAME" \
--web-identity-token "$(tr -d '\n' < /tmp/reqsign-aws-role-token)" \
--query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]' \
--output text)"
read -r access_key secret_key session_token <<< "$credentials"
test -n "$access_key" && test -n "$secret_key" && test -n "$session_token"
echo "::add-mask::$access_key"
echo "::add-mask::$secret_key"
echo "::add-mask::$session_token"
{
echo "AWS_ACCESS_KEY_ID=$access_key"
echo "AWS_SECRET_ACCESS_KEY=$secret_key"
echo "AWS_SESSION_TOKEN=$session_token"
} >> "$GITHUB_ENV"
- name: Launch the ephemeral IMDSv2 test instance
env:
IMAGE_URI: ${{ needs.build_live_image.outputs.image }}
INSTANCE_PROFILE: ${{ vars.REQSIGN_AWS_LIVE_EC2_INSTANCE_PROFILE }}
SUBNET_ID: ${{ vars.REQSIGN_AWS_LIVE_SUBNET_ID }}
SECURITY_GROUP_ID: ${{ vars.REQSIGN_AWS_LIVE_SECURITY_GROUP_ID }}
RESULT_BUCKET: ${{ vars.REQSIGN_AWS_LIVE_TEST_BUCKET }}
shell: bash
run: |
result_key="live-tests/results/${GITHUB_RUN_ID}-${GITHUB_RUN_ATTEMPT}/imds.log"
echo "IMDS_RESULT_KEY=$result_key" >> "$GITHUB_ENV"
cat > "$RUNNER_TEMP/reqsign-imds-user-data.sh" <<EOF
#!/bin/bash
log_file=/var/log/reqsign-live-test.log
(
set -euo pipefail
dnf install --assumeyes docker
systemctl enable --now docker
aws ecr get-login-password --region '${AWS_REGION}' | docker login --username AWS --password-stdin '${IMAGE_URI%/*}'
docker run --rm --network host \
--env AWS_REGION='${AWS_REGION}' \
--env REQSIGN_AWS_V4_TEST_IMDS=on \
--env REQSIGN_AWS_V4_VALIDATE_CREDENTIALS=on \
--env RUST_LOG=info \
'${IMAGE_URI}' test_imds_v2_credential_provider --nocapture
) > "\$log_file" 2>&1
test_status=\$?
printf '\nREQSIGN_TEST_EXIT_CODE=%s\n' "\$test_status" >> "\$log_file"
aws s3 cp "\$log_file" 's3://${RESULT_BUCKET}/${result_key}' --region '${AWS_REGION}'
shutdown -h now
EOF
chmod 700 "$RUNNER_TEMP/reqsign-imds-user-data.sh"
ami_id="$(aws ssm get-parameter \
--name /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64 \
--query 'Parameter.Value' \
--output text)"
expires_at="$(date -u -d '+2 hours' '+%Y-%m-%dT%H:%M:%SZ')"
instance_id="$(aws ec2 run-instances \
--image-id "$ami_id" \
--instance-type t3.nano \
--count 1 \
--iam-instance-profile "Name=$INSTANCE_PROFILE" \
--subnet-id "$SUBNET_ID" \
--security-group-ids "$SECURITY_GROUP_ID" \
--associate-public-ip-address \
--metadata-options 'HttpEndpoint=enabled,HttpTokens=required,HttpPutResponseHopLimit=2,InstanceMetadataTags=disabled' \
--instance-initiated-shutdown-behavior terminate \
--user-data "file://$RUNNER_TEMP/reqsign-imds-user-data.sh" \
--tag-specifications "ResourceType=instance,Tags=[{Key=Name,Value=reqsign-live-test-imds},{Key=Project,Value=reqsign},{Key=Purpose,Value=live-test},{Key=GitHubRunId,Value=${GITHUB_RUN_ID}},{Key=ExpiresAt,Value=$expires_at}]" \
--query 'Instances[0].InstanceId' \
--output text)"
echo "INSTANCE_ID=$instance_id" >> "$GITHUB_ENV"
result_found=false
for _ in {1..120}; do
if aws s3api head-object --bucket "$RESULT_BUCKET" --key "$result_key" >/dev/null 2>&1; then
result_found=true
break
fi
sleep 10
done
test "$result_found" = "true"
aws s3 cp "s3://$RESULT_BUCKET/$result_key" "$RUNNER_TEMP/reqsign-imds-result.log"
sed -E 's/(AccessKeyId|SecretAccessKey|Token).*/\1: [REDACTED]/I' "$RUNNER_TEMP/reqsign-imds-result.log"
grep -qx 'REQSIGN_TEST_EXIT_CODE=0' "$RUNNER_TEMP/reqsign-imds-result.log"
- name: Clean up the IMDSv2 test instance
if: always()
env:
RESULT_BUCKET: ${{ vars.REQSIGN_AWS_LIVE_TEST_BUCKET }}
shell: bash
run: |
if [[ -n "${INSTANCE_ID:-}" ]]; then
aws ec2 terminate-instances --instance-ids "$INSTANCE_ID" >/dev/null 2>&1 || true
fi
if [[ -n "${IMDS_RESULT_KEY:-}" ]]; then
aws s3api delete-object --bucket "$RESULT_BUCKET" --key "$IMDS_RESULT_KEY" >/dev/null 2>&1 || true
fi
summary:
if: always()
needs:
- check_live_test
- test_hosted_providers
- build_live_image
- test_ecs_provider
- test_imds_provider
runs-on: ubuntu-latest
steps:
- name: Write live-test summary
env:
ENABLED: ${{ needs.check_live_test.outputs.enabled }}
HOSTED_RESULT: ${{ needs.test_hosted_providers.result }}
IMAGE_RESULT: ${{ needs.build_live_image.result }}
ECS_RESULT: ${{ needs.test_ecs_provider.result }}
IMDS_RESULT: ${{ needs.test_imds_provider.result }}
shell: bash
run: |
{
echo "## AWS V4 live credential-provider tests"
echo
echo "| Coverage | Result |"
echo "|---|---|"
echo "| Static, Env, Profile, Process, Default | $HOSTED_RESULT |"
echo "| AssumeRole, WebIdentity, Cognito, S3 Access Grants, S3 Express, S3 signing | $HOSTED_RESULT |"
echo "| Live-test image | $IMAGE_RESULT |"
echo "| ECS task credentials on Fargate | $ECS_RESULT |"
echo "| IMDSv2 credentials on ephemeral EC2 | $IMDS_RESULT |"
echo
echo "SSOCredentialProvider remains mock-only because the current provider requires a pre-authorized legacy SSO cache and has no unattended token refresh flow."
} >> "$GITHUB_STEP_SUMMARY"
if [[ "$ENABLED" == "true" && ( "$HOSTED_RESULT" != "success" || "$IMAGE_RESULT" != "success" || "$ECS_RESULT" != "success" || "$IMDS_RESULT" != "success" ) ]]; then
exit 1
fi