Skip to content

Commit c7a6b51

Browse files
committed
2 parents 086da2b + b5c9f37 commit c7a6b51

File tree

3 files changed

+38
-5
lines changed

3 files changed

+38
-5
lines changed

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { bootTimeExceeded, listEC2Runners } from '../aws/runners';
66
import { RunnerList } from '../aws/runners.d';
77
import { createGithubAppAuth, createGithubInstallationAuth, createOctokitClient } from '../github/auth';
88
import { createRunners, getGitHubEnterpriseApiUrl } from '../scale-runners/scale-up';
9+
import { validateSsmParameterStoreTags } from '../scale-runners/scale-up';
910

1011
const logger = createChildLogger('pool');
1112

@@ -41,9 +42,10 @@ export async function adjust(event: PoolEvent): Promise<void> {
4142
const onDemandFailoverOnError = process.env.ENABLE_ON_DEMAND_FAILOVER_FOR_ERRORS
4243
? (JSON.parse(process.env.ENABLE_ON_DEMAND_FAILOVER_FOR_ERRORS) as [string])
4344
: [];
44-
const ssmParameterStoreTags = process.env.SSM_PARAMETER_STORE_TAGS
45-
? JSON.parse(process.env.SSM_PARAMETER_STORE_TAGS)
46-
: {};
45+
const ssmParameterStoreTags: { Key: string; Value: string }[] =
46+
process.env.SSM_PARAMETER_STORE_TAGS && process.env.SSM_PARAMETER_STORE_TAGS.trim() !== ''
47+
? validateSsmParameterStoreTags(process.env.SSM_PARAMETER_STORE_TAGS)
48+
: [];
4749

4850
const { ghesApiUrl, ghesBaseUrl } = getGitHubEnterpriseApiUrl();
4951

lambdas/functions/control-plane/src/scale-runners/scale-up.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,37 @@ function generateRunnerServiceConfig(githubRunnerConfig: CreateGitHubRunnerConfi
9090
return config;
9191
}
9292

93+
export function validateSsmParameterStoreTags(tagsJson: string): { Key: string; Value: string }[] {
94+
try {
95+
const tags = JSON.parse(tagsJson);
96+
97+
if (!Array.isArray(tags)) {
98+
throw new Error('Tags must be an array');
99+
}
100+
101+
if (tags.length === 0) {
102+
return [];
103+
}
104+
105+
tags.forEach((tag, index) => {
106+
if (typeof tag !== 'object' || tag === null) {
107+
throw new Error(`Tag at index ${index} must be an object`);
108+
}
109+
if (!tag.Key || typeof tag.Key !== 'string' || tag.Key.trim() === '') {
110+
throw new Error(`Tag at index ${index} has missing or invalid 'Key' property`);
111+
}
112+
if (!tag.Value || typeof tag.Value !== 'string' || tag.Value.trim() === '') {
113+
throw new Error(`Tag at index ${index} has missing or invalid 'Value' property`);
114+
}
115+
});
116+
117+
return tags;
118+
} catch (err) {
119+
logger.error('Invalid SSM_PARAMETER_STORE_TAGS format', { error: err });
120+
throw new Error(`Failed to parse SSM_PARAMETER_STORE_TAGS: ${(err as Error).message}`);
121+
}
122+
}
123+
93124
async function getGithubRunnerRegistrationToken(githubRunnerConfig: CreateGitHubRunnerConfig, ghClient: Octokit) {
94125
const registrationToken =
95126
githubRunnerConfig.runnerType === 'Org'
@@ -261,7 +292,7 @@ export async function scaleUp(payloads: ActionRequestMessageSQS[]): Promise<stri
261292
: [];
262293
const ssmParameterStoreTags: { Key: string; Value: string }[] =
263294
process.env.SSM_PARAMETER_STORE_TAGS && process.env.SSM_PARAMETER_STORE_TAGS.trim() !== ''
264-
? JSON.parse(process.env.SSM_PARAMETER_STORE_TAGS)
295+
? validateSsmParameterStoreTags(process.env.SSM_PARAMETER_STORE_TAGS)
265296
: [];
266297

267298
const { ghesApiUrl, ghesBaseUrl } = getGitHubEnterpriseApiUrl();

modules/runners/pool/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ No modules.
4949
| Name | Description | Type | Default | Required |
5050
|------|-------------|------|---------|:--------:|
5151
| <a name="input_aws_partition"></a> [aws\_partition](#input\_aws\_partition) | (optional) partition for the arn if not 'aws' | `string` | `"aws"` | no |
52-
| <a name="input_config"></a> [config](#input\_config) | Lookup details in parent module. | <pre>object({<br/> lambda = object({<br/> log_level = string<br/> logging_retention_in_days = number<br/> logging_kms_key_id = string<br/> reserved_concurrent_executions = number<br/> s3_bucket = string<br/> s3_key = string<br/> s3_object_version = string<br/> security_group_ids = list(string)<br/> runtime = string<br/> architecture = string<br/> memory_size = number<br/> timeout = number<br/> zip = string<br/> subnet_ids = list(string)<br/> parameter_store_tags = map(string)<br/> })<br/> tags = map(string)<br/> ghes = object({<br/> url = string<br/> ssl_verify = string<br/> })<br/> github_app_parameters = object({<br/> key_base64 = map(string)<br/> id = map(string)<br/> })<br/> subnet_ids = list(string)<br/> runner = object({<br/> disable_runner_autoupdate = bool<br/> ephemeral = bool<br/> enable_jit_config = bool<br/> enable_on_demand_failover_for_errors = list(string)<br/> boot_time_in_minutes = number<br/> labels = list(string)<br/> launch_template = object({<br/> name = string<br/> })<br/> group_name = string<br/> name_prefix = string<br/> pool_owner = string<br/> role = object({<br/> arn = string<br/> })<br/> })<br/> instance_types = list(string)<br/> instance_target_capacity_type = string<br/> instance_allocation_strategy = string<br/> instance_max_spot_price = string<br/> prefix = string<br/> pool = list(object({<br/> schedule_expression = string<br/> schedule_expression_timezone = string<br/> size = number<br/> }))<br/> role_permissions_boundary = string<br/> kms_key_arn = string<br/> ami_kms_key_arn = string<br/> ami_id_ssm_parameter_arn = string<br/> role_path = string<br/> ssm_token_path = string<br/> ssm_config_path = string<br/> ami_id_ssm_parameter_name = string<br/> ami_id_ssm_parameter_read_policy_arn = string<br/> arn_ssm_parameters_path_config = string<br/> lambda_tags = map(string)<br/> user_agent = string<br/> })</pre> | n/a | yes |
52+
| <a name="input_config"></a> [config](#input\_config) | Lookup details in parent module. | <pre>object({<br/> lambda = object({<br/> log_level = string<br/> logging_retention_in_days = number<br/> logging_kms_key_id = string<br/> reserved_concurrent_executions = number<br/> s3_bucket = string<br/> s3_key = string<br/> s3_object_version = string<br/> security_group_ids = list(string)<br/> runtime = string<br/> architecture = string<br/> memory_size = number<br/> timeout = number<br/> zip = string<br/> subnet_ids = list(string)<br/> parameter_store_tags = string<br/> })<br/> tags = map(string)<br/> ghes = object({<br/> url = string<br/> ssl_verify = string<br/> })<br/> github_app_parameters = object({<br/> key_base64 = map(string)<br/> id = map(string)<br/> })<br/> subnet_ids = list(string)<br/> runner = object({<br/> disable_runner_autoupdate = bool<br/> ephemeral = bool<br/> enable_jit_config = bool<br/> enable_on_demand_failover_for_errors = list(string)<br/> boot_time_in_minutes = number<br/> labels = list(string)<br/> launch_template = object({<br/> name = string<br/> })<br/> group_name = string<br/> name_prefix = string<br/> pool_owner = string<br/> role = object({<br/> arn = string<br/> })<br/> })<br/> instance_types = list(string)<br/> instance_target_capacity_type = string<br/> instance_allocation_strategy = string<br/> instance_max_spot_price = string<br/> prefix = string<br/> pool = list(object({<br/> schedule_expression = string<br/> schedule_expression_timezone = string<br/> size = number<br/> }))<br/> role_permissions_boundary = string<br/> kms_key_arn = string<br/> ami_kms_key_arn = string<br/> ami_id_ssm_parameter_arn = string<br/> role_path = string<br/> ssm_token_path = string<br/> ssm_config_path = string<br/> ami_id_ssm_parameter_name = string<br/> ami_id_ssm_parameter_read_policy_arn = string<br/> arn_ssm_parameters_path_config = string<br/> lambda_tags = map(string)<br/> user_agent = string<br/> })</pre> | n/a | yes |
5353
| <a name="input_tracing_config"></a> [tracing\_config](#input\_tracing\_config) | Configuration for lambda tracing. | <pre>object({<br/> mode = optional(string, null)<br/> capture_http_requests = optional(bool, false)<br/> capture_error = optional(bool, false)<br/> })</pre> | `{}` | no |
5454

5555
## Outputs

0 commit comments

Comments
 (0)