configure-aws-credentials/test/mockinputs.test.ts
Tom Keller d05a2190d4 feat: add validation for custom session tags
Harden the custom-tags feature against misuse and
misconfiguration:

- Validate input is a JSON object (reject arrays, primitives, null)
- Enforce STS tag constraints: key length (128), value length (256),
  allowed characters
- Reject nested object/array values that would silently stringify to
  '[object Object]'
- Block overriding default session tags (GitHub, Repository,
  Workflow, etc.)
- Enforce 50-tag session limit
- Warn when custom-tags used with OIDC or web identity
- Fix missing await on helpers test assertion
- Remove unused CUSTOM_TAGS_JSON_INPUTS fixture
- Normalize test mocking to vi.mocked() pattern
2026-05-06 14:35:45 -07:00

154 lines
4.9 KiB
TypeScript

import type * as core from '@actions/core';
const inputs = {
GH_OIDC_INPUTS: {
'role-to-assume': 'arn:aws:iam::111111111111:role/MY-ROLE',
'aws-region': 'fake-region-1',
'special-characters-workaround': 'true',
},
CUSTOM_TAGS_INVALID_JSON_INPUTS: {
'aws-access-key-id': 'MYAWSACCESSKEYID',
'aws-secret-access-key': 'MYAWSSECRETACCESSKEY',
'role-to-assume': 'arn:aws:iam::111111111111:role/MY-ROLE',
'aws-region': 'fake-region-1',
'retry-max-attempts': '1',
'custom-tags': 'not a json',
},
CUSTOM_TAGS_ARRAY_INPUTS: {
'aws-access-key-id': 'MYAWSACCESSKEYID',
'aws-secret-access-key': 'MYAWSSECRETACCESSKEY',
'role-to-assume': 'arn:aws:iam::111111111111:role/MY-ROLE',
'aws-region': 'fake-region-1',
'retry-max-attempts': '1',
'custom-tags': '[1, 2, 3]',
},
CUSTOM_TAGS_RESERVED_KEY_INPUTS: {
'aws-access-key-id': 'MYAWSACCESSKEYID',
'aws-secret-access-key': 'MYAWSSECRETACCESSKEY',
'role-to-assume': 'arn:aws:iam::111111111111:role/MY-ROLE',
'aws-region': 'fake-region-1',
'retry-max-attempts': '1',
'custom-tags': JSON.stringify({ Repository: 'evil-repo' }),
},
CUSTOM_TAGS_INVALID_KEY_CHARS_INPUTS: {
'aws-access-key-id': 'MYAWSACCESSKEYID',
'aws-secret-access-key': 'MYAWSSECRETACCESSKEY',
'role-to-assume': 'arn:aws:iam::111111111111:role/MY-ROLE',
'aws-region': 'fake-region-1',
'retry-max-attempts': '1',
'custom-tags': JSON.stringify({ 'invalid{key}': 'value' }),
},
CUSTOM_TAGS_OBJECT_INPUTS: {
'aws-access-key-id': 'MYAWSACCESSKEYID',
'aws-secret-access-key': 'MYAWSSECRETACCESSKEY',
'role-to-assume': 'arn:aws:iam::111111111111:role/MY-ROLE',
'aws-region': 'fake-region-1',
'retry-max-attempts': '1',
'custom-tags': JSON.stringify({ Environment: 'Production', Team: 'DevOps' }),
},
IAM_USER_INPUTS: {
'aws-access-key-id': 'MYAWSACCESSKEYID',
'aws-secret-access-key': 'MYAWSSECRETACCESSKEY',
'aws-region': 'fake-region-1',
},
IAM_ASSUMEROLE_INPUTS: {
'aws-access-key-id': 'MYAWSACCESSKEYID',
'aws-secret-access-key': 'MYAWSSECRETACCESSKEY',
'role-to-assume': 'arn:aws:iam::111111111111:role/MY-ROLE',
'aws-region': 'fake-region-1',
},
WEBIDENTITY_TOKEN_FILE_INPUTS: {
'web-identity-token-file': 'file.txt',
'role-to-assume': 'arn:aws:iam::111111111111:role/MY-ROLE',
'aws-region': 'fake-region-1',
},
EXISTING_ROLE_INPUTS: {
'role-to-assume': 'arn:aws:iam::111111111111:role/MY-ROLE',
'role-chaining': 'true',
'aws-region': 'fake-region-1',
},
USE_EXISTING_CREDENTIALS_INPUTS: {
'aws-region': 'fake-region-1',
'use-existing-credentials': 'true',
'role-to-assume': 'arn:aws:iam::111111111111:role/MY-ROLE',
},
NO_ENV_CREDS_INPUTS: {
'role-to-assume': 'arn:aws:iam::111111111111:role/MY-ROLE',
'aws-region': 'fake-region-1',
'output-env-credentials': 'false',
},
STEP_BUT_NO_ENV_INPUTS: {
'role-to-assume': 'arn:aws:iam::111111111111:role/MY-ROLE',
'aws-region': 'fake-region-1',
'output-env-credentials': 'false',
'output-credentials': 'true',
},
};
const envs = {
GITHUB_REPOSITORY: 'MY-REPOSITORY-NAME',
GITHUB_WORKFLOW: 'MY-WORKFLOW-ID',
GITHUB_ACTION: 'MY-ACTION-NAME',
GITHUB_ACTOR: 'MY-USERNAME[bot]',
GITHUB_SHA: 'MY-COMMIT-ID',
GITHUB_WORKSPACE: '/home/github',
GITHUB_ACTIONS: 'true',
};
const outputs = {
STS_CREDENTIALS: {
Credentials: {
AccessKeyId: 'STSAWSACCESSKEYID',
SecretAccessKey: 'STSAWSSECRETACCESSKEY',
SessionToken: 'STSAWSSESSIONTOKEN',
Expiration: new Date(8640000000000000),
},
AssumedRoleUser: {
Arn: 'arn:aws:sts::111111111111:assumed-role/MY-ROLE/',
AssumedRoleId: 'AROAFAKEASSUMEDROLEID',
},
},
GET_CALLER_IDENTITY: {
Account: '111111111111',
Arn: 'arn:aws:iam::111111111111:role/MY-ROLE',
},
FAKE_STS_ACCESS_KEY_ID: 'STSAWSACCESSKEYID',
FAKE_STS_SECRET_ACCESS_KEY: 'STSAWSSECRETACCESSKEY',
FAKE_STS_SESSION_TOKEN: 'STSAWSSESSIONTOKEN',
ODD_CHARACTER_CREDENTIALS: {
Credentials: {
AccessKeyId: 'STSA#$%^&',
SecretAccessKey: 'STSA#$%^&Key',
SessionToken: 'STSA#$%^',
Expiration: new Date(8640000000000000),
},
AssumedRoleUser: {
Arn: 'arn:aws:sts::111111111111:assumed-role/MY-ROLE/',
AssumedRoleId: 'AROAFAKEASSUMEDROLEID',
},
},
};
export default {
getInput: (fakeEnv: Record<string, string>) => {
return (name: string, options?: core.InputOptions): string => {
if (!fakeEnv[name]) {
if (options?.required) throw new Error(`Input ${name} not found`);
return '';
}
return fakeEnv[name];
};
},
getMultilineInput: (fakeEnv: Record<string, string[]>) => {
return (name: string, options?: core.InputOptions): string[] => {
if (!fakeEnv[name]) {
if (options?.required) throw new Error(`Input ${name} not found`);
return [];
}
return fakeEnv[name];
};
},
...inputs,
outputs,
envs,
} as const;