mirror of
https://github.com/aws-actions/configure-aws-credentials.git
synced 2026-09-04 06:15:07 +09:00
Support usage of AWS Profiles
This commit is contained in:
@@ -822,4 +822,221 @@ describe('Configure AWS Credentials', {}, () => {
|
||||
expect(core.setFailed).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('AWS Profile Support', {}, () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
mockedSTSClient.reset();
|
||||
vi.mock('node:fs');
|
||||
vol.reset();
|
||||
});
|
||||
|
||||
it('writes profile files with OIDC authentication', async () => {
|
||||
vi.spyOn(core, 'getInput').mockImplementation(
|
||||
mocks.getInput({
|
||||
...mocks.GH_OIDC_INPUTS,
|
||||
'aws-profile': 'dev',
|
||||
}),
|
||||
);
|
||||
vi.spyOn(core, 'getIDToken').mockResolvedValue('testoidctoken');
|
||||
mockedSTSClient.on(AssumeRoleWithWebIdentityCommand).resolves(mocks.outputs.STS_CREDENTIALS);
|
||||
mockedSTSClient.on(GetCallerIdentityCommand).resolves({ ...mocks.outputs.GET_CALLER_IDENTITY });
|
||||
process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN = 'fake-token';
|
||||
|
||||
await run();
|
||||
|
||||
// Verify credentials were NOT exported to environment variables
|
||||
expect(core.exportVariable).not.toHaveBeenCalledWith('AWS_ACCESS_KEY_ID', expect.anything());
|
||||
expect(core.exportVariable).not.toHaveBeenCalledWith('AWS_SECRET_ACCESS_KEY', expect.anything());
|
||||
expect(core.exportVariable).not.toHaveBeenCalledWith('AWS_SESSION_TOKEN', expect.anything());
|
||||
|
||||
// Verify AWS_PROFILE was exported
|
||||
expect(core.exportVariable).toHaveBeenCalledWith('AWS_PROFILE', 'dev');
|
||||
|
||||
// Verify region was still exported
|
||||
expect(core.exportVariable).toHaveBeenCalledWith('AWS_REGION', 'fake-region-1');
|
||||
expect(core.exportVariable).toHaveBeenCalledWith('AWS_DEFAULT_REGION', 'fake-region-1');
|
||||
|
||||
// Verify profile files were written
|
||||
expect(core.info).toHaveBeenCalledWith('Writing credentials to profile: dev');
|
||||
expect(core.info).toHaveBeenCalledWith('Writing config to profile: dev');
|
||||
expect(core.info).toHaveBeenCalledWith('✓ Successfully configured AWS profile: dev');
|
||||
expect(core.setFailed).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('writes profile files with IAM user credentials', async () => {
|
||||
vi.spyOn(core, 'getInput').mockImplementation(
|
||||
mocks.getInput({
|
||||
...mocks.IAM_USER_INPUTS,
|
||||
'aws-profile': 'production',
|
||||
}),
|
||||
);
|
||||
mockedSTSClient.on(GetCallerIdentityCommand).resolves({ ...mocks.outputs.GET_CALLER_IDENTITY });
|
||||
// biome-ignore lint/suspicious/noExplicitAny: any required to mock private method
|
||||
vi.spyOn(CredentialsClient.prototype as any, 'loadCredentials').mockResolvedValue({
|
||||
accessKeyId: 'MYAWSACCESSKEYID',
|
||||
});
|
||||
|
||||
await run();
|
||||
|
||||
// Verify credentials were NOT exported to env vars
|
||||
expect(core.exportVariable).not.toHaveBeenCalledWith('AWS_ACCESS_KEY_ID', expect.anything());
|
||||
|
||||
// Verify AWS_PROFILE was exported
|
||||
expect(core.exportVariable).toHaveBeenCalledWith('AWS_PROFILE', 'production');
|
||||
|
||||
// Verify region was exported
|
||||
expect(core.exportVariable).toHaveBeenCalledWith('AWS_REGION', 'fake-region-1');
|
||||
|
||||
// Verify profile files were written
|
||||
expect(core.info).toHaveBeenCalledWith('✓ Successfully configured AWS profile: production');
|
||||
expect(core.setFailed).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('writes profile files with role assumption', async () => {
|
||||
vi.spyOn(core, 'getInput').mockImplementation(
|
||||
mocks.getInput({
|
||||
...mocks.IAM_ASSUMEROLE_INPUTS,
|
||||
'aws-profile': 'assumed-role',
|
||||
}),
|
||||
);
|
||||
mockedSTSClient.on(AssumeRoleCommand).resolves(mocks.outputs.STS_CREDENTIALS);
|
||||
mockedSTSClient.on(GetCallerIdentityCommand).resolves({ ...mocks.outputs.GET_CALLER_IDENTITY });
|
||||
// biome-ignore lint/suspicious/noExplicitAny: any required to mock private method
|
||||
vi.spyOn(CredentialsClient.prototype as any, 'loadCredentials')
|
||||
.mockResolvedValueOnce({ accessKeyId: 'MYAWSACCESSKEYID' })
|
||||
.mockResolvedValueOnce({ accessKeyId: 'STSAWSACCESSKEYID' });
|
||||
|
||||
await run();
|
||||
|
||||
// Verify assumed role credentials were NOT exported to env vars
|
||||
expect(core.exportVariable).not.toHaveBeenCalledWith('AWS_ACCESS_KEY_ID', 'STSAWSACCESSKEYID');
|
||||
|
||||
// Verify AWS_PROFILE was exported
|
||||
expect(core.exportVariable).toHaveBeenCalledWith('AWS_PROFILE', 'assumed-role');
|
||||
|
||||
// Verify profile files were written
|
||||
expect(core.info).toHaveBeenCalledWith('✓ Successfully configured AWS profile: assumed-role');
|
||||
expect(core.setFailed).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('respects output-env-credentials=false for AWS_PROFILE', async () => {
|
||||
vi.spyOn(core, 'getInput').mockImplementation(
|
||||
mocks.getInput({
|
||||
...mocks.GH_OIDC_INPUTS,
|
||||
'aws-profile': 'dev',
|
||||
'output-env-credentials': 'false',
|
||||
}),
|
||||
);
|
||||
vi.spyOn(core, 'getIDToken').mockResolvedValue('testoidctoken');
|
||||
mockedSTSClient.on(AssumeRoleWithWebIdentityCommand).resolves(mocks.outputs.STS_CREDENTIALS);
|
||||
mockedSTSClient.on(GetCallerIdentityCommand).resolves({ ...mocks.outputs.GET_CALLER_IDENTITY });
|
||||
process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN = 'fake-token';
|
||||
|
||||
await run();
|
||||
|
||||
// Verify AWS_PROFILE was NOT exported when output-env-credentials is false
|
||||
expect(core.exportVariable).not.toHaveBeenCalledWith('AWS_PROFILE', expect.anything());
|
||||
|
||||
// Verify region is still exported (always exported in profile mode)
|
||||
expect(core.exportVariable).toHaveBeenCalledWith('AWS_REGION', 'fake-region-1');
|
||||
expect(core.exportVariable).toHaveBeenCalledWith('AWS_DEFAULT_REGION', 'fake-region-1');
|
||||
|
||||
// Verify profile files were still written
|
||||
expect(core.info).toHaveBeenCalledWith('✓ Successfully configured AWS profile: dev');
|
||||
expect(core.setFailed).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('maintains backward compatibility when aws-profile is not specified', async () => {
|
||||
vi.spyOn(core, 'getInput').mockImplementation(mocks.getInput(mocks.GH_OIDC_INPUTS));
|
||||
vi.spyOn(core, 'getIDToken').mockResolvedValue('testoidctoken');
|
||||
mockedSTSClient.on(AssumeRoleWithWebIdentityCommand).resolves(mocks.outputs.STS_CREDENTIALS);
|
||||
mockedSTSClient.on(GetCallerIdentityCommand).resolves({ ...mocks.outputs.GET_CALLER_IDENTITY });
|
||||
process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN = 'fake-token';
|
||||
|
||||
await run();
|
||||
|
||||
// Verify credentials WERE exported to environment variables (backward compatibility)
|
||||
expect(core.exportVariable).toHaveBeenCalledWith('AWS_ACCESS_KEY_ID', 'STSAWSACCESSKEYID');
|
||||
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SECRET_ACCESS_KEY', 'STSAWSSECRETACCESSKEY');
|
||||
expect(core.exportVariable).toHaveBeenCalledWith('AWS_SESSION_TOKEN', 'STSAWSSESSIONTOKEN');
|
||||
expect(core.exportVariable).toHaveBeenCalledWith('AWS_REGION', 'fake-region-1');
|
||||
expect(core.exportVariable).toHaveBeenCalledWith('AWS_DEFAULT_REGION', 'fake-region-1');
|
||||
|
||||
// Verify AWS_PROFILE was NOT exported
|
||||
expect(core.exportVariable).not.toHaveBeenCalledWith('AWS_PROFILE', expect.anything());
|
||||
|
||||
// Verify profile files were NOT written
|
||||
expect(core.info).not.toHaveBeenCalledWith(expect.stringContaining('Writing credentials to profile'));
|
||||
expect(core.setFailed).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('handles default profile correctly', async () => {
|
||||
vi.spyOn(core, 'getInput').mockImplementation(
|
||||
mocks.getInput({
|
||||
...mocks.GH_OIDC_INPUTS,
|
||||
'aws-profile': 'default',
|
||||
}),
|
||||
);
|
||||
vi.spyOn(core, 'getIDToken').mockResolvedValue('testoidctoken');
|
||||
mockedSTSClient.on(AssumeRoleWithWebIdentityCommand).resolves(mocks.outputs.STS_CREDENTIALS);
|
||||
mockedSTSClient.on(GetCallerIdentityCommand).resolves({ ...mocks.outputs.GET_CALLER_IDENTITY });
|
||||
process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN = 'fake-token';
|
||||
|
||||
await run();
|
||||
|
||||
// Verify profile files were written for 'default' profile
|
||||
expect(core.info).toHaveBeenCalledWith('Writing credentials to profile: default');
|
||||
expect(core.info).toHaveBeenCalledWith('Writing config to profile: default');
|
||||
expect(core.info).toHaveBeenCalledWith('✓ Successfully configured AWS profile: default');
|
||||
expect(core.setFailed).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('rejects invalid profile names with whitespace', async () => {
|
||||
vi.spyOn(core, 'getInput').mockImplementation(
|
||||
mocks.getInput({
|
||||
...mocks.GH_OIDC_INPUTS,
|
||||
'aws-profile': 'invalid profile',
|
||||
}),
|
||||
);
|
||||
vi.spyOn(core, 'getIDToken').mockResolvedValue('testoidctoken');
|
||||
mockedSTSClient.on(AssumeRoleWithWebIdentityCommand).resolves(mocks.outputs.STS_CREDENTIALS);
|
||||
mockedSTSClient.on(GetCallerIdentityCommand).resolves({ ...mocks.outputs.GET_CALLER_IDENTITY });
|
||||
process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN = 'fake-token';
|
||||
|
||||
await run();
|
||||
|
||||
expect(core.setFailed).toHaveBeenCalledWith(expect.stringContaining('whitespace'));
|
||||
});
|
||||
|
||||
it('always exports region in profile mode even with output-env-credentials=false', async () => {
|
||||
vi.spyOn(core, 'getInput').mockImplementation(
|
||||
mocks.getInput({
|
||||
...mocks.GH_OIDC_INPUTS,
|
||||
'aws-profile': 'dev',
|
||||
'output-env-credentials': 'false',
|
||||
}),
|
||||
);
|
||||
vi.spyOn(core, 'getIDToken').mockResolvedValue('testoidctoken');
|
||||
mockedSTSClient.on(AssumeRoleWithWebIdentityCommand).resolves(mocks.outputs.STS_CREDENTIALS);
|
||||
mockedSTSClient.on(GetCallerIdentityCommand).resolves({ ...mocks.outputs.GET_CALLER_IDENTITY });
|
||||
process.env.ACTIONS_ID_TOKEN_REQUEST_TOKEN = 'fake-token';
|
||||
|
||||
await run();
|
||||
|
||||
// Verify region was exported even when output-env-credentials is false
|
||||
expect(core.exportVariable).toHaveBeenCalledWith('AWS_REGION', 'fake-region-1');
|
||||
expect(core.exportVariable).toHaveBeenCalledWith('AWS_DEFAULT_REGION', 'fake-region-1');
|
||||
|
||||
// Verify credential env vars were NOT exported
|
||||
expect(core.exportVariable).not.toHaveBeenCalledWith('AWS_ACCESS_KEY_ID', expect.anything());
|
||||
expect(core.exportVariable).not.toHaveBeenCalledWith('AWS_SECRET_ACCESS_KEY', expect.anything());
|
||||
expect(core.exportVariable).not.toHaveBeenCalledWith('AWS_SESSION_TOKEN', expect.anything());
|
||||
|
||||
// Verify AWS_PROFILE was NOT exported (output-env-credentials=false)
|
||||
expect(core.exportVariable).not.toHaveBeenCalledWith('AWS_PROFILE', expect.anything());
|
||||
|
||||
expect(core.setFailed).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user