Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add ubuntu agent and cdn with lambda@edge resource for public access #134

Merged
merged 4 commits into from
Jun 17, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/cdk.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,7 @@ jobs:
- name: Run CDK Build and Test
run: |
npm install
cd resources/cf-url-rewriter
npm install
cd -
npm run build
4 changes: 4 additions & 0 deletions bin/ci-stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import { App, RemovalPolicy } from '@aws-cdk/core';
import { CIStack } from '../lib/ci-stack';
import { CIConfigStack } from '../lib/ci-config-stack';
import { CiCdnStack } from '../lib/ci-cdn-stack';

const app = new App();

Expand All @@ -17,3 +18,6 @@ const defaultEnv: string = 'Dev';
const ciConfigStack = new CIConfigStack(app, `OpenSearch-CI-Config-${defaultEnv}`, {});

const ciStack = new CIStack(app, `OpenSearch-CI-${defaultEnv}`, {});

const ciCdnStack = new CiCdnStack(app, `OpenSearch-CI-Cdn-${defaultEnv}`, {});
ciCdnStack.addDependency(ciStack);
69 changes: 69 additions & 0 deletions lib/buildArtefacts/artifacts-public-access.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/**
gaiksaya marked this conversation as resolved.
Show resolved Hide resolved
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/

import { Bucket } from '@aws-cdk/aws-s3';
import {
CloudFrontAllowedMethods, CloudFrontWebDistribution, LambdaEdgeEventType, OriginAccessIdentity,
} from '@aws-cdk/aws-cloudfront';
import { CanonicalUserPrincipal, PolicyStatement } from '@aws-cdk/aws-iam';
import { NodejsFunction } from '@aws-cdk/aws-lambda-nodejs';
import { Architecture, Runtime } from '@aws-cdk/aws-lambda';
import { CfnOutput, Duration } from '@aws-cdk/core';
import { CiCdnStack } from '../ci-cdn-stack';

export class ArtifactsPublicAccess {
constructor(stack: CiCdnStack, buildBucketArn: string) {
const buildBucket = Bucket.fromBucketArn(stack, 'artifactBuildBucket', `${buildBucketArn.toString()}`);

const originAccessIdentity = new OriginAccessIdentity(stack, 'cloudfront-OAI', {
comment: `OAI for ${buildBucket.bucketName}`,
});

buildBucket.addToResourcePolicy(new PolicyStatement({
actions: ['s3:GetObject'],
resources: [buildBucket.arnForObjects('*')],
principals: [new CanonicalUserPrincipal(originAccessIdentity.cloudFrontOriginAccessIdentityS3CanonicalUserId)],
}));

const urlRewriter = new NodejsFunction(stack, 'CfUrlRewriter', {
runtime: Runtime.NODEJS_14_X,
entry: `${__dirname}/../../resources/cf-url-rewriter/cf-url-rewriter.ts`,
handler: 'handler',
memorySize: 128,
architecture: Architecture.X86_64,
});

const distro = new CloudFrontWebDistribution(stack, 'CloudFrontBuildBucket', {
originConfigs: [
{
s3OriginSource: {
s3BucketSource: buildBucket,
originAccessIdentity,
},
behaviors: [
{
isDefaultBehavior: true,
compress: true,
allowedMethods: CloudFrontAllowedMethods.GET_HEAD,
lambdaFunctionAssociations: [{
eventType: LambdaEdgeEventType.VIEWER_REQUEST,
lambdaFunction: urlRewriter.currentVersion,
}],
defaultTtl: Duration.seconds(300),
},
],
},
],
});

new CfnOutput(stack, 'BuildDistributionDomainName', {
value: distro.distributionDomainName,
description: 'The domain name where the build artifacts will be available',
});
}
}
93 changes: 93 additions & 0 deletions lib/buildArtefacts/build-artifacts-permissions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/**
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/

import { Stack } from '@aws-cdk/core';
import {
ArnPrincipal, Effect, Policy, PolicyStatement, Role,
} from '@aws-cdk/aws-iam';
import { CiCdnStack } from '../ci-cdn-stack';

export interface buildArtifactProps {
mainNodeArn: string,
agentNodeArn: string,
buildBucketArn: string
}

export class BuildArtifactsPermissions {
private static readonly BUNDLE_ROLE_NAME = 'opensearch-bundle';

constructor(stack: CiCdnStack, props: buildArtifactProps) {
const opensearchBundleRole = new Role(stack, BuildArtifactsPermissions.BUNDLE_ROLE_NAME, {
assumedBy: Role.fromRoleArn(stack, 'MainNodeRole', `${props.mainNodeArn}`),
roleName: 'opensearch-bundle',
});

opensearchBundleRole.assumeRolePolicy?.addStatements(new PolicyStatement({
actions: ['sts:AssumeRole'],
principals: [new ArnPrincipal(`${props.agentNodeArn}`)],
}));

const opensearchBundlePolicies = BuildArtifactsPermissions.getOpensearchBundlePolicies(stack, props.buildBucketArn);
opensearchBundlePolicies.forEach((policy) => {
policy.attachToRole(opensearchBundleRole);
});
}

private static getOpensearchBundlePolicies(scope: Stack, s3BucketArn: string): Policy[] {
const policies: Policy[] = [];
const signingPolicy = new Policy(scope, 'signing-policy', {
statements: [
new PolicyStatement(
{
actions: ['sts:AssumeRole'],
resources: ['arn:aws:iam::447201093745:role/OpenSearchSignerPGPSigning-ArtifactAccessRole'],
effect: Effect.ALLOW,
},
),
],
});

const openSearchBundlePolicy = new Policy(scope, 'opensearch-bundle-policy', {
statements: [
new PolicyStatement({
actions: [
's3:GetObject*',
's3:GetBucket*',
's3:List*',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should not allow listing. @peterzhuamazon can weigh in here regarding security concerns. If not required can we remove it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have replicated the same permission as present in current opensearch-bundle role in current jenkins account

],
resources: [`${s3BucketArn}`],
effect: Effect.ALLOW,
}),
new PolicyStatement(
{
actions: [
's3:GetObject*',
's3:GetBucket*',
's3:List*',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above

's3:PutObject',
's3:PutObjectLegalHold',
's3:PutObjectRetention',
's3:PutObjectTagging',
's3:PutObjectVersionTagging',
's3:Abort*',
],
resources: [
`${s3BucketArn}/*/builds/*`,
`${s3BucketArn}/*/shas/*`,
`${s3BucketArn}/*/dist/*`,
`${s3BucketArn}/*/index.json`,
],
effect: Effect.ALLOW,
},
),
],
});
policies.push(signingPolicy, openSearchBundlePolicy);
return policies;
}
}
30 changes: 30 additions & 0 deletions lib/ci-cdn-stack.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/

import {
Construct, Fn, Stack, StackProps,
} from '@aws-cdk/core';
import { BuildArtifactsPermissions } from './buildArtefacts/build-artifacts-permissions';
import { ArtifactsPublicAccess } from './buildArtefacts/artifacts-public-access';

export class CiCdnStack extends Stack {
constructor(scope: Construct, id: string, props: StackProps) {
super(scope, id, props);
const mainNodeRoleArn = Fn.importValue('mainNodeRoleArn');
const agentNodeRoleArn = Fn.importValue('agentNodeRoleArn');
const buildBucketArn = Fn.importValue('buildBucketArn');

const buildArtifacts = new BuildArtifactsPermissions(this, {
mainNodeArn: mainNodeRoleArn,
agentNodeArn: agentNodeRoleArn,
buildBucketArn,
});

const artifactPublicAccess = new ArtifactsPublicAccess(this, buildBucketArn);
}
}
12 changes: 11 additions & 1 deletion lib/ci-stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@
import { FlowLogDestination, FlowLogTrafficType, Vpc } from '@aws-cdk/aws-ec2';
import { Secret } from '@aws-cdk/aws-secretsmanager';
import {
CfnOutput,
CfnParameter, Construct, Fn, RemovalPolicy, Stack, StackProps,
} from '@aws-cdk/core';
import { ListenerCertificate } from '@aws-cdk/aws-elasticloadbalancingv2';
import { FileSystem } from '@aws-cdk/aws-efs';
import { Bucket } from '@aws-cdk/aws-s3';
import { CIConfigStack } from './ci-config-stack';
import { JenkinsMainNode } from './compute/jenkins-main-node';
import { JenkinsMonitoring } from './monitoring/ci-alarms';
Expand Down Expand Up @@ -96,7 +98,8 @@ export class CIStack extends Stack {
const certificateArn = Secret.fromSecretCompleteArn(this, 'certificateArn', importedArnSecretBucketValue.toString());
const listenerCertificate = ListenerCertificate.fromArn(certificateArn.secretValue.toString());
const agentNode = new AgentNodes(this);
const agentNodes: AgentNodeProps[] = [agentNode.AL2_X64, agentNode.AL2_X64_DOCKER_1, agentNode.AL2_ARM64, agentNode.AL2_ARM64_DOCKER_1];
const agentNodes: AgentNodeProps[] = [agentNode.AL2_X64, agentNode.AL2_X64_DOCKER_1, agentNode.AL2_ARM64, agentNode.AL2_ARM64_DOCKER_1,
agentNode.UBUNTU_X64_DOCKER];

const mainJenkinsNode = new JenkinsMainNode(this, {
vpc,
Expand Down Expand Up @@ -124,10 +127,17 @@ export class CIStack extends Stack {
useSsl,
});

const artifactBucket = new Bucket(this, 'BuildBucket');

this.monitoring = new JenkinsMonitoring(this, externalLoadBalancer, mainJenkinsNode);

if (additionalCommandsContext.toString() !== 'undefined') {
new RunAdditionalCommands(this, additionalCommandsContext.toString());
}

new CfnOutput(this, 'Artifact Bucket Arn', {
value: artifactBucket.bucketArn.toString(),
exportName: 'buildBucketArn',
});
}
}
9 changes: 9 additions & 0 deletions lib/compute/agent-nodes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ export class AgentNodes {

readonly AL2_ARM64_DOCKER_1: AgentNodeProps;

readonly UBUNTU_X64_DOCKER: AgentNodeProps;

constructor(stack: Stack) {
this.AL2_X64 = {
workerLabelString: 'AL2-X64',
Expand Down Expand Up @@ -61,5 +63,12 @@ export class AgentNodes {
amiId: 'ami-020c52efb1a60f1ae',
initScript: 'sudo yum update -y || sudo yum update -y',
};
this.UBUNTU_X64_DOCKER = {
workerLabelString: 'Jenkins-Agent-Ubuntu2004-X64-m52xlarge-Docker-Builder',
instanceType: 'M52xlarge',
remoteUser: 'ubuntu',
amiId: 'ami-0f6ceb3b3687a3fba',
rishabh6788 marked this conversation as resolved.
Show resolved Hide resolved
initScript: 'sudo apt-mark hold docker docker.io openssh-server && docker ps',
};
}
}
Loading