From 45dffc76a4131e063bf02baf87b8ec8f77e31dd2 Mon Sep 17 00:00:00 2001 From: Aleksandar Stojanov Date: Tue, 26 Dec 2023 14:39:33 +0100 Subject: [PATCH 1/2] cloudrun disallow envs from secrets - change file structure - fix codeql workflow --- .github/workflows/codeql-analysis.yaml | 1 + CHANGELOG.md | 8 ++++++++ .../{cloudrunService.ts => disallowPublicIngress.ts} | 0 __tests__/cloudrun/index.ts | 2 +- .../{cloudrunv2Service.ts => disallowPublicIngress.ts} | 0 __tests__/cloudrunv2/index.ts | 2 +- .../index.ts => disallowPublicIngress.ts} | 2 +- src/cloudrun/index.ts | 4 ++-- .../index.ts => disallowPublicIngress.ts} | 2 +- src/cloudrunv2/index.ts | 4 ++-- 10 files changed, 17 insertions(+), 8 deletions(-) rename __tests__/cloudrun/{cloudrunService.ts => disallowPublicIngress.ts} (100%) rename __tests__/cloudrunv2/{cloudrunv2Service.ts => disallowPublicIngress.ts} (100%) rename src/cloudrun/{cloudrunDisallowPublicIngress/index.ts => disallowPublicIngress.ts} (93%) rename src/cloudrunv2/{cloudrunv2DisallowPublicIngress/index.ts => disallowPublicIngress.ts} (93%) diff --git a/.github/workflows/codeql-analysis.yaml b/.github/workflows/codeql-analysis.yaml index 974944c..8242a80 100644 --- a/.github/workflows/codeql-analysis.yaml +++ b/.github/workflows/codeql-analysis.yaml @@ -1,6 +1,7 @@ name: CodeQL on: + push: pull_request: branches: - main diff --git a/CHANGELOG.md b/CHANGELOG.md index c0f77c5..6cc4b47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - dependabot npm scan (#4). - `cloudrunv2-disallow-public-ingress` (#5). +### Changed + +- Update test and code file structure (#6). + +### Fixed + +- codeql event on push in main branch (#6). + ## [1.1.0] - 2023-12-25 ### Added diff --git a/__tests__/cloudrun/cloudrunService.ts b/__tests__/cloudrun/disallowPublicIngress.ts similarity index 100% rename from __tests__/cloudrun/cloudrunService.ts rename to __tests__/cloudrun/disallowPublicIngress.ts diff --git a/__tests__/cloudrun/index.ts b/__tests__/cloudrun/index.ts index ba548aa..5bb6120 100644 --- a/__tests__/cloudrun/index.ts +++ b/__tests__/cloudrun/index.ts @@ -1 +1 @@ -export * as cloudrunService from "./cloudrunService" +export * as cloudrunService from "./disallowPublicIngress" diff --git a/__tests__/cloudrunv2/cloudrunv2Service.ts b/__tests__/cloudrunv2/disallowPublicIngress.ts similarity index 100% rename from __tests__/cloudrunv2/cloudrunv2Service.ts rename to __tests__/cloudrunv2/disallowPublicIngress.ts diff --git a/__tests__/cloudrunv2/index.ts b/__tests__/cloudrunv2/index.ts index f4e90b5..8f5ff66 100644 --- a/__tests__/cloudrunv2/index.ts +++ b/__tests__/cloudrunv2/index.ts @@ -1 +1 @@ -export * as cloudrunV2Service from "../cloudrunv2/cloudrunv2Service" +export * as cloudrunV2Service from "./disallowPublicIngress" diff --git a/src/cloudrun/cloudrunDisallowPublicIngress/index.ts b/src/cloudrun/disallowPublicIngress.ts similarity index 93% rename from src/cloudrun/cloudrunDisallowPublicIngress/index.ts rename to src/cloudrun/disallowPublicIngress.ts index f62155b..b68beb9 100644 --- a/src/cloudrun/cloudrunDisallowPublicIngress/index.ts +++ b/src/cloudrun/disallowPublicIngress.ts @@ -1,6 +1,6 @@ import { ResourceValidationArgs, ReportViolation, EnforcementLevel } from "@pulumi/policy"; -export const cloudrunDisallowPublicIngress = { +export const disallowPublicIngress = { name: "cloudrun-disallow-public-ingress", description: "Check that CloudRun services do not have public ingress set to 'all'.", enforcementLevel: "advisory" as EnforcementLevel, diff --git a/src/cloudrun/index.ts b/src/cloudrun/index.ts index aecedc5..648e4dc 100644 --- a/src/cloudrun/index.ts +++ b/src/cloudrun/index.ts @@ -1,5 +1,5 @@ -import { cloudrunDisallowPublicIngress } from "./cloudrunDisallowPublicIngress"; +import { disallowPublicIngress } from "./disallowPublicIngress"; export const cloudrunPolicies = [ - cloudrunDisallowPublicIngress, + disallowPublicIngress, ]; diff --git a/src/cloudrunv2/cloudrunv2DisallowPublicIngress/index.ts b/src/cloudrunv2/disallowPublicIngress.ts similarity index 93% rename from src/cloudrunv2/cloudrunv2DisallowPublicIngress/index.ts rename to src/cloudrunv2/disallowPublicIngress.ts index 3040056..594230f 100644 --- a/src/cloudrunv2/cloudrunv2DisallowPublicIngress/index.ts +++ b/src/cloudrunv2/disallowPublicIngress.ts @@ -1,6 +1,6 @@ import { ResourceValidationArgs, ReportViolation, EnforcementLevel } from "@pulumi/policy"; -export const cloudrunv2DisallowPublicIngress = { +export const disallowPublicIngress = { name: "cloudrunv2-disallow-public-ingress", description: "Check that CloudRun2 services do not have public ingress set to 'all'.", enforcementLevel: "advisory" as EnforcementLevel, diff --git a/src/cloudrunv2/index.ts b/src/cloudrunv2/index.ts index 0df4603..70b5911 100644 --- a/src/cloudrunv2/index.ts +++ b/src/cloudrunv2/index.ts @@ -1,5 +1,5 @@ -import { cloudrunv2DisallowPublicIngress } from "./cloudrunv2DisallowPublicIngress"; +import { disallowPublicIngress } from "./disallowPublicIngress"; export const cloudrunv2Policies = [ - cloudrunv2DisallowPublicIngress, + disallowPublicIngress, ]; From 5041ff3aa95e75b26b44c5f80966bc6d1d79131b Mon Sep 17 00:00:00 2001 From: Aleksandar Stojanov Date: Tue, 26 Dec 2023 17:56:24 +0100 Subject: [PATCH 2/2] disallow environment variables from Secret Manager Signed-off-by: Aleksandar Stojanov --- CHANGELOG.md | 1 + __tests__/cloudrun/disallowPublicIngress.ts | 44 --------------- __tests__/cloudrun/index.ts | 33 +++++++++++- __tests__/cloudrunv2/disallowPublicIngress.ts | 30 ----------- __tests__/cloudrunv2/index.ts | 54 ++++++++++++++++++- __tests__/compute/backendService.ts | 17 ------ __tests__/compute/index.ts | 7 ++- __tests__/index.ts | 6 +-- src/cloudrun/disallowEnvsSecrets.ts | 25 +++++++++ src/cloudrun/index.ts | 2 + src/cloudrunv2/disallowEnvsSecrets.ts | 49 +++++++++++++++++ src/cloudrunv2/disallowPublicIngress.ts | 2 +- src/cloudrunv2/index.ts | 3 ++ 13 files changed, 175 insertions(+), 98 deletions(-) delete mode 100644 __tests__/cloudrun/disallowPublicIngress.ts delete mode 100644 __tests__/cloudrunv2/disallowPublicIngress.ts delete mode 100644 __tests__/compute/backendService.ts create mode 100644 src/cloudrun/disallowEnvsSecrets.ts create mode 100644 src/cloudrunv2/disallowEnvsSecrets.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 6cc4b47..4ce900a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - CodeQL analysis (#4). - dependabot npm scan (#4). - `cloudrunv2-disallow-public-ingress` (#5). +- disallow environment variables from Secret Manager - `cloudrun.Service`, `cloudrunv2.Service` and `cloudrunv2.Job` (#6). ### Changed diff --git a/__tests__/cloudrun/disallowPublicIngress.ts b/__tests__/cloudrun/disallowPublicIngress.ts deleted file mode 100644 index f707963..0000000 --- a/__tests__/cloudrun/disallowPublicIngress.ts +++ /dev/null @@ -1,44 +0,0 @@ -import * as gcp from "@pulumi/gcp"; - -export const clodrunServicePass1 = new gcp.cloudrun.Service("pass#1", { - location: "europe-west1", - template: { - spec: { - containers: [{ - image: "us-docker.pkg.dev/cloudrun/container/hello", - }], - }, - } -}); - -export const clodrunServicePass2 = new gcp.cloudrun.Service("pass#2", { - location: "europe-west1", - metadata: { - annotations: { - "run.googleapis.com/ingress": "internal-only", - }, - }, - template: { - spec: { - containers: [{ - image: "us-docker.pkg.dev/cloudrun/container/hello", - }], - }, - } -}); - -export const clodrunServiceFail1 = new gcp.cloudrun.Service("fail#1", { - location: "europe-west1", - metadata: { - annotations: { - "run.googleapis.com/ingress": "all", - }, - }, - template: { - spec: { - containers: [{ - image: "us-docker.pkg.dev/cloudrun/container/hello", - }], - }, - } -}); diff --git a/__tests__/cloudrun/index.ts b/__tests__/cloudrun/index.ts index 5bb6120..22a840a 100644 --- a/__tests__/cloudrun/index.ts +++ b/__tests__/cloudrun/index.ts @@ -1 +1,32 @@ -export * as cloudrunService from "./disallowPublicIngress" +import * as gcp from "@pulumi/gcp"; + +export const cloudrunPService = new gcp.cloudrun.Service("fail#1", { + location: "europe-west1", + metadata: { + annotations: { + "run.googleapis.com/ingress": "all", + }, + }, + template: { + spec: { + containers: [{ + image: "us-docker.pkg.dev/cloudrun/container/hello", + envs: [ + { + name: "FOO", + value: "bar", + }, + { + name: "SECRET_ENV_VAR", + valueFrom: { + secretKeyRef: { + name: "my-secret", + key: "1", + }, + }, + }, + ], + }], + }, + } +}); diff --git a/__tests__/cloudrunv2/disallowPublicIngress.ts b/__tests__/cloudrunv2/disallowPublicIngress.ts deleted file mode 100644 index 7bd8374..0000000 --- a/__tests__/cloudrunv2/disallowPublicIngress.ts +++ /dev/null @@ -1,30 +0,0 @@ -import * as gcp from "@pulumi/gcp"; - -export const clodrunv2ServicePass1 = new gcp.cloudrunv2.Service("pass#1", { - location: "europe-west1", - template: { - containers: [{ - image: "us-docker.pkg.dev/cloudrun/container/hello", - }], - }, -}); - -export const clodrunv2ServicePass2 = new gcp.cloudrunv2.Service("pass#2", { - location: "europe-west1", - ingress: "INGRESS_TRAFFIC_INTERNAL_LOAD_BALANCER", - template: { - containers: [{ - image: "us-docker.pkg.dev/cloudrun/container/hello", - }], - }, -}); - -export const clodrunv2ServiceFail1 = new gcp.cloudrunv2.Service("fail#1", { - location: "europe-west1", - ingress: "INGRESS_TRAFFIC_ALL", - template: { - containers: [{ - image: "us-docker.pkg.dev/cloudrun/container/hello", - }], - }, -}); \ No newline at end of file diff --git a/__tests__/cloudrunv2/index.ts b/__tests__/cloudrunv2/index.ts index 8f5ff66..8afd321 100644 --- a/__tests__/cloudrunv2/index.ts +++ b/__tests__/cloudrunv2/index.ts @@ -1 +1,53 @@ -export * as cloudrunV2Service from "./disallowPublicIngress" +import * as gcp from "@pulumi/gcp"; + +export const cloudrunv2Service = new gcp.cloudrunv2.Service("fail#1", { + location: "europe-west1", + ingress: "INGRESS_TRAFFIC_ALL", + template: { + containers: [{ + image: "us-docker.pkg.dev/cloudrun/container/hello", + envs: [ + { + name: "FOO", + value: "bar", + }, + { + name: "SECRET_ENV_VAR", + valueSource: { + secretKeyRef: { + secret: "my-secret", + version: "1", + }, + }, + }, + ], + }], + }, +}); + +export const cloudrunv2SJob = new gcp.cloudrunv2.Job("fail#1", { + location: "europe-west1", + template: { + template: { + containers: [{ + image: "us-docker.pkg.dev/cloudrun/container/hello", + envs: [ + { + name: "FOO", + value: "bar", + }, + { + name: "SECRET_ENV_VAR", + valueSource: { + secretKeyRef: { + secret: "my-secret", + version: "1", + }, + }, + }, + ], + }], + }, + }, +}); + diff --git a/__tests__/compute/backendService.ts b/__tests__/compute/backendService.ts deleted file mode 100644 index b9acc1e..0000000 --- a/__tests__/compute/backendService.ts +++ /dev/null @@ -1,17 +0,0 @@ -import * as gcp from "@pulumi/gcp"; - -export const backendServicePass1 = new gcp.compute.BackendService("pass#1", { - name: "pass#1", - securityPolicy: "projects/123456789/global/securityPolicies/foo" -}); - -export const backendServicePass2 = new gcp.compute.BackendService("pass#2", { - name: "pass#1", - loadBalancingScheme: "EXTERNAL", - securityPolicy: "projects/123456789/global/securityPolicies/foo" -}); - -export const backendServiceFail1 = new gcp.compute.BackendService("fail#1", { - name: "fail#1", - loadBalancingScheme: "EXTERNAL" -}); diff --git a/__tests__/compute/index.ts b/__tests__/compute/index.ts index 98e178c..e6092fa 100644 --- a/__tests__/compute/index.ts +++ b/__tests__/compute/index.ts @@ -1 +1,6 @@ -export * as backendService from "./backendService" +import * as gcp from "@pulumi/gcp"; + +export const backendService = new gcp.compute.BackendService("fail#1", { + name: "fail#1", + loadBalancingScheme: "EXTERNAL" +}); diff --git a/__tests__/index.ts b/__tests__/index.ts index ef25f64..5a80315 100644 --- a/__tests__/index.ts +++ b/__tests__/index.ts @@ -1,3 +1,3 @@ -export * as cloudrun from './cloudrun/index' -export * as cloudrunv2 from './cloudrunv2/index' -export * as compute from './compute/index' +export * as cloudrun from './cloudrun' +export * as cloudrunv2 from './cloudrunv2' +export * as compute from './compute' diff --git a/src/cloudrun/disallowEnvsSecrets.ts b/src/cloudrun/disallowEnvsSecrets.ts new file mode 100644 index 0000000..2a738e6 --- /dev/null +++ b/src/cloudrun/disallowEnvsSecrets.ts @@ -0,0 +1,25 @@ +import { ResourceValidationArgs, ReportViolation, EnforcementLevel } from "@pulumi/policy"; + +export const disallowEnvsSecrets = { + name: "cloudrun-service-disallow-envs-secrets", + description: "Check that CloudRun services do not use environment variables from secrets.", + enforcementLevel: "advisory" as EnforcementLevel, + validateResource: (args: ResourceValidationArgs, reportViolation: ReportViolation) => { + if (args.type === "gcp:cloudrun/service:Service") { + const containers = args.props.template.spec.containers; + if (containers) { + containers.forEach((container: any) => { + if (container.envs) { + container.envs.forEach((env: any) => { + if (env?.valueFrom?.secretKeyRef) { + reportViolation( + "CloudRun services should use secrets as mounted volumes." + ); + } + }); + } + }); + } + } + }, +} diff --git a/src/cloudrun/index.ts b/src/cloudrun/index.ts index 648e4dc..1f06aea 100644 --- a/src/cloudrun/index.ts +++ b/src/cloudrun/index.ts @@ -1,5 +1,7 @@ import { disallowPublicIngress } from "./disallowPublicIngress"; +import { disallowEnvsSecrets } from "./disallowEnvsSecrets"; export const cloudrunPolicies = [ + disallowEnvsSecrets, disallowPublicIngress, ]; diff --git a/src/cloudrunv2/disallowEnvsSecrets.ts b/src/cloudrunv2/disallowEnvsSecrets.ts new file mode 100644 index 0000000..b6d5e10 --- /dev/null +++ b/src/cloudrunv2/disallowEnvsSecrets.ts @@ -0,0 +1,49 @@ +import { ResourceValidationArgs, ReportViolation, EnforcementLevel } from "@pulumi/policy"; + +export const serviceDisallowEnvsSecrets = { + name: "cloudrunv2-service-disallow-envs-secrets", + description: "Check that CloudRun2 services do not use environment variables from secrets.", + enforcementLevel: "advisory" as EnforcementLevel, + validateResource: (args: ResourceValidationArgs, reportViolation: ReportViolation) => { + if (args.type === "gcp:cloudrunv2/service:Service") { + const containers = args.props.template.containers; + if (containers) { + containers.forEach((container: any) => { + if (container.envs) { + container.envs.forEach((env: any) => { + if (env?.valueSource?.secretKeyRef) { + reportViolation( + "CloudRun2 services should use secrets as mounted volumes." + ); + } + }); + } + }); + } + } + }, +} + +export const jobDisallowEnvsSecrets = { + name: "cloudrunv2-job-disallow-envs-secrets", + description: "Check that CloudRun2 jobs do not use environment variables from secrets.", + enforcementLevel: "advisory" as EnforcementLevel, + validateResource: (args: ResourceValidationArgs, reportViolation: ReportViolation) => { + if (args.type === "gcp:cloudrunv2/job:Job") { + const containers = args.props.template.template.containers; + if (containers) { + containers.forEach((container: any) => { + if (container.envs) { + container.envs.forEach((env: any) => { + if (env?.valueSource?.secretKeyRef) { + reportViolation( + "CloudRun2 jobs should use secrets as mounted volumes." + ); + } + }); + } + }); + } + } + }, +} diff --git a/src/cloudrunv2/disallowPublicIngress.ts b/src/cloudrunv2/disallowPublicIngress.ts index 594230f..460ba30 100644 --- a/src/cloudrunv2/disallowPublicIngress.ts +++ b/src/cloudrunv2/disallowPublicIngress.ts @@ -1,7 +1,7 @@ import { ResourceValidationArgs, ReportViolation, EnforcementLevel } from "@pulumi/policy"; export const disallowPublicIngress = { - name: "cloudrunv2-disallow-public-ingress", + name: "cloudrunv2-service-disallow-public-ingress", description: "Check that CloudRun2 services do not have public ingress set to 'all'.", enforcementLevel: "advisory" as EnforcementLevel, validateResource: (args: ResourceValidationArgs, reportViolation: ReportViolation) => { diff --git a/src/cloudrunv2/index.ts b/src/cloudrunv2/index.ts index 70b5911..4218d78 100644 --- a/src/cloudrunv2/index.ts +++ b/src/cloudrunv2/index.ts @@ -1,5 +1,8 @@ import { disallowPublicIngress } from "./disallowPublicIngress"; +import { serviceDisallowEnvsSecrets, jobDisallowEnvsSecrets } from "./disallowEnvsSecrets"; export const cloudrunv2Policies = [ + serviceDisallowEnvsSecrets, + jobDisallowEnvsSecrets, disallowPublicIngress, ];