Skip to content

Commit d1d5874

Browse files
committed
Initial commit
0 parents  commit d1d5874

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+58209
-0
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
node_modules
2+
dist
3+
cdk.out
4+
.DS_Store
5+
*.iml
6+
*.idea

Infra/README.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Cross Talk Infrastructure
2+
3+
This package defines the infrastructure for the Cross Talk video chat sample using the Cloud Development Kit (CDK).
4+
5+
## Development
6+
7+
### Prerequisites
8+
9+
- The [aws-cli](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html) must be installed *and* configured with an AWS account on the deployment machine (see https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html for instructions on how to do this on your preferred development platform).
10+
- This project requires Node.js ≥ 10.17.0 and NPM.
11+
[Node](http://nodejs.org/) and [NPM](https://npmjs.org/) are really easy to install.
12+
To make sure you have them available on your machine, try running the following command.
13+
```sh
14+
npm -v && node -v
15+
```
16+
- Install or update the [AWS CDK CLI] from npm.
17+
```sh
18+
npm i -g aws-cdk
19+
```
20+
21+
### Install
22+
23+
#### 1/ Bootstrapping your AWS account
24+
25+
You only need to do this one time per environment where you want to deploy CDK applications.
26+
If you’re unsure whether your environment has been bootstrapped already, you can always run
27+
the command again.
28+
29+
Make sure you have credentials for **ACCOUNT** (replace with your AWS account ID) in a profile
30+
named **account-profile**. For more information, see [Named profiles](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-profiles.html).
31+
Run the following command in this `Infra` directory:
32+
33+
```sh
34+
npm install
35+
cdk bootstrap \
36+
--profile account-profile \
37+
--cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess \
38+
aws://ACCOUNT1/ap-southeast-2
39+
```
40+
41+
#### 2/ Deploying
42+
43+
A convenience script is provided to deploy all infrastructure to your environment. This builds
44+
all the lambdas, the website, the infrastructure and then initiates the CDK deployment.
45+
46+
```
47+
./deployStack.sh --profile <your_account_profile>
48+
```

Infra/bin/app.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/usr/bin/env node
2+
3+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4+
// SPDX-License-Identifier: MIT-0
5+
6+
import "source-map-support/register";
7+
import * as cdk from "@aws-cdk/core";
8+
import { AppStacks } from "../lib/AppStacks";
9+
10+
const app = new cdk.App();
11+
new AppStacks(app, "CrossTalkStacks");
12+
app.synth();

Infra/cdk.context.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"application": "CrossTalk"
3+
}

Infra/cdk.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"app": "npx ts-node bin/app.ts",
3+
"context": {
4+
"@aws-cdk/core:enableStackNameDuplicates": "true",
5+
"aws-cdk:enableDiffNoFail": "true",
6+
"@aws-cdk/core:newStyleStackSynthesis": "true"
7+
}
8+
}

Infra/deployStack.sh

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#!/bin/bash
2+
3+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
4+
# SPDX-License-Identifier: MIT-0
5+
6+
set -e;
7+
8+
CDK_PROFILE=default
9+
while [[ "$#" -gt 0 ]]; do case $1 in
10+
--profile) CDK_PROFILE="$2"; shift;;
11+
esac; shift; done
12+
13+
# Build all the lambdas
14+
cd ../Lambdas/Common && npm i && npm run build
15+
cd ../ChimeCallService && npm i && npm run build
16+
cd ..
17+
18+
# Build the website
19+
cd ../Website && npm i && npm run build
20+
21+
# Build the infrastructure cdk code
22+
cd ../Infra && npm i && npm run build
23+
24+
# Synth and deploy the sandbox stack
25+
cdk --profile $CDK_PROFILE synth && cdk --profile $CDK_PROFILE deploy '*' --require-approval never

Infra/lib/AppStacks.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: MIT-0
3+
4+
import {Construct, Stage, StageProps, Tags} from "@aws-cdk/core";
5+
import {CognitoAuthStack} from "./stack/CognitoAuthStack";
6+
import {StaticWebsiteStack} from "./stack/StaticWebsiteStack";
7+
import {ApiStack} from "./stack/ApiStack";
8+
import {AppSyncStack} from "./stack/AppSyncStack";
9+
import {UserPoolStack} from "./stack/UserPoolStack";
10+
11+
export class AppStacks extends Construct {
12+
constructor(scope: Construct, id: string) {
13+
super(scope, id);
14+
15+
// see comment in source for this stack to understand why we inject this
16+
// into the cognito stack instead of doing it sanely...
17+
const userPoolStack = new UserPoolStack(this, 'UserPoolStack');
18+
19+
const appsyncStack = new AppSyncStack(this, 'AppSyncStack', {
20+
userPool: userPoolStack.userPool
21+
});
22+
23+
const apiStack = new ApiStack(this, 'ApiStack', {
24+
graphqlEndpoint: appsyncStack.graphqlApi.graphqlUrl
25+
});
26+
27+
const authStack = new CognitoAuthStack(this, 'CognitoAuthStack', {
28+
meetingProviderApi: apiStack.meetingApi,
29+
userPool: userPoolStack.userPool,
30+
graphqlApiArn: appsyncStack.graphqlApi.arn
31+
});
32+
33+
new StaticWebsiteStack(this, 'StaticWebsiteStack', {
34+
identityPoolId: authStack.identityPoolId,
35+
userPoolClientId: authStack.userPoolClientId,
36+
userPoolId: userPoolStack.userPool.userPoolId,
37+
graphqlEndpoint: appsyncStack.graphqlApi.graphqlUrl,
38+
apiUrl: apiStack.meetingApi.api.url
39+
});
40+
}
41+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: MIT-0
3+
4+
import { Construct, Duration, Stack } from "@aws-cdk/core";
5+
import * as apigateway from "@aws-cdk/aws-apigateway";
6+
import * as iam from "@aws-cdk/aws-iam";
7+
import { AuthorizationType } from "@aws-cdk/aws-apigateway";
8+
import * as lambda from "@aws-cdk/aws-lambda";
9+
import { getLambdaPath } from "../utils/lambda";
10+
11+
export interface MeetingProviderProps {
12+
lambdaAssetDirectory: string;
13+
environment: { [key: string]: string };
14+
policyStatements: iam.PolicyStatement[];
15+
}
16+
17+
export interface MeetingProviderApi {
18+
api: apigateway.RestApi;
19+
queryPath: string;
20+
}
21+
22+
export default class MeetingProvider extends Construct {
23+
public readonly api: MeetingProviderApi;
24+
25+
constructor(scope: Stack, id: string, props: MeetingProviderProps) {
26+
super(scope, id);
27+
28+
const apiDefaults = {
29+
restApiName: `${id}Api`,
30+
description: `${id}Api`,
31+
defaultCorsPreflightOptions: {
32+
allowOrigins: apigateway.Cors.ALL_ORIGINS,
33+
allowMethods: apigateway.Cors.ALL_METHODS,
34+
},
35+
policy: new iam.PolicyDocument({
36+
statements: [
37+
// Allow only callers with credentials from the AWS account
38+
// for this stage
39+
new iam.PolicyStatement({
40+
effect: iam.Effect.ALLOW,
41+
principals: [new iam.AccountPrincipal(scope.account)],
42+
actions: ["execute-api:Invoke"],
43+
resources: ["execute-api:/*"],
44+
}),
45+
// Open up OPTIONS to allow browsers to make unauthenticated
46+
// preflight requests
47+
new iam.PolicyStatement({
48+
effect: iam.Effect.ALLOW,
49+
principals: [new iam.AnyPrincipal()],
50+
actions: ["execute-api:Invoke"],
51+
resources: ["execute-api:/*/OPTIONS/*"],
52+
}),
53+
],
54+
}),
55+
};
56+
57+
const api = new apigateway.RestApi(this, `${id}Api`, apiDefaults);
58+
59+
const lambdaFn = new lambda.Function(scope, `${id}-Handler`, {
60+
runtime: lambda.Runtime.NODEJS_12_X,
61+
code: lambda.Code.fromAsset(getLambdaPath(props.lambdaAssetDirectory)),
62+
handler: `index.chimeCallHandler`,
63+
timeout: Duration.seconds(30),
64+
environment: props.environment,
65+
initialPolicy: props.policyStatements,
66+
});
67+
68+
const apiPath = "call-create";
69+
const apiResource = api.root.addResource(apiPath);
70+
71+
const lambdaIntegration = new apigateway.LambdaIntegration(lambdaFn);
72+
73+
apiResource.addMethod("GET", lambdaIntegration, {
74+
authorizationType: AuthorizationType.IAM,
75+
});
76+
77+
this.api = {
78+
api,
79+
queryPath: `/${apiPath}`,
80+
};
81+
}
82+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
"""
2+
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
SPDX-License-Identifier: MIT-0
4+
"""
5+
6+
import logging
7+
import boto3
8+
import json
9+
from uuid import uuid4
10+
11+
logger = logging.getLogger(__name__)
12+
logger.setLevel(logging.INFO)
13+
14+
s3_client = boto3.client('s3')
15+
cloudfront_client = boto3.client('cloudfront')
16+
17+
18+
def on_event(event, context):
19+
logger.info(f'New event {json.dumps(event, indent=2)}')
20+
21+
request_type = event['RequestType']
22+
if request_type == 'Create' or request_type == 'Update':
23+
s3_bucket = event['ResourceProperties']['S3_BUCKET']
24+
s3_key = event['ResourceProperties']['S3_CONFIG_FILE_KEY']
25+
website_config = event['ResourceProperties']['WEBSITE_CONFIG']
26+
distribution_id = event['ResourceProperties']['CLOUDFRONT_DISTRIBUTION_ID']
27+
update_website_config(s3_bucket, s3_key, website_config, distribution_id)
28+
elif request_type == 'Delete':
29+
logger.info("Website config deletion")
30+
pass
31+
else:
32+
raise Exception("Invalid request type: %s" % request_type)
33+
34+
35+
def update_website_config(s3_bucket, s3_key, website_config, distribution_id):
36+
logger.info(f"Updating config file {s3_key}")
37+
s3_client.put_object(Body=website_config, Bucket=s3_bucket, Key=s3_key)
38+
39+
logger.info(f"Invalidating Cloudfront distribution {distribution_id}")
40+
cloudfront_client.create_invalidation(
41+
DistributionId=distribution_id,
42+
InvalidationBatch={
43+
'Paths': {
44+
'Quantity': 1,
45+
'Items': [f'/{s3_key}']
46+
},
47+
'CallerReference': str(uuid4()),
48+
})
49+
50+
logger.info(f"Website config updated succesfully")

Infra/lib/graphql/schema.graphql

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
"""
2+
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
SPDX-License-Identifier: MIT-0
4+
"""
5+
6+
type chimeSession @aws_cognito_user_pools @aws_iam {
7+
meeting: String
8+
attendee: String
9+
username: String
10+
}
11+
12+
type Mutation {
13+
startChimeSession(meeting: String!, attendee: String!, username: String!): chimeSession
14+
@aws_iam
15+
claimChimeSession(meeting: String!): String
16+
@aws_iam
17+
}
18+
19+
type Query {
20+
stub: String
21+
@deprecated(reason: "this is a None datasource and used only for subscriptions so this is a no-op")
22+
@aws_iam
23+
}
24+
25+
type Subscription {
26+
chimeSessionStarted: chimeSession
27+
@aws_subscribe(mutations: ["startChimeSession"])
28+
chimeSessionClaimed: String
29+
@aws_subscribe(mutations: ["claimChimeSession"])
30+
}
31+
32+
schema {
33+
query: Query
34+
mutation: Mutation
35+
subscription: Subscription
36+
}

0 commit comments

Comments
 (0)