Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(lambda): bump @aws-sdk/client-ssm from 3.321.1 to 3.350.0 in /lambdas #3319

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions lambdas/functions/control-plane/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,13 @@
"ts-node-dev": "^2.0.0"
},
"dependencies": {
"@aws-sdk/client-ec2": "^3.303.0",
"@aws-sdk/client-ec2": "^3.350.0",
"@aws-sdk/types": "^3.347.0",
"@octokit/auth-app": "4.0.13",
"@octokit/rest": "^19.0.7",
"@octokit/types": "^9.0.0",
"@terraform-aws-github-runner/aws-ssm-util": "*",
"@terraform-aws-github-runner/aws-powertools-util": "*",
"@terraform-aws-github-runner/aws-ssm-util": "*",
"cron-parser": "^4.8.1",
"typescript": "^5.0.4"
}
Expand Down
19 changes: 9 additions & 10 deletions lambdas/functions/control-plane/src/aws/runners.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import {
FleetLaunchTemplateOverridesRequest,
TerminateInstancesCommand,
} from '@aws-sdk/client-ec2';
import { SSM } from '@aws-sdk/client-ssm';
import { createChildLogger } from '@terraform-aws-github-runner/aws-powertools-util';
import { getParameter, putParameter } from '@terraform-aws-github-runner/aws-ssm-util';
import moment from 'moment';

import ScaleError from './../scale-runners/ScaleError';
Expand Down Expand Up @@ -138,14 +138,13 @@ export async function createRunner(runnerParameters: Runners.RunnerInputParamete
},
});

const ec2Clinnt = new EC2Client({ region: process.env.AWS_REGION });
const ssmClient = new SSM({ region: process.env.AWS_REGION });
const ec2Client = new EC2Client({ region: process.env.AWS_REGION });

let amiIdOverride = undefined;

if (runnerParameters.amiIdSsmParameterName) {
try {
amiIdOverride = (await ssmClient.getParameter({ Name: runnerParameters.amiIdSsmParameterName })).Parameter?.Value;
amiIdOverride = await getParameter(runnerParameters.amiIdSsmParameterName);
logger.debug(`AMI override SSM parameter (${runnerParameters.amiIdSsmParameterName}) set to: ${amiIdOverride}`);
} catch (e) {
logger.error(
Expand Down Expand Up @@ -197,7 +196,7 @@ export async function createRunner(runnerParameters: Runners.RunnerInputParamete
],
Type: 'instant',
});
fleet = await ec2Clinnt.send(createFleetCommand);
fleet = await ec2Client.send(createFleetCommand);
} catch (e) {
logger.warn('Create fleet request failed.', { error: e as Error });
throw e;
Expand Down Expand Up @@ -239,11 +238,11 @@ export async function createRunner(runnerParameters: Runners.RunnerInputParamete
const isDelay = instances.length >= ssmParameterStoreMaxThroughput ? true : false;

for (const instance of instances) {
await ssmClient.putParameter({
Name: `${runnerParameters.ssmTokenPath}/${instance}`,
Value: runnerParameters.runnerServiceConfig.join(' '),
Type: 'SecureString',
});
await putParameter(
`${runnerParameters.ssmTokenPath}/${instance}`,
runnerParameters.runnerServiceConfig.join(' '),
true,
);

if (isDelay) {
// Delay to prevent AWS ssm rate limits by being within the max throughput limit
Expand Down
16 changes: 8 additions & 8 deletions lambdas/functions/control-plane/src/gh-auth/gh-auth.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { createAppAuth } from '@octokit/auth-app';
import { StrategyOptions } from '@octokit/auth-app/dist-types/types';
import { request } from '@octokit/request';
import { RequestInterface } from '@octokit/types';
import { getParameterValue } from '@terraform-aws-github-runner/aws-ssm-util';
import { getParameter } from '@terraform-aws-github-runner/aws-ssm-util';
import { mocked } from 'jest-mock';
import { MockProxy, mock } from 'jest-mock-extended';
import nock from 'nock';
Expand All @@ -18,7 +18,7 @@ const GITHUB_APP_ID = '1';
const PARAMETER_GITHUB_APP_ID_NAME = `/actions-runner/${ENVIRONMENT}/github_app_id`;
const PARAMETER_GITHUB_APP_KEY_BASE64_NAME = `/actions-runner/${ENVIRONMENT}/github_app_key_base64`;

const mockedGet = mocked(getParameterValue);
const mockedGet = mocked(getParameter);

beforeEach(() => {
jest.resetModules();
Expand Down Expand Up @@ -117,8 +117,8 @@ ${decryptedValue}`,
const result = await createGithubAppAuth(installationId);

// Assert
expect(getParameterValue).toBeCalledWith(PARAMETER_GITHUB_APP_ID_NAME);
expect(getParameterValue).toBeCalledWith(PARAMETER_GITHUB_APP_KEY_BASE64_NAME);
expect(getParameter).toBeCalledWith(PARAMETER_GITHUB_APP_ID_NAME);
expect(getParameter).toBeCalledWith(PARAMETER_GITHUB_APP_KEY_BASE64_NAME);

expect(mockedCreatAppAuth).toBeCalledTimes(1);
expect(mockedCreatAppAuth).toBeCalledWith(authOptions);
Expand Down Expand Up @@ -154,8 +154,8 @@ ${decryptedValue}`,
const result = await createGithubAppAuth(installationId, githubServerUrl);

// Assert
expect(getParameterValue).toBeCalledWith(PARAMETER_GITHUB_APP_ID_NAME);
expect(getParameterValue).toBeCalledWith(PARAMETER_GITHUB_APP_KEY_BASE64_NAME);
expect(getParameter).toBeCalledWith(PARAMETER_GITHUB_APP_ID_NAME);
expect(getParameter).toBeCalledWith(PARAMETER_GITHUB_APP_KEY_BASE64_NAME);

expect(mockedCreatAppAuth).toBeCalledTimes(1);
expect(mockedCreatAppAuth).toBeCalledWith(authOptions);
Expand Down Expand Up @@ -191,8 +191,8 @@ ${decryptedValue}`,
const result = await createGithubAppAuth(installationId, githubServerUrl);

// Assert
expect(getParameterValue).toBeCalledWith(PARAMETER_GITHUB_APP_ID_NAME);
expect(getParameterValue).toBeCalledWith(PARAMETER_GITHUB_APP_KEY_BASE64_NAME);
expect(getParameter).toBeCalledWith(PARAMETER_GITHUB_APP_ID_NAME);
expect(getParameter).toBeCalledWith(PARAMETER_GITHUB_APP_KEY_BASE64_NAME);

expect(mockedCreatAppAuth).toBeCalledTimes(1);
expect(mockedCreatAppAuth).toBeCalledWith(authOptions);
Expand Down
6 changes: 3 additions & 3 deletions lambdas/functions/control-plane/src/gh-auth/gh-auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { OctokitOptions } from '@octokit/core/dist-types/types';
import { request } from '@octokit/request';
import { Octokit } from '@octokit/rest';
import { createChildLogger } from '@terraform-aws-github-runner/aws-powertools-util';
import { getParameterValue } from '@terraform-aws-github-runner/aws-ssm-util';
import { getParameter } from '@terraform-aws-github-runner/aws-ssm-util';

const logger = createChildLogger('gh-auth');

Expand Down Expand Up @@ -45,11 +45,11 @@ export async function createGithubInstallationAuth(
}

async function createAuth(installationId: number | undefined, ghesApiUrl: string): Promise<AuthInterface> {
const appId = parseInt(await getParameterValue(process.env.PARAMETER_GITHUB_APP_ID_NAME));
const appId = parseInt(await getParameter(process.env.PARAMETER_GITHUB_APP_ID_NAME));
let authOptions: StrategyOptions = {
appId,
privateKey: Buffer.from(
await getParameterValue(process.env.PARAMETER_GITHUB_APP_KEY_BASE64_NAME),
await getParameter(process.env.PARAMETER_GITHUB_APP_KEY_BASE64_NAME),
'base64',
// replace literal \n characters with new lines to allow the key to be stored as a
// single line variable. This logic should match how the GitHub Terraform provider
Expand Down
5 changes: 3 additions & 2 deletions lambdas/functions/gh-agent-syncer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@
"typescript": "^5.0.3"
},
"dependencies": {
"@aws-sdk/client-s3": "^3.315.0",
"@aws-sdk/lib-storage": "^3.315.0",
"@aws-sdk/client-s3": "^3.350.0",
"@aws-sdk/lib-storage": "^3.350.0",
"@aws-sdk/types": "^3.347.0",
"@terraform-aws-github-runner/aws-powertools-util": "*",
"axios": "^1.3.5"
}
Expand Down
4 changes: 2 additions & 2 deletions lambdas/functions/webhook/src/webhook/handler.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Webhooks } from '@octokit/webhooks';
import { getParameterValue } from '@terraform-aws-github-runner/aws-ssm-util';
import { getParameter } from '@terraform-aws-github-runner/aws-ssm-util';
import { mocked } from 'jest-mock';
import nock from 'nock';

Expand Down Expand Up @@ -41,7 +41,7 @@ describe('handler', () => {
jest.clearAllMocks();
jest.resetAllMocks();

const mockedGet = mocked(getParameterValue);
const mockedGet = mocked(getParameter);
mockedGet.mockResolvedValueOnce(GITHUB_APP_WEBHOOK_SECRET);
});

Expand Down
4 changes: 2 additions & 2 deletions lambdas/functions/webhook/src/webhook/handler.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Webhooks } from '@octokit/webhooks';
import { CheckRunEvent, WorkflowJobEvent } from '@octokit/webhooks-types';
import { createChildLogger } from '@terraform-aws-github-runner/aws-powertools-util';
import { getParameterValue } from '@terraform-aws-github-runner/aws-ssm-util';
import { getParameter } from '@terraform-aws-github-runner/aws-ssm-util';
import { IncomingHttpHeaders } from 'http';

import { Response } from '../lambda';
Expand Down Expand Up @@ -99,7 +99,7 @@ async function verifySignature(githubEvent: string, headers: IncomingHttpHeaders
return 500;
}

const secret = await getParameterValue(process.env.PARAMETER_GITHUB_APP_WEBHOOK_SECRET);
const secret = await getParameter(process.env.PARAMETER_GITHUB_APP_WEBHOOK_SECRET);

const webhooks = new Webhooks({
secret: secret,
Expand Down
3 changes: 2 additions & 1 deletion lambdas/libs/aws-ssm-util/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"typescript": "^5.0.2"
},
"dependencies": {
"@aws-sdk/client-ssm": "^3.321.1"
"@aws-sdk/client-ssm": "^3.350.0",
"@aws-sdk/types": "^3.347.0"
}
}
107 changes: 96 additions & 11 deletions lambdas/libs/aws-ssm-util/src/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
import { GetParameterCommandOutput, SSM } from '@aws-sdk/client-ssm';
import {
GetParameterCommand,
GetParameterCommandOutput,
PutParameterCommand,
PutParameterCommandOutput,
SSMClient,
} from '@aws-sdk/client-ssm';
import { mockClient } from 'aws-sdk-client-mock';
import 'aws-sdk-client-mock-jest';
import nock from 'nock';

import { getParameterValue } from '.';

jest.mock('@aws-sdk/client-ssm');
import { getParameter, putParameter } from '.';

const mockSSMClient = mockClient(SSMClient);
const cleanEnv = process.env;

beforeEach(() => {
Expand All @@ -14,8 +21,8 @@ beforeEach(() => {
nock.disableNetConnect();
});

describe('Test getParameterValue', () => {
test('Gets parameters and returns string', async () => {
describe('Test getParameter and putParameter', () => {
it('Gets parameters and returns string', async () => {
// Arrange
const parameterValue = 'test';
const parameterName = 'testParam';
Expand All @@ -30,16 +37,94 @@ describe('Test getParameterValue', () => {
},
};

SSM.prototype.getParameter = jest.fn().mockResolvedValue(output);
mockSSMClient.on(GetParameterCommand).resolves(output);

// Act
const result = await getParameterValue(parameterName);
const result = await getParameter(parameterName);

// Assert
expect(result).toBe(parameterValue);
});

test('Gets invalid parameters and returns string', async () => {
it('Puts parameters and returns error on failure', async () => {
// Arrange
const parameterValue = 'test';
const parameterName = 'testParam';
const output: PutParameterCommandOutput = {
$metadata: {
httpStatusCode: 401,
},
};

mockSSMClient.on(PutParameterCommand).resolves(output);

// Act
expect(putParameter(parameterName, parameterValue, true)).rejects;
});

it('Puts parameters and returns success', async () => {
// Arrange
const parameterValue = 'test';
const parameterName = 'testParam';
const output: PutParameterCommandOutput = {
$metadata: {
httpStatusCode: 200,
},
};

mockSSMClient.on(PutParameterCommand).resolves(output);

// Act
expect(putParameter(parameterName, parameterValue, true)).resolves;
});

it('Puts parameters as String', async () => {
// Arrange
const parameterValue = 'test';
const parameterName = 'testParam';
const secure = false;
const output: PutParameterCommandOutput = {
$metadata: {
httpStatusCode: 200,
},
};

mockSSMClient.on(PutParameterCommand).resolves(output);

// Act
await putParameter(parameterName, parameterValue, secure);

expect(mockSSMClient).toHaveReceivedCommandWith(PutParameterCommand, {
Name: parameterName,
Value: parameterValue,
Type: 'String',
});
});

it('Puts parameters as SecureString', async () => {
// Arrange
const parameterValue = 'test';
const parameterName = 'testParam';
const secure = true;
const output: PutParameterCommandOutput = {
$metadata: {
httpStatusCode: 200,
},
};

mockSSMClient.on(PutParameterCommand).resolves(output);

// Act
await putParameter(parameterName, parameterValue, secure);

expect(mockSSMClient).toHaveReceivedCommandWith(PutParameterCommand, {
Name: parameterName,
Value: parameterValue,
Type: 'SecureString',
});
});

it('Gets invalid parameters and returns string', async () => {
// Arrange
const parameterName = 'invalid';
const output: GetParameterCommandOutput = {
Expand All @@ -48,10 +133,10 @@ describe('Test getParameterValue', () => {
},
};

SSM.prototype.getParameter = jest.fn().mockResolvedValue(output);
mockSSMClient.on(GetParameterCommand).resolves(output);

// Act
const result = await getParameterValue(parameterName);
const result = await getParameter(parameterName);

// Assert
expect(result).toBe(undefined);
Expand Down
20 changes: 16 additions & 4 deletions lambdas/libs/aws-ssm-util/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
import { SSM } from '@aws-sdk/client-ssm';
import { GetParameterCommand, PutParameterCommand, SSMClient } from '@aws-sdk/client-ssm';

export async function getParameterValue(parameter_name: string): Promise<string> {
const client = new SSM({ region: process.env.AWS_REGION });
return (await client.getParameter({ Name: parameter_name, WithDecryption: true })).Parameter?.Value as string;
export async function getParameter(parameter_name: string): Promise<string> {
const client = new SSMClient({ region: process.env.AWS_REGION });
return (await client.send(new GetParameterCommand({ Name: parameter_name, WithDecryption: true }))).Parameter
?.Value as string;
}

export async function putParameter(parameter_name: string, parameter_value: string, secure: boolean): Promise<void> {
const client = new SSMClient({ region: process.env.AWS_REGION });
await client.send(
new PutParameterCommand({
Name: parameter_name,
Value: parameter_value,
Type: secure ? 'SecureString' : 'String',
}),
);
}
Loading