Skip to content

Commit f2e29b5

Browse files
ScottGuymernpalm
authored andcommitted
fix: Dynamic set SSM-paramater tier #4613
1 parent 9d1e25a commit f2e29b5

File tree

3 files changed

+40
-1
lines changed

3 files changed

+40
-1
lines changed

docs/configuration.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ To be able to support a number of use-cases, the module has quite a lot of confi
1919

2020
The module uses the AWS System Manager Parameter Store to store configuration for the runners, as well as registration tokens and secrets for the Lambdas. Paths for the parameters can be configured via the variable `ssm_paths`. The location of the configuration parameters is retrieved by the runners via the instance tag `ghr:ssm_config_path`. The following default paths will be used. Tokens or JIT config stored in the token path will be deleted after retrieval by instance, data not deleted after a day will be deleted by a SSM housekeeper lambda.
2121

22+
Furthermore, to accommodate larger JIT configurations or other stored values, the module implements automatic tier selection for SSM parameters:
23+
24+
- **Parameter Tiering**: If the size of a parameter's value exceeds 4KB (specifically, 4000 bytes), the module will automatically use the 'Advanced' tier for that SSM parameter. Values smaller than this threshold will use the 'Standard' tier.
25+
- **Cost Implications**: While the 'Standard' tier is generally free for a certain number of parameters and operations, the 'Advanced' tier incurs costs. These costs are typically pro-rated per hour for each parameter stored using the Advanced tier. For detailed and up-to-date pricing, please refer to the [AWS Systems Manager Pricing page](https://aws.amazon.com/systems-manager/pricing/#Parameter_Store).
26+
- **Housekeeping Recommendation**: The last sentence of the "AWS SSM Parameters" section already mentions that "data not deleted after a day will be deleted by a SSM housekeeper lambda." It is crucial to ensure this or a similar housekeeping mechanism is active and correctly configured, especially considering the potential costs associated with 'Advanced' tier parameters. This utility should identify and delete any orphaned parameters to help manage costs and maintain a clean SSM environment.
27+
2228
| Path | Description |
2329
| ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
2430
| `ssm_paths.root/var.prefix?/app/` | App secrets used by Lambda's |

lambdas/libs/aws-ssm-util/src/index.test.ts

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import 'aws-sdk-client-mock-jest/vitest';
99
import { mockClient } from 'aws-sdk-client-mock';
1010
import nock from 'nock';
1111

12-
import { getParameter, putParameter } from '.';
12+
import { getParameter, putParameter, SSM_ADVANCED_TIER_THRESHOLD } from '.';
1313
import { describe, it, expect, beforeEach, vi } from 'vitest';
1414

1515
const mockSSMClient = mockClient(SSMClient);
@@ -139,4 +139,30 @@ describe('Test getParameter and putParameter', () => {
139139
// Act
140140
await expect(getParameter(parameterName)).rejects.toThrow(`Parameter ${parameterName} not found`);
141141
});
142+
143+
it.each([
144+
['a'.repeat(SSM_ADVANCED_TIER_THRESHOLD - 1), 'Standard'],
145+
['a'.repeat(SSM_ADVANCED_TIER_THRESHOLD), 'Advanced'],
146+
['a'.repeat(SSM_ADVANCED_TIER_THRESHOLD + 1), 'Advanced'],
147+
])('Puts parameters with value and sets correct SSM tier based on size and threshold', async (data, expectedTier) => {
148+
// Arrange
149+
const parameterValue = data;
150+
const parameterName = 'testParamSmall';
151+
const secure = false;
152+
const output: PutParameterCommandOutput = {
153+
$metadata: { httpStatusCode: 200 },
154+
};
155+
mockSSMClient.on(PutParameterCommand).resolves(output);
156+
157+
// Act
158+
await putParameter(parameterName, parameterValue, secure);
159+
160+
// Assert
161+
expect(mockSSMClient).toHaveReceivedCommandWith(PutParameterCommand, {
162+
Name: parameterName,
163+
Value: parameterValue,
164+
Type: 'String',
165+
Tier: expectedTier,
166+
});
167+
});
142168
});

lambdas/libs/aws-ssm-util/src/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,26 @@ export async function getParameter(parameter_name: string): Promise<string> {
1717
return result;
1818
}
1919

20+
export const SSM_ADVANCED_TIER_THRESHOLD = 4000;
21+
2022
export async function putParameter(
2123
parameter_name: string,
2224
parameter_value: string,
2325
secure: boolean,
2426
options: { tags?: Tag[] } = {},
2527
): Promise<void> {
2628
const client = getTracedAWSV3Client(new SSMClient({ region: process.env.AWS_REGION }));
29+
30+
// Determine tier based on parameter_value size
31+
const valueSizeBytes = Buffer.byteLength(parameter_value, 'utf8');
32+
2733
await client.send(
2834
new PutParameterCommand({
2935
Name: parameter_name,
3036
Value: parameter_value,
3137
Type: secure ? 'SecureString' : 'String',
3238
Tags: options.tags,
39+
Tier: valueSizeBytes >= SSM_ADVANCED_TIER_THRESHOLD ? 'Advanced' : 'Standard',
3340
}),
3441
);
3542
}

0 commit comments

Comments
 (0)