Skip to content

Instantly share code, notes, and snippets.

@agonbina
Last active September 24, 2020 16:52
Show Gist options
  • Save agonbina/b22f0a07442addf097ee7e18e612ff9f to your computer and use it in GitHub Desktop.
Save agonbina/b22f0a07442addf097ee7e18e612ff9f to your computer and use it in GitHub Desktop.
import {
EventBridgeLambda,
EventsQueue,
FilterPolicyType,
getResourceNameWithPrefix,
LambdaFunction,
QueueLambda,
relativeRootPath,
SNSLambda
} from '@getcaya/infra'
import * as aws from '@pulumi/aws'
import * as pulumi from '@pulumi/pulumi'
import { envConfig, getEnvOrDefault } from './utils'
/**
* Globals
*/
const namePrefix = `${pulumi.getProject()}-${pulumi.getStack()}`
const config = new pulumi.Config(pulumi.getProject())
const chargebeeEventBridgeArn = pulumi.output(
// TODO: pass as config ?
new pulumi.StackReference(`AMN-DATA/platform-billing/${pulumi.getStack()}`).outputs['eventBridgeARN']
)
const graphEventsSnsTopicName = getResourceNameWithPrefix('graph-events')
const graphEventsSnsTopic = aws.sns.Topic.get(graphEventsSnsTopicName, config.require('snsTopicEventsArn'))
/**
* node_modules lambda layer. We are going to re-use the same layer for every lambda.
*/
const zipFile = relativeRootPath(config.require('nodeModulesPath'))
const nodeModuleLambdaLayerName = getResourceNameWithPrefix('lambda-layer-nodemodules')
const nodeModuleLambdaLayer = new aws.lambda.LayerVersion(nodeModuleLambdaLayerName, {
compatibleRuntimes: [aws.lambda.NodeJS12dXRuntime],
code: new pulumi.asset.FileArchive(zipFile),
layerName: nodeModuleLambdaLayerName
})
/**
* Code archive
*/
const code = new pulumi.asset.AssetArchive({
'.': new pulumi.asset.FileArchive(relativeRootPath(config.require('functionsPath')))
})
/**
* Queues
*/
const subscriptionPlanCreatedQueue = new EventsQueue({
name: getResourceNameWithPrefix('subscription-plan-created-queue'),
topic: graphEventsSnsTopic,
filterPolicy: {
type: FilterPolicyType.SubscriptionPlan,
mutation: ['CREATED']
},
visibilityTimeoutSeconds: 60
})
const customerInfoUpdatedQueue = new EventsQueue({
name: getResourceNameWithPrefix('customer-info-updated-queue'),
topic: graphEventsSnsTopic,
filterPolicy: {
type: FilterPolicyType.Customer,
mutation: ['UPDATED'],
updatedFields: ['firstName', 'lastName', 'companyName', 'email', 'phoneNumber']
},
visibilityTimeoutSeconds: 60
})
const customerScanCenterUpdatedQueue = new EventsQueue({
name: getResourceNameWithPrefix('customer-scancenter-updated-queue'),
topic: graphEventsSnsTopic,
filterPolicy: {
type: FilterPolicyType.Customer,
mutation: ['UPDATED'],
updatedFields: ['scanCenter']
}
})
/**
* Lambdas
*/
const scheduleReturnsQueueLambdaName = `${namePrefix}-schedule-returns`
const scheduleReturnsQueueLambda = new QueueLambda({
name: scheduleReturnsQueueLambdaName,
layers: [nodeModuleLambdaLayer.arn],
code,
handler: 'build/functions/schedule-returns.handler',
queue: subscriptionPlanCreatedQueue.queue,
queueBatchSize: 1,
environment: {
...envConfig()
}
})
const updateCustomerInfoToChargebeeLambdaName = `${namePrefix}-customerInfoToCB`
const updateCustomerInfoToChargebeeLambda = new QueueLambda({
name: updateCustomerInfoToChargebeeLambdaName,
layers: [nodeModuleLambdaLayer.arn],
code,
handler: 'build/functions/customer/update-customer.handler',
queue: customerInfoUpdatedQueue.queue,
queueBatchSize: 1,
environment: {
...envConfig()
}
})
const enableReturnsByScanCenterLambdaName = `${namePrefix}-enableReturns`
const enableReturnsByScanCenterLambda = new QueueLambda({
name: enableReturnsByScanCenterLambdaName,
layers: [nodeModuleLambdaLayer.arn],
code,
handler: 'build/functions/customer/enable-returns-by-scancenter.handler',
queue: customerScanCenterUpdatedQueue.queue,
queueBatchSize: 1,
environment: {
...envConfig()
}
})
const handleReturnsScheduleToggleLambdaName = `${namePrefix}-handleReturnsToggle`
const handleReturnsScheduleToggleLambda = new SNSLambda({
name: handleReturnsScheduleToggleLambdaName,
description: 'Toggle scheduled moving of documents to(or from) the return basket',
layers: [nodeModuleLambdaLayer.arn],
code,
handler: 'build/functions/customer/handle-returns-schedule-toggle.handler',
topic: graphEventsSnsTopic,
snsFilterPolicy: {
type: FilterPolicyType.Customer,
mutation: ['UPDATED'],
updatedFields: ['returnsInterval']
},
timeout: 900,
environment: envConfig()
})
const updateReturnAddressLambdaName = getResourceNameWithPrefix('updateReturnAddress')
const updateReturnAddressLambda = new EventBridgeLambda({
name: updateReturnAddressLambdaName,
handler: 'build/functions/updateReturnAddress.handler',
code,
layers: [nodeModuleLambdaLayer.arn],
environment: {
...envConfig(),
SEGMENT_WRITE_KEY: getEnvOrDefault('SEGMENT_WRITE_KEY', 'o6g7lIhM5Y9ZwA5rzXxPLDqW2qk39RpB')
},
eventBridgeArn: chargebeeEventBridgeArn,
eventPattern: {
source: ['chargebee.events.subscription_changed']
}
})
const customNotificationLambdaName = getResourceNameWithPrefix('customNotification')
const customNotificationLambda = new LambdaFunction({
name: customNotificationLambdaName,
handler: 'build/functions/customer/custom-notification.handler',
runtime: aws.lambda.NodeJS12dXRuntime,
code,
layers: [nodeModuleLambdaLayer.arn],
environment: envConfig()
})
const migrateAccountLambdaName = getResourceNameWithPrefix('migrateAccount')
const migrateAccountLambda = new LambdaFunction({
name: migrateAccountLambdaName,
handler: 'build/functions/customer/migrate.handler',
runtime: aws.lambda.NodeJS12dXRuntime,
code,
layers: [nodeModuleLambdaLayer.arn],
environment: {
...envConfig(),
thundra_agent_lambda_trace_request_skip: 'true',
COGNITO_LEGACY_USER_POOL_ID: getEnvOrDefault('COGNITO_LEGACY_USER_POOL_ID', 'eu-central-1_sF6Y9OOZg'),
COGNITO_LEGACY_CLIENT_ID: getEnvOrDefault('COGNITO_LEGACY_CLIENT_ID', '2rs2mcch1k2hhk312croih12re')
}
})
const setupCustomerLambdaName = getResourceNameWithPrefix('setupCustomer')
const setupCustomerLambda = new LambdaFunction({
name: setupCustomerLambdaName,
handler: 'build/functions/customer/setup-customer.handler',
runtime: aws.lambda.NodeJS12dXRuntime,
code,
layers: [nodeModuleLambdaLayer.arn],
environment: envConfig()
})
/**
* AWS Cognito Resources (Imported from serverless stack)
*/
const isProduction = pulumi.getStack() === 'production'
const userPoolId = isProduction ? 'eu-central-1_3SDdDsA6m' : 'eu-central-1_XZTe0nEwq'
const cognitoUserPoolAccounts = new aws.cognito.UserPool(
getResourceNameWithPrefix('cognitoUserPoolAccounts'),
{
name: `${pulumi.getStack()}-platform-accounts`,
adminCreateUserConfig: {
allowAdminCreateUserOnly: false
},
aliasAttributes: ['preferred_username', 'email'],
autoVerifiedAttributes: ['email'],
emailConfiguration: {
emailSendingAccount: 'DEVELOPER',
sourceArn: 'arn:aws:ses:eu-west-1:420446605159:identity/notifications@getcaya.com',
replyToEmailAddress: 'notifications@getcaya.com'
},
mfaConfiguration: 'OFF',
passwordPolicy: {
minimumLength: 8,
requireLowercase: false,
requireNumbers: false,
requireSymbols: false,
requireUppercase: false,
temporaryPasswordValidityDays: 7
},
// TODO: to change the lamdas once the first time import is done.
lambdaConfig: {
preSignUp: isProduction
? 'arn:aws:lambda:eu-central-1:420446605159:function:platform-production-setupCustomer'
: 'arn:aws:lambda:eu-central-1:420446605159:function:platform-testing-setupCustomer',
customMessage: isProduction
? 'arn:aws:lambda:eu-central-1:420446605159:function:platform-production-customNotification'
: 'arn:aws:lambda:eu-central-1:420446605159:function:platform-testing-customNotification',
...(isProduction
? { userMigration: 'arn:aws:lambda:eu-central-1:420446605159:function:platform-production-migrateAccount' }
: {})
},
...(isProduction
? {
userPoolAddOns: { advancedSecurityMode: 'AUDIT' }
}
: {})
},
{
import: userPoolId
}
)
const setupCustomerLambdaPermission = new aws.lambda.Permission(
getResourceNameWithPrefix('setupCustomerLambdaPermission'),
{
function: setupCustomerLambda.lambda,
action: 'lambda:InvokeFunction',
principal: 'cognito-idp.amazonaws.com',
sourceArn: cognitoUserPoolAccounts.arn
}
)
const customNotificationLambdaPermission = new aws.lambda.Permission(
getResourceNameWithPrefix('customNotificationLambdaPermission'),
{
function: customNotificationLambda.lambda,
action: 'lambda:InvokeFunction',
principal: 'cognito-idp.amazonaws.com',
sourceArn: cognitoUserPoolAccounts.arn
}
)
if (isProduction) {
const migrateAccountLambdaPermission = new aws.lambda.Permission(
getResourceNameWithPrefix('migrateAccountLambdaPermission'),
{
function: migrateAccountLambda.lambda,
action: 'lambda:InvokeFunction',
principal: 'cognito-idp.amazonaws.com',
sourceArn: cognitoUserPoolAccounts.arn
}
)
}
const mobileClientId = isProduction ? '1mb87qq2cblf02899skttkc1i7' : '1lnvudc1rm1s633sbe4ii1lkr0'
const cognitoUserPoolClientMobileApp = new aws.cognito.UserPoolClient(
getResourceNameWithPrefix('UserPoolClientMobileApp'),
{
name: 'Mobile App',
explicitAuthFlows: ['USER_PASSWORD_AUTH'],
readAttributes: ['email'],
writeAttributes: ['email'],
refreshTokenValidity: 30,
userPoolId: cognitoUserPoolAccounts.id
},
{
parent: cognitoUserPoolAccounts,
import: `${userPoolId}/${mobileClientId}`
}
)
const webAppClientId = isProduction ? 'smi9060mf6k8oee4ainard6g5' : '7rbudv7odaunt3b6vsiepfdsnc'
const cognitoUserPoolClientWebApp = new aws.cognito.UserPoolClient(
getResourceNameWithPrefix('UserPoolClientWebApp'),
{
name: 'Web App',
explicitAuthFlows: ['USER_PASSWORD_AUTH'],
readAttributes: ['email'],
writeAttributes: ['email'],
refreshTokenValidity: 30,
userPoolId: cognitoUserPoolAccounts.id
},
{
parent: cognitoUserPoolAccounts,
import: `${userPoolId}/${webAppClientId}`
}
)
const alexaClientAppId = isProduction ? 's8iaiu1r1allrdb7o93tsklb2' : '6r3icoecfo9fn13ns1jr1ufdd1'
const cognitoUserPoolClientAlexaApp = new aws.cognito.UserPoolClient(
getResourceNameWithPrefix('UserPoolAlexaSkillApp'),
{
name: 'Alexa',
explicitAuthFlows: [],
readAttributes: ['email_verified', 'email'],
refreshTokenValidity: 30,
userPoolId: cognitoUserPoolAccounts.id,
supportedIdentityProviders: ['COGNITO'],
callbackUrls: isProduction
? [
'https://alexa.amazon.co.jp/api/skill/link/M3AX6CFJ15WDFG',
'https://layla.amazon.com/api/skill/link/M3AX6CFJ15WDFG',
'https://pitangui.amazon.com/api/skill/link/M3AX6CFJ15WDFG'
]
: [
'https://layla.amazon.com/api/skill/link/MS2F2Z51OLZMY',
'https://pitangui.amazon.com/api/skill/link/MS2F2Z51OLZMY'
],
allowedOauthFlows: ['code', 'implicit'],
allowedOauthFlowsUserPoolClient: true,
allowedOauthScopes: ['openid', 'email']
},
{
parent: cognitoUserPoolAccounts,
import: `${userPoolId}/${alexaClientAppId}`
}
)
/**
* Outputs
*/
export const userPoolAccountsId = cognitoUserPoolAccounts.id
export const userPoolWebAppClientId = cognitoUserPoolClientWebApp.id
export const userPoolMobileAppClientId = cognitoUserPoolClientMobileApp.id
export const userPoolAlexaAppClientId = cognitoUserPoolClientAlexaApp.id
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment