in templates/CDKTemplate.js [52:277]
constructor(scope, id, props) {
super(scope, id, props);
// Lambda function IAM/VPC
let echoLambda = null;
// Lambda: IAM Role
const lambda_role = new iam.Role(this, NAME + 'LambdaExecutionRole', {
assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com')
});
lambda_role.addManagedPolicy( iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaBasicExecutionRole'));
let env = {
NEPTUNE_HOST: NEPTUNE_HOST,
NEPTUNE_PORT: NEPTUNE_PORT,
NEPTUNE_IAM_AUTH_ENABLED: NEPTUNE_IAM_AUTH.toString(),
LOGGING_ENABLED: 'false',
NEPTUNE_DB_NAME: NEPTUNE_DB_NAME,
NEPTUNE_REGION: REGION,
NEPTUNE_DOMAIN: this.parseNeptuneDomainFromHost(NEPTUNE_HOST),
NEPTUNE_TYPE: NEPTUNE_TYPE,
};
if (NEPTUNE_IAM_AUTH) {
// is IAM auth
echoLambda = new lambda.Function(this, LAMBDA_FUNCTION_NAME, {
functionName: LAMBDA_FUNCTION_NAME,
description: 'Neptune GraphQL Resolver for AppSync',
code: lambda.Code.fromAsset(LAMBDA_ZIP_FILE),
handler: 'index.handler',
runtime: lambda.Runtime.NODEJS_18_X,
timeout: Duration.seconds(15),
memorySize: 128,
environment: env,
initialPolicy: [new iam.PolicyStatement({
sid: NAME + "NeptuneQueryPolicy",
effect: iam.Effect.ALLOW,
actions: [
NEPTUNE_TYPE + ':connect',
NEPTUNE_TYPE + ':DeleteDataViaQuery',
NEPTUNE_TYPE + ':ReadDataViaQuery',
NEPTUNE_TYPE + ':WriteDataViaQuery'
],
resources: [NEPTUNE_IAM_POLICY_RESOURCE]
})],
roleArn: lambda_role.roleArn
});
} else {
// is VPC auth
const neptune_vpc = ec2.Vpc.fromLookup(this, 'Neptune_VPC', {
vpcId: NEPTUNE_DBSubnetGroup
});
lambda_role.addManagedPolicy( iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSLambdaVPCAccessExecutionRole'));
let subnets = NEPTUNE_DBSubnetIds.split(',').map((subnetId) => ec2.Subnet.fromSubnetId(this, 'neptuneSubnet-' + subnetId, subnetId));
echoLambda = new lambda.Function(this, LAMBDA_FUNCTION_NAME, {
functionName: LAMBDA_FUNCTION_NAME,
description: 'Neptune GraphQL Resolver for AppSync',
code: lambda.Code.fromAsset(LAMBDA_ZIP_FILE),
handler: 'index.handler',
runtime: lambda.Runtime.NODEJS_18_X,
timeout: Duration.seconds(15),
memorySize: 128,
environment: env,
vpc: neptune_vpc,
vpcSubnets: {
subnets: subnets
},
securityGroups: [
ec2.SecurityGroup.fromSecurityGroupId(this, 'neptuneSecurityGroup', NEPTUNE_VpcSecurityGroupId)
],
allowPublicSubnet: 'true',
roleArn: lambda_role.roleArn
});
}
echoLambda.node.addDependency(lambda_role);
LAMBDA_ARN = echoLambda.functionArn;
// Appsync: GraphQL API
const itemsGraphQLApi = new CfnGraphQLApi(this, NAME + 'API', {
name: NAME + 'API',
authenticationType: 'API_KEY'
});
// AppSync: Key
new CfnApiKey(this, NAME + '-' + 'APIKEY', {
apiId: itemsGraphQLApi.attrApiId
});
// AppSync: Schema
const apiSchema = new CfnGraphQLSchema(this, NAME + 'Schema', {
apiId: itemsGraphQLApi.attrApiId,
definition: APPSYNC_SCHEMA
});
// AppSync: IAM Lambda invocation role
const lambdaInvokationRole = new iam.Role(this, NAME + 'LambdaInvocationRole', {
assumedBy: new iam.ServicePrincipal('appsync.amazonaws.com')
});
lambdaInvokationRole.addToPolicy(
new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: ["lambda:invokeFunction"],
resources: [
LAMBDA_ARN,
LAMBDA_ARN + ":*"
]
})
);
// AppSync: DataSource
const dataSource = new CfnDataSource(this, NAME + 'DataSource', {
apiId: itemsGraphQLApi.attrApiId,
name: NAME + 'DataSource',
type: 'AWS_LAMBDA',
lambdaConfig: {
lambdaFunctionArn: LAMBDA_ARN,
},
serviceRoleArn: lambdaInvokationRole.roleArn
});
dataSource.node.addDependency(itemsGraphQLApi);
dataSource.node.addDependency(lambdaInvokationRole);
dataSource.node.addDependency(echoLambda);
// AppSync: Function
const functionappSync = new CfnFunctionConfiguration(this, NAME + 'Function', {
apiId: itemsGraphQLApi.attrApiId,
dataSourceName: NAME + 'DataSource',
name: NAME + 'Function',
runtime: {
name: "APPSYNC_JS",
runtimeVersion: "1.0.0",
},
code:
`import { util } from '@aws-appsync/utils';
export function request(ctx) {
const {source, args} = ctx
return {
operation: 'Invoke',
payload: {
field: ctx.info.fieldName,
arguments: args,
selectionSetGraphQL: ctx.info.selectionSetGraphQL,
source
},
};
}
export function response(ctx) {
return ctx.result;
}`
});
functionappSync.node.addDependency(dataSource);
// AppSync: attach resolvers to queries
APPSYNC_ATTACH_QUERY.forEach(n => {
const resolver = new CfnResolver(this, n + "Resolver", {
apiId: itemsGraphQLApi.attrApiId,
typeName: 'Query',
fieldName: n,
kind: "PIPELINE",
pipelineConfig: {
functions: [
functionappSync.attrFunctionId
]},
runtime: {
name: "APPSYNC_JS",
runtimeVersion: "1.0.0",
},
code:
`import {util} from '@aws-appsync/utils';
export function request(ctx) {
return {};
}
export function response(ctx) {
return ctx.prev.result;
}`
});
resolver.node.addDependency(functionappSync);
resolver.node.addDependency(apiSchema);
});
// AppSync: attach resolvers to mutations
APPSYNC_ATTACH_MUTATION.forEach(n => {
const resolver = new CfnResolver(this, n + "Resolver", {
apiId: itemsGraphQLApi.attrApiId,
typeName: 'Mutation',
fieldName: n,
kind: "PIPELINE",
pipelineConfig: {
functions: [
functionappSync.attrFunctionId
]},
runtime: {
name: "APPSYNC_JS",
runtimeVersion: "1.0.0",
},
code:
`import {util} from '@aws-appsync/utils';
export function request(ctx) {
return {};
}
export function response(ctx) {
return ctx.prev.result;
}`
});
resolver.node.addDependency(functionappSync);
resolver.node.addDependency(apiSchema);
});
}