Skip to content

Commit

Permalink
feat: Add tracking and update cdk for security fixes (#18)
Browse files Browse the repository at this point in the history
* feat: track if installed, updated or deleted

* chore: update to latest cdk and eks blueprint versions

This incorporates recent security fixes

---------

Co-authored-by: Steffen Neubauer <steffen@garden.io>
  • Loading branch information
twelvemo and stefreak committed Jun 1, 2023
1 parent 2409082 commit 0f27b95
Show file tree
Hide file tree
Showing 8 changed files with 2,999 additions and 398 deletions.
1 change: 1 addition & 0 deletions .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ jobs:
npm run rain
env:
CDK_RELEASE_VERSION: "${{ steps.release.outputs.major }}.${{ steps.release.outputs.minor }}.${{ steps.release.outputs.patch }}"
CDK_ENVIRONMENT: prod

- name: Archive release assets
if: ${{ steps.release.outputs.release_created }}
Expand Down
12 changes: 7 additions & 5 deletions cdk.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,20 @@
},
"context": {
"GardenDevClusterStackID": "garden-dev-cluster",

"EKSClusterName": "garden-dev-cluster",
"EKSNodeGroupMinSize": 1,
"EKSNodeGroupMaxSize": 10,

"ECRRepositories": "api,result,vote,worker",
"ECRPrefix": "garden-dev-cluster",

"IAMEKSFullAccessRole": "",
"IAMEKSFullAccessPrincipals": "",

"IngressSubdomain": "",
"IngressRoute53HostedZoneId": ""
"IngressRoute53HostedZoneId": "",
"dev": {
"SegmentAPIWriteKey": "7f9LMF7SUiOJHp1DKGGMTWAsMQVATmga"
},
"prod": {
"SegmentAPIWriteKey": "n28eGgbHFaNYAUe09O0j29hYOXhsCYj7"
}
}
}
3,217 changes: 2,831 additions & 386 deletions package-lock.json

Large diffs are not rendered by default.

16 changes: 10 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@
"description": "Garden development cluster CDK and CFN quickstart, batteries included.",
"main": "src/index.ts",
"dependencies": {
"@aws-quickstart/eks-blueprints": "=1.6.0",
"@types/aws-lambda": "^8.10.114",
"aws-cdk-lib": "=2.66.1",
"@aws-quickstart/eks-blueprints": "=1.8.1",
"@segment/analytics-node": "^1.0.0-beta.26",
"@types/aws-lambda": "^8.10.115",
"aws-cdk-lib": "=2.81.0",
"aws-lambda": "^1.0.7",
"cdk": "^2.73.0-alpha.0",
"cdk-assets": "^2.73.0-alpha.0",
"constructs": "=10.1.252"
"cdk": "^2.81.0-alpha.0",
"cdk-assets": "^2.81.0",
"constructs": "=10.2.39",
"hasha": "^5.2.2",
"pjson": "^1.0.9"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
Expand All @@ -25,6 +28,7 @@
"license": "MPL-2.0",
"homepage": "https://github.com/garden-io/dev-cluster",
"devDependencies": {
"@types/analytics-node": "^3.1.11",
"ts-node": "^10.9.1"
}
}
14 changes: 14 additions & 0 deletions src/constructs/garden-addon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import * as iam from "aws-cdk-lib/aws-iam";
import * as cdk from "aws-cdk-lib";
import { ECRRepositories } from "./ecr-repositories";
import { EKSCleanupLB } from "./eks-cleanuplb";
import { TrackUsage } from "./tracking";
import { GardenEKSDevCluster } from "../stacks/garden-dev-cluster";
var pjson = require("pjson");

export interface GardenAddOnProps {
readonly accountId: string
Expand Down Expand Up @@ -45,6 +47,9 @@ export class GardenAddOn implements ClusterAddOn {

// fix cluster deletion
this.addCleanupLBHack(clusterInfo)

//track usage
this.trackUsage(clusterInfo)
}

private addCleanupLBHack(clusterInfo: ClusterInfo) {
Expand All @@ -64,6 +69,15 @@ export class GardenAddOn implements ClusterAddOn {
})
}

private trackUsage(clusterInfo: ClusterInfo) {
const cluster = clusterInfo.cluster
new TrackUsage(cluster, "TrackUsage", {
account: this.props.accountId,
stackVersion: pjson.version,
parameters: this.props.parameters
})
}

private createFullAccessIAMRoleIfNeeded(clusterInfo: ClusterInfo) {
const cluster = clusterInfo.cluster
const parameters = this.props.parameters
Expand Down
69 changes: 69 additions & 0 deletions src/constructs/tracking.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import * as path from 'path';
import { CustomResource, Stack } from 'aws-cdk-lib';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as lambdaNodejs from 'aws-cdk-lib/aws-lambda-nodejs';
import * as cr from 'aws-cdk-lib/custom-resources';
import { Construct } from 'constructs';
import * as cdk from "aws-cdk-lib";
import { PROP_ACCOUNT, PROP_SEGMENT_KEY, PROP_CF_STACK_ARN, PROP_VERSION, PROP_FULL_ACCESS_ROLE, PROP_FULL_ACCESS_PRINCIPALS, PROP_CLUSTER_NAME, PROP_ECR_PREFIX, PROP_ECR_REPO_NAMES, PROP_HOSTEDZONE_ID, PROP_MAX_NODEGROUP_SIZE, PROP_MIN_NODEGROUP_SIZE, PROP_SUBDOMAIN} from '../functions/tracking';
import { GardenEKSDevCluster} from '../stacks/garden-dev-cluster';


export const cdkEnvironment: string = process.env.CDK_ENVIRONMENT || 'dev';
interface TrackUsageProps {
stackVersion: string;
account: string;
parameters: typeof GardenEKSDevCluster.parameters;
}

export class TrackUsage extends Construct {
constructor(scope: Construct, id: string, props: TrackUsageProps) {
super(scope, id);

new CustomResource(this, 'Resource', {
serviceToken: TrackUsageProvider.getOrCreate(this),
resourceType: 'Custom::TrackUsage',
properties: {
[PROP_SEGMENT_KEY]: this.node.tryGetContext(cdkEnvironment).SegmentAPIWriteKey,
[PROP_VERSION]: props.stackVersion,
[PROP_ACCOUNT]: props.account,
[PROP_CF_STACK_ARN]: cdk.Stack.of(scope).stackId,
[PROP_FULL_ACCESS_ROLE]: props.parameters.fullAccessRole,
[PROP_FULL_ACCESS_PRINCIPALS]: props.parameters.fullAccessPrincipals,
[PROP_ECR_REPO_NAMES]: props.parameters.ecrRepoNames,
[PROP_ECR_PREFIX]: props.parameters.ecrPrefix,
[PROP_SUBDOMAIN]: props.parameters.subdomain,
[PROP_HOSTEDZONE_ID]: props.parameters.hostedZoneID,
[PROP_CLUSTER_NAME]: props.parameters.clusterName,
[PROP_MIN_NODEGROUP_SIZE]: props.parameters.minNodeGroupSize,
[PROP_MAX_NODEGROUP_SIZE]: props.parameters.maxNodeGroupSize
},
});
}
}

class TrackUsageProvider extends Construct {

/**
* Returns the singleton provider.
*/
public static getOrCreate(scope: Construct) {
const stack = Stack.of(scope);
const id = 'garden.custom-track-usage-provider';
const x = stack.node.tryFindChild(id) as TrackUsageProvider || new TrackUsageProvider(stack, id);
return x.provider.serviceToken;
}

private readonly provider: cr.Provider;

constructor(scope: Construct, id: string) {
super(scope, id);

this.provider = new cr.Provider(this, 'track-usage-provider', {
onEventHandler: new lambdaNodejs.NodejsFunction(this, 'tracking-on-event', {
runtime: lambda.Runtime.NODEJS_18_X ,
entry: path.join(__dirname, '..', 'functions', 'tracking.ts'),
}),
});
}
}
4 changes: 3 additions & 1 deletion src/functions/ecr-repositories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@ export async function handler(event: AWSCDKAsyncCustomResource.OnEventRequest):

// get deleted repos
for (const repo of oldRepos.filter((r) => !newRepos.includes(r))) {
console.log(`deleting repo ${prefix}/${repo}`)
await deleteRepo(prefix, repo)
}

for (const repo of newRepos.filter((r) => !oldRepos.includes(r))) {
createRepo(prefix, repo)
console.log(`creating repo ${prefix}/${repo}`)
await createRepo(prefix, repo)
}
return {}

Expand Down
64 changes: 64 additions & 0 deletions src/functions/tracking.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import * as AWSCDKAsyncCustomResource from 'aws-cdk-lib/custom-resources/lib/provider-framework/types';
import Analytics from "@segment/analytics-node";
import hasha = require("hasha");

export const PROP_SEGMENT_KEY = "segmentApiKey"
export const PROP_VERSION = "gardenDevClusterVersion"
export const PROP_ACCOUNT = "awsAccount"
export const PROP_CF_STACK_ARN = "cloudformationStackArn"
export const PROP_FULL_ACCESS_ROLE = "iamFullAccessRole"
export const PROP_FULL_ACCESS_PRINCIPALS = "iamFullAccessPrincipals"
export const PROP_ECR_REPO_NAMES = "ecrRepoNames"
export const PROP_ECR_PREFIX = "ecrPrefix"
export const PROP_SUBDOMAIN = "subdomain"
export const PROP_HOSTEDZONE_ID = "hostedzoneID"
export const PROP_CLUSTER_NAME = "clusterName"
export const PROP_MIN_NODEGROUP_SIZE = "minNodegroupSize"
export const PROP_MAX_NODEGROUP_SIZE = "maxNodegroupSize"

export async function handler(event: AWSCDKAsyncCustomResource.OnEventRequest): Promise<AWSCDKAsyncCustomResource.OnEventResponse> {
const version: string = event.ResourceProperties[PROP_VERSION]
const accountHash: string = hasha(event.ResourceProperties[PROP_ACCOUNT],{algorithm: "sha512"})
const cfnStackArnHash: string = hasha(event.ResourceProperties[PROP_CF_STACK_ARN], {algorithm: 'sha512'}).slice(0,64)
const analytics = new Analytics({writeKey: event.ResourceProperties[PROP_SEGMENT_KEY]})
switch (event.RequestType) {
case 'Create':
analytics.track({
anonymousId: cfnStackArnHash,
event: "Installed dev-cluster",
properties: {
version: version,
accountHash: accountHash,
platform: "AWS"
},
})
await analytics.closeAndFlush()
return {}

case 'Update':
analytics.track({
anonymousId: cfnStackArnHash,
event: "Updated dev-cluster",
properties: {
version: version,
accountHash: accountHash,
platform: "AWS"
},
})
await analytics.closeAndFlush()
return {}

case 'Delete':
analytics.track({
anonymousId: cfnStackArnHash,
event: "Deleted dev-cluster",
properties: {
version: version,
accountHash: accountHash,
platform: "AWS"
},
})
await analytics.closeAndFlush()
return {}
}
}

0 comments on commit 0f27b95

Please sign in to comment.