Skip to content

Commit afa76c2

Browse files
author
Vishal Wadhera
committed
adding dynamodb table as a SSM parameter store replacement to store tokens
1 parent dc246ac commit afa76c2

42 files changed

Lines changed: 2318 additions & 252 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,5 @@
11
# Changelog
22

3-
## [7.10.2](https://github.com/github-aws-runners/terraform-aws-github-runner/compare/v7.10.1...v7.10.2) (2026-08-10)
4-
5-
6-
### Bug Fixes
7-
8-
* **lambda:** bump postcss from 8.5.22 to 8.5.24 in /lambdas ([#5241](https://github.com/github-aws-runners/terraform-aws-github-runner/issues/5241)) ([17cd322](https://github.com/github-aws-runners/terraform-aws-github-runner/commit/17cd322aa4a43db583072cce4b87f99db494b6d0))
9-
* **termination-watcher:** only emit SpotInterruptionWarning metric for actual spot interruption events ([#5245](https://github.com/github-aws-runners/terraform-aws-github-runner/issues/5245)) ([7480fd5](https://github.com/github-aws-runners/terraform-aws-github-runner/commit/7480fd58d4c517e8e999a830905bbd9334dc987d))
10-
* wrap LOG_LEVEL env var with upper() for Powertools v2 compatibility ([#5238](https://github.com/github-aws-runners/terraform-aws-github-runner/issues/5238)) ([2394f84](https://github.com/github-aws-runners/terraform-aws-github-runner/commit/2394f8445faeba3d37998791cf51ae9dd0ab453e))
11-
123
## [7.10.1](https://github.com/github-aws-runners/terraform-aws-github-runner/compare/v7.10.0...v7.10.1) (2026-07-31)
134

145

lambdas/functions/control-plane/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"@aws-github-runner/aws-ssm-util": "*",
3535
"@aws-github-runner/runner-providers": "*",
3636
"@aws-lambda-powertools/parameters": "^2.31.0",
37+
"@aws-sdk/client-dynamodb": "^3.1009.0",
3738
"@aws-sdk/client-ec2": "^3.1009.0",
3839
"@aws-sdk/client-sqs": "^3.1009.0",
3940
"@middy/core": "^6.4.5",
@@ -42,6 +43,7 @@
4243
"@octokit/plugin-retry": "8.0.3",
4344
"@octokit/plugin-throttling": "11.0.3",
4445
"@octokit/rest": "22.0.1",
46+
"@smithy/node-http-handler": "^4.5.0",
4547
"cron-parser": "^5.4.0"
4648
},
4749
"nx": {

lambdas/functions/control-plane/src/modules.d.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,21 @@ declare namespace NodeJS {
1515
PARAMETER_GITHUB_APP_CLIENT_SECRET_NAME: string;
1616
PARAMETER_GITHUB_APP_ID_NAME: string;
1717
PARAMETER_GITHUB_APP_KEY_BASE64_NAME: string;
18+
RUNNER_CONFIG_STORAGE_BACKEND?: string;
19+
RUNNER_CONFIG_DYNAMODB_TABLE_NAME?: string;
20+
RUNNER_CONFIG_DYNAMODB_PARTITION_KEY_NAME?: string;
21+
RUNNER_CONFIG_DYNAMODB_VALUE_ATTRIBUTE_NAME?: string;
22+
RUNNER_CONFIG_DYNAMODB_CONFIG_KEY_PREFIX?: string;
23+
RUNNER_CONFIG_DYNAMODB_CONSISTENT_READ?: string;
24+
RUNNER_CONFIG_DYNAMODB_TOKEN_OVERWRITE_PROTECTION_ENABLED?: string;
25+
RUNNER_CONFIG_DYNAMODB_TOKEN_KEY_PREFIX?: string;
26+
RUNNER_CONFIG_DYNAMODB_TTL_SECONDS?: string;
27+
RUNNER_CONFIG_DYNAMODB_TTL_ATTRIBUTE_NAME?: string;
28+
RUNNER_CONFIG_DYNAMODB_CLIENT_MAX_ATTEMPTS?: string;
29+
RUNNER_CONFIG_DYNAMODB_CLIENT_RETRY_MODE?: string;
30+
RUNNER_CONFIG_DYNAMODB_CLIENT_HTTP_KEEP_ALIVE?: string;
31+
RUNNER_CONFIG_DYNAMODB_CLIENT_HTTP_MAX_SOCKETS?: string;
32+
RUNNER_CONFIG_DYNAMODB_CLIENT_HTTP_KEEP_ALIVE_MSECS?: string;
1833
RUNNER_OWNER: string;
1934
RUNNER_PROVIDER_TYPE?: string;
2035
SCALE_DOWN_CONFIG: string;

lambdas/functions/control-plane/src/pool/pool.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import yn from 'yn';
66
import { createGithubAppAuth, createGithubInstallationAuth, createOctokitClient } from '../github/auth';
77
import { controlPlaneProviderRegistry } from '../control-plane-providers';
88
import { getGitHubEnterpriseApiUrl, validateSsmParameterStoreTags } from '../scale-runners/github-runner';
9+
import { loadRunnerConfigStorageFromEnv } from '../scale-runners/runner-config-storage';
910
import type { RunnerStatus } from './pool-provider';
1011

1112
const logger = createChildLogger('pool');
@@ -28,6 +29,7 @@ export async function adjust(event: PoolEvent): Promise<void> {
2829
const environment = process.env.ENVIRONMENT;
2930
const ssmTokenPath = process.env.SSM_TOKEN_PATH;
3031
const ssmConfigPath = process.env.SSM_CONFIG_PATH || '';
32+
const runnerConfigStorage = loadRunnerConfigStorageFromEnv();
3133
const ephemeral = yn(process.env.ENABLE_EPHEMERAL_RUNNERS, { default: false });
3234
const enableJitConfig = yn(process.env.ENABLE_JIT_CONFIG, { default: ephemeral });
3335
const disableAutoUpdate = yn(process.env.DISABLE_RUNNER_AUTOUPDATE, { default: false });
@@ -95,6 +97,7 @@ export async function adjust(event: PoolEvent): Promise<void> {
9597
ssmTokenPath,
9698
ssmConfigPath,
9799
ssmParameterStoreTags,
100+
runnerConfigStorage,
98101
},
99102
numberOfRunners: topUp,
100103
githubInstallationClient,

lambdas/functions/control-plane/src/scale-runners/github-runner.ts

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { createChildLogger } from '@aws-github-runner/aws-powertools-util';
2-
import { getParameter, putParameter } from '@aws-github-runner/aws-ssm-util';
32
import { Octokit } from '@octokit/rest';
43

54
import { metricGitHubAppRateLimit } from '../github/rate-limit';
5+
import { createRunnerConfigStore } from './runner-config-storage';
66
import { ActionRequestMessage, CreateGitHubRunnerConfig, EphemeralRunnerConfig, RunnerGroup } from './types';
77

88
const logger = createChildLogger('github-runner');
@@ -171,34 +171,28 @@ export async function getRunnerGroupId(
171171
let runnerGroupId: number | undefined = 1;
172172
if (githubRunnerConfig.runnerType === 'Org' && githubRunnerConfig.runnerGroup !== undefined) {
173173
let runnerGroup: string | undefined;
174-
// check if runner group id is already stored in SSM Parameter Store and
175-
// use it if it exists to avoid API call to GitHub
174+
const runnerConfigStore = createRunnerConfigStore(githubRunnerConfig);
175+
const runnerGroupCacheKey = `runner-group/${githubRunnerConfig.runnerGroup}`;
176+
// check if runner group id is already cached and use it if it exists to
177+
// avoid an API call to GitHub
176178
try {
177-
runnerGroup = await getParameter(
178-
`${githubRunnerConfig.ssmConfigPath}/runner-group/${githubRunnerConfig.runnerGroup}`,
179-
);
179+
runnerGroup = await runnerConfigStore.getConfigValue(runnerGroupCacheKey);
180180
} catch (err) {
181181
logger.debug('Handling error:', err as Error);
182182
logger.warn(
183-
`SSM Parameter "${githubRunnerConfig.ssmConfigPath}/runner-group/${githubRunnerConfig.runnerGroup}"
184-
for Runner group ${githubRunnerConfig.runnerGroup} does not exist`,
183+
`Runner group cache entry "${runnerGroupCacheKey}" for Runner group ${githubRunnerConfig.runnerGroup} does not exist`,
185184
);
186185
}
187186
if (runnerGroup === undefined) {
188187
// get runner group id from GitHub
189188
runnerGroupId = await getRunnerGroupByName(ghClient, githubRunnerConfig);
190-
// store runner group id in SSM
189+
// store runner group id in the configured runner config storage
191190
try {
192-
await putParameter(
193-
`${githubRunnerConfig.ssmConfigPath}/runner-group/${githubRunnerConfig.runnerGroup}`,
194-
runnerGroupId.toString(),
195-
false,
196-
{
197-
tags: githubRunnerConfig.ssmParameterStoreTags,
198-
},
199-
);
191+
await runnerConfigStore.putConfigValue(runnerGroupCacheKey, runnerGroupId.toString(), {
192+
tags: githubRunnerConfig.ssmParameterStoreTags,
193+
});
200194
} catch (err) {
201-
logger.debug('Error storing runner group id in SSM Parameter Store', err as Error);
195+
logger.debug('Error storing runner group id', err as Error);
202196
throw err;
203197
}
204198
} else {
@@ -241,10 +235,10 @@ export async function createStartRunnerConfig(
241235
}
242236
}
243237

244-
function addDelay(runnerIds: string[]) {
238+
function addDelay(runnerIds: string[], enabled = true) {
245239
const delay = async (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
246240
const ssmParameterStoreMaxThroughput = 40;
247-
const isDelay = runnerIds.length >= ssmParameterStoreMaxThroughput;
241+
const isDelay = enabled && runnerIds.length >= ssmParameterStoreMaxThroughput;
248242
return { isDelay, delay };
249243
}
250244

@@ -259,7 +253,8 @@ async function createRegistrationTokenConfig(
259253
ghClient: Octokit,
260254
options: StartRunnerConfigOptions,
261255
): Promise<string[]> {
262-
const { isDelay, delay } = addDelay(runnerIds);
256+
const runnerConfigStore = createRunnerConfigStore(githubRunnerConfig);
257+
const { isDelay, delay } = addDelay(runnerIds, runnerConfigStore.delayWritesForSsmThroughput);
263258
const token = await getGithubRunnerRegistrationToken(githubRunnerConfig, ghClient);
264259
const runnerServiceConfig = generateRunnerServiceConfig(githubRunnerConfig, token);
265260

@@ -268,7 +263,7 @@ async function createRegistrationTokenConfig(
268263
});
269264

270265
for (const runnerId of runnerIds) {
271-
await putParameter(`${githubRunnerConfig.ssmTokenPath}/${runnerId}`, runnerServiceConfig.join(' '), true, {
266+
await runnerConfigStore.putRunnerConfig(runnerId, runnerServiceConfig.join(' '), {
272267
tags: [...(options.getSsmParameterTags?.(runnerId) ?? []), ...githubRunnerConfig.ssmParameterStoreTags],
273268
});
274269
if (isDelay) {
@@ -293,7 +288,8 @@ async function createJitConfig(
293288
options: StartRunnerConfigOptions,
294289
): Promise<string[]> {
295290
const runnerGroupId = await getRunnerGroupId(githubRunnerConfig, ghClient);
296-
const { isDelay, delay } = addDelay(runnerIds);
291+
const runnerConfigStore = createRunnerConfigStore(githubRunnerConfig);
292+
const { isDelay, delay } = addDelay(runnerIds, runnerConfigStore.delayWritesForSsmThroughput);
297293
const runnerLabels = githubRunnerConfig.runnerLabels.split(',');
298294
const failedRunnerIds: string[] = [];
299295

@@ -331,11 +327,11 @@ async function createJitConfig(
331327
runnerLabels,
332328
});
333329

334-
// store jit config in ssm parameter store
330+
// store jit config in the configured runner config storage
335331
logger.debug('Runner JIT config for ephemeral runner generated.', {
336332
instance: runnerId,
337333
});
338-
await putParameter(`${githubRunnerConfig.ssmTokenPath}/${runnerId}`, runnerConfig.data.encoded_jit_config, true, {
334+
await runnerConfigStore.putRunnerConfig(runnerId, runnerConfig.data.encoded_jit_config, {
339335
tags: [...(options.getSsmParameterTags?.(runnerId) ?? []), ...githubRunnerConfig.ssmParameterStoreTags],
340336
});
341337
if (isDelay) {

0 commit comments

Comments
 (0)