serverless-spy 2.3.16 → 2.3.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"ServerlessSpy.mjs","names":["props?: ServerlessSpyProps","filterWithDefaults: Required<SpyFilter>","nodes: IConstruct[]","functionSubscription: LambdaSubscription | undefined","fs","fs: LambdaSpied"],"sources":["../../src/ServerlessSpy.ts"],"sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\nimport { PythonLayerVersion } from '@aws-cdk/aws-lambda-python-alpha';\nimport {\n aws_iam,\n BundlingFileAccess,\n CfnOutput,\n custom_resources,\n Duration,\n NestedStack,\n Stack,\n} from 'aws-cdk-lib';\nimport * as dynamoDb from 'aws-cdk-lib/aws-dynamodb';\nimport * as events from 'aws-cdk-lib/aws-events';\nimport * as targets from 'aws-cdk-lib/aws-events-targets';\nimport { Effect } from 'aws-cdk-lib/aws-iam';\nimport * as lambda from 'aws-cdk-lib/aws-lambda';\nimport {\n Architecture,\n ILayerVersion,\n SingletonFunction,\n} from 'aws-cdk-lib/aws-lambda';\nimport * as dynamoDbStream from 'aws-cdk-lib/aws-lambda-event-sources';\nimport { SqsEventSource } from 'aws-cdk-lib/aws-lambda-event-sources';\nimport * as lambdaNode from 'aws-cdk-lib/aws-lambda-nodejs';\nimport { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs';\nimport * as s3 from 'aws-cdk-lib/aws-s3';\nimport * as s3notif from 'aws-cdk-lib/aws-s3-notifications';\nimport * as sns from 'aws-cdk-lib/aws-sns';\nimport * as snsSubs from 'aws-cdk-lib/aws-sns-subscriptions';\nimport * as sqs from 'aws-cdk-lib/aws-sqs';\nimport { Construct, IConstruct } from 'constructs';\nimport { envVariableNames } from './common/envVariableNames';\n\nexport interface ServerlessSpyProps {\n readonly generateSpyEventsFileLocation?: string;\n readonly spySqsWithNoSubscriptionAndDropAllMessages?: boolean;\n readonly debugMode?: boolean;\n}\n\nexport interface SpyFilter {\n readonly spyLambda?: boolean;\n readonly spySqs?: boolean;\n readonly spySnsTopic?: boolean;\n readonly spySnsSubsription?: boolean;\n readonly spyEventBridge?: boolean;\n readonly spyEventBridgeRule?: boolean;\n readonly spyS3?: boolean;\n readonly spyDynamoDB?: boolean;\n}\n\nconst isLambdaFunction = (node: IConstruct): node is lambda.Function =>\n 'functionName' in node && 'functionArn' in node && 'runtime' in node;\n\nconst serverlessSpyIotEndpointCrNamePrefix = 'ServerlessSpyIotEndpoint';\n\nexport class ServerlessSpy extends Construct {\n private createdResourcesBySSpy: IConstruct[] = [];\n private lambdaSubscriptionPool: LambdaSubscription[] = [];\n private lambdaSubscriptionMain: LambdaSubscription;\n private lambdasSpied: LambdaSpied[] = [];\n public serviceKeys: string[] = [];\n private spiedNodes: IConstruct[] = [];\n private layerMap: Partial<Record<string, ILayerVersion>> = {};\n private readonly iotEndpoint: string;\n\n constructor(\n scope: Construct,\n id: string,\n private props?: ServerlessSpyProps\n ) {\n super(scope, id);\n\n const rootStack = this.cleanName(\n this.findRootStack(Stack.of(this)).node.id\n );\n\n const getIoTEndpoint = new custom_resources.AwsCustomResource(\n this,\n serverlessSpyIotEndpointCrNamePrefix,\n {\n onCreate: {\n service: 'Iot',\n action: 'describeEndpoint',\n physicalResourceId:\n custom_resources.PhysicalResourceId.fromResponse('endpointAddress'),\n parameters: {\n endpointType: 'iot:Data-ATS',\n },\n },\n onUpdate: {\n service: 'Iot',\n action: 'describeEndpoint',\n physicalResourceId:\n custom_resources.PhysicalResourceId.fromResponse('endpointAddress'),\n parameters: {\n endpointType: 'iot:Data-ATS',\n },\n },\n installLatestAwsSdk: false,\n policy: custom_resources.AwsCustomResourcePolicy.fromSdkCalls({\n resources: custom_resources.AwsCustomResourcePolicy.ANY_RESOURCE,\n }),\n functionName: serverlessSpyIotEndpointCrNamePrefix + rootStack,\n }\n );\n this.iotEndpoint = getIoTEndpoint.getResponseField('endpointAddress');\n\n this.createdResourcesBySSpy.push(getIoTEndpoint);\n\n new CfnOutput(this, 'ServerlessSpyIoTEndpoint', {\n key: 'ServerlessSpyWsUrl',\n value: `${this.iotEndpoint}/${rootStack}`,\n });\n\n this.lambdaSubscriptionMain = this.provideFunctionForSubscription();\n }\n\n private getDefaultLambdaEnvironmentVariables(): { [key: string]: string } {\n return {\n NODE_OPTIONS: '--enable-source-maps',\n };\n }\n\n /**\n * Initalize spying on resources given as parameter.\n * @param nodes Which reources and their children to spy on.\n */\n public spyNodes(nodes: IConstruct[]) {\n for (const node of nodes) {\n let ns = this.getAllNodes(node);\n this.internalSpyNodes(ns);\n }\n\n this.finalizeSpy();\n }\n\n /**\n * Initalize spying on resources.\n * @param filter Limit which resources to spy on.\n */\n public spy(filter?: SpyFilter) {\n let nodes = this.getAllNodes(Stack.of(this));\n\n const filterWithDefaults: Required<SpyFilter> = {\n spyLambda: true,\n spySqs: true,\n spySnsTopic: true,\n spySnsSubsription: true,\n spyEventBridge: true,\n spyEventBridgeRule: true,\n spyS3: true,\n spyDynamoDB: true,\n ...filter,\n };\n\n const CRID =\n 'AWS' +\n custom_resources.AwsCustomResource.PROVIDER_FUNCTION_UUID.replace(\n /-/gi,\n ''\n ).substring(0, 16);\n\n nodes = nodes.filter((node) => {\n if (\n // Ignore the custom resource and the Provider (as well as any other Providers using the same provider function), otherwise we cause\n // circular dependencies\n node.node.id.startsWith(CRID) ||\n node.node.id === 'Provider' ||\n // Ignore singleton functions as they can cause very odd behavior and crashes\n node instanceof SingletonFunction\n ) {\n if (this.props?.debugMode) {\n console.info(`Skipping ${node.node.id}`);\n }\n return false;\n } else if (\n filterWithDefaults.spyLambda &&\n (node instanceof lambda.Function ||\n node instanceof NodejsFunction ||\n isLambdaFunction(node))\n ) {\n return true;\n } else if (filterWithDefaults.spySnsTopic && node instanceof sns.Topic) {\n return true;\n } else if (\n filterWithDefaults.spySnsSubsription &&\n node instanceof sns.Subscription\n ) {\n return true;\n } else if (filterWithDefaults.spyS3 && node instanceof s3.Bucket) {\n return true;\n } else if (\n filterWithDefaults.spyDynamoDB &&\n node instanceof dynamoDb.Table\n ) {\n return true;\n } else if (\n filterWithDefaults.spyDynamoDB &&\n node instanceof dynamoDb.TableV2\n ) {\n return true;\n } else if (\n filterWithDefaults.spyEventBridge &&\n node instanceof events.EventBus\n ) {\n return true;\n } else if (\n filterWithDefaults.spyEventBridgeRule &&\n node instanceof events.Rule\n ) {\n return true;\n } else if (\n filterWithDefaults.spySqs &&\n node instanceof lambda.CfnEventSourceMapping\n ) {\n return true;\n } else if (\n filterWithDefaults.spySqs &&\n this.props?.spySqsWithNoSubscriptionAndDropAllMessages &&\n node instanceof sqs.Queue\n ) {\n return true;\n }\n\n return false;\n });\n\n this.internalSpyNodes(nodes);\n this.finalizeSpy();\n }\n\n private internalSpyNodes(nodes: IConstruct[]) {\n for (const node of nodes) {\n this.internalSpyNode(node);\n }\n }\n\n private finalizeSpy() {\n //set mapping property for all functions we created\n for (const func of this.lambdaSubscriptionPool) {\n func.function.addEnvironment(\n envVariableNames.SSPY_INFRA_MAPPING,\n JSON.stringify(func.mapping)\n );\n }\n\n //set mapping property for all functions we spy on\n for (const func of this.lambdasSpied) {\n func.function.addEnvironment(\n envVariableNames.SSPY_INFRA_MAPPING,\n JSON.stringify(func.mapping)\n );\n }\n\n if (this.props?.generateSpyEventsFileLocation) {\n this.writeSpyEventsClass(this.props?.generateSpyEventsFileLocation);\n }\n }\n\n private getExtensionAssetLocation() {\n let extensionAssetLocation = path.join(\n __dirname,\n '../extension/dist/layer'\n );\n\n const extensionAssetLocationAlt = path.join(\n __dirname,\n '../lib/extension/dist/layer'\n );\n\n if (!fs.existsSync(extensionAssetLocation)) {\n if (!fs.existsSync(extensionAssetLocationAlt)) {\n throw new Error(\n `Folder with assets for extension does not exists at ${extensionAssetLocation} or at ${extensionAssetLocationAlt} `\n );\n } else {\n extensionAssetLocation = extensionAssetLocationAlt;\n }\n }\n\n const extensionAssetLocationWrapper = path.join(\n extensionAssetLocation,\n 'spy-wrapper'\n );\n if (!fs.existsSync(extensionAssetLocationWrapper)) {\n throw new Error(\n `Wrapper script for extension does not exists ${extensionAssetLocation}`\n );\n }\n\n const extensionAssetLocationCode = path.join(\n extensionAssetLocation,\n `nodejs/node_modules/interceptor.js`\n );\n if (!fs.existsSync(extensionAssetLocationCode)) {\n throw new Error(\n `Code for extension does not exists ${extensionAssetLocationCode}`\n );\n }\n return extensionAssetLocation;\n }\n\n private getLanguageExtensionAssetLocation(language: string) {\n const rootDir = path.join(__dirname, '..');\n\n let extensionAssetLocation = path.join(rootDir, `extensions/${language}`);\n\n const extensionAssetLocationAlt = path.join(\n rootDir,\n `lib/extensions/${language}`\n );\n\n if (!fs.existsSync(extensionAssetLocation)) {\n if (!fs.existsSync(extensionAssetLocationAlt)) {\n throw new Error(\n `Folder with assets for extension for ${language} does not exists at ${extensionAssetLocation} or at ${extensionAssetLocationAlt} `\n );\n } else {\n extensionAssetLocation = extensionAssetLocationAlt;\n }\n }\n\n const extensionAssetLocationWrapper = path.join(\n // extensionAssetLocation.substring(\n // 0,\n // extensionAssetLocation.lastIndexOf(path.sep)\n // ),\n extensionAssetLocation,\n 'spy-wrapper'\n );\n if (!fs.existsSync(extensionAssetLocationWrapper)) {\n throw new Error(\n `Wrapper script for extension does not exists at ${extensionAssetLocationWrapper}`\n );\n }\n\n return extensionAssetLocation;\n }\n\n /**\n * Write SpyEvents class, which helps with writing the code for tests.\n * @param fileLocation\n */\n private writeSpyEventsClass(fileLocation: string) {\n fs.mkdirSync(path.dirname(fileLocation), { recursive: true });\n\n const properties = this.serviceKeys\n .map((sk) => ` ${sk.replace(/#/g, '')}: '${sk}' = '${sk}';\\n`)\n .join('');\n\n const code = `/* eslint-disable */\\nexport class ServerlessSpyEvents {\\n${properties}}\\n`;\n\n fs.writeFileSync(fileLocation, code);\n }\n\n private getAllNodes(parent: IConstruct) {\n const nodes: IConstruct[] = [];\n nodes.push(parent);\n this.getAllNodesRecursive(parent, nodes);\n return nodes;\n }\n\n private getAllNodesRecursive(parent: IConstruct, nodes: IConstruct[]) {\n for (const node of parent.node.children) {\n nodes.push(node);\n this.getAllNodesRecursive(node, nodes);\n }\n }\n\n private internalSpyNode(node: IConstruct) {\n if (this.spiedNodes.includes(node)) {\n return;\n }\n\n this.spiedNodes.push(node);\n\n if (this.createdResourcesBySSpy.includes(node)) {\n return;\n }\n\n if (this.lambdaSubscriptionPool.find((s) => s.function === node)) {\n return;\n }\n\n if (this.props?.debugMode) {\n console.info('Spy on node', this.getConstructName(node));\n }\n\n if (\n node instanceof lambda.Function ||\n node instanceof NodejsFunction ||\n isLambdaFunction(node)\n ) {\n this.internalSpyLambda(node);\n } else if (node instanceof sns.Topic) {\n this.internalSpySnsTopic(node);\n } else if (node instanceof sns.Subscription) {\n this.internalSpySnsSubscription(node);\n } else if (node instanceof s3.Bucket) {\n this.internalSpyS3(node);\n } else if (node instanceof dynamoDb.Table) {\n this.internalSpyDynamodb(node);\n } else if (node instanceof dynamoDb.TableV2) {\n this.internalSpyDynamodb(node);\n } else if (node instanceof events.EventBus) {\n this.internalSpyEventBus(node);\n } else if (node instanceof events.Rule) {\n this.internalSpyEventBusRule(node);\n } else if (node instanceof lambda.CfnEventSourceMapping) {\n this.internalSpySqs(node);\n } else if (node instanceof sqs.Queue) {\n if (this.props?.spySqsWithNoSubscriptionAndDropAllMessages) {\n this.internalSpySpySqsWithNoSubscription(node);\n }\n }\n }\n\n private getExtensionForRuntime(\n runtime: lambda.Runtime,\n architecture: lambda.Architecture\n ): { layer: lambda.ILayerVersion; spyWrapperPath: string } | undefined {\n const layerKey =\n `sspy_extension_${runtime.toString()}_${architecture.name.toString()}`.replace(\n /\\./g,\n '_'\n );\n\n let layer = this.layerMap[layerKey];\n let spyWrapperPath = '/opt/spy-wrapper';\n\n switch (runtime.name) {\n case lambda.Runtime.PYTHON_3_8.name:\n case lambda.Runtime.PYTHON_3_9.name:\n case lambda.Runtime.PYTHON_3_10.name:\n case lambda.Runtime.PYTHON_3_11.name:\n case lambda.Runtime.PYTHON_3_12.name:\n spyWrapperPath = '/opt/python/spy-wrapper';\n layer =\n layer ||\n new PythonLayerVersion(this, layerKey, {\n compatibleRuntimes: [runtime],\n compatibleArchitectures: [architecture],\n entry: this.getLanguageExtensionAssetLocation('python'),\n bundling: {\n bundlingFileAccess: BundlingFileAccess.VOLUME_COPY,\n },\n });\n break;\n case lambda.Runtime.NODEJS_12_X.name:\n case lambda.Runtime.NODEJS_14_X.name:\n case lambda.Runtime.NODEJS_16_X.name:\n case lambda.Runtime.NODEJS_18_X.name:\n case lambda.Runtime.NODEJS_20_X.name:\n case lambda.Runtime.NODEJS_22_X.name:\n layer =\n layer ||\n new lambda.LayerVersion(this, layerKey, {\n compatibleRuntimes: [runtime],\n compatibleArchitectures: [architecture],\n code: lambda.Code.fromAsset(this.getExtensionAssetLocation()),\n });\n break;\n default:\n console.log(`No extensions available for ${runtime.toString()}`);\n return undefined;\n }\n\n this.layerMap[layerKey] = layer;\n this.createdResourcesBySSpy.push(layer);\n return { layer, spyWrapperPath };\n }\n\n private internalSpySpySqsWithNoSubscription(queue: sqs.Queue) {\n const subscription = this.findElement<lambda.CfnEventSourceMapping>(\n (n: IConstruct) =>\n n instanceof lambda.CfnEventSourceMapping &&\n (n as lambda.CfnEventSourceMapping).eventSourceArn === queue.queueArn\n );\n\n if (subscription) {\n return; //already have subscription\n }\n\n const queueName = this.getConstructName(queue);\n const func = new NodejsFunction(\n this,\n `${queueName}SqsSubscriptionAndDropAllMessages`,\n {\n memorySize: 512,\n timeout: Duration.seconds(5),\n runtime: lambda.Runtime.NODEJS_22_X,\n handler: 'handler',\n entry: this.getAssetLocation(\n 'functions/sqsSubscriptionAndDropAllMessages.js'\n ),\n environment: this.getDefaultLambdaEnvironmentVariables(),\n }\n );\n func.addEventSource(new SqsEventSource(queue));\n this.setupForIoT(func);\n const { layer, spyWrapperPath } = this.getExtensionForRuntime(\n func.runtime,\n func.architecture\n )!;\n func.addLayers(layer);\n\n func.addEnvironment('AWS_LAMBDA_EXEC_WRAPPER', spyWrapperPath);\n\n if (this.props?.debugMode) {\n func.addEnvironment(envVariableNames.SSPY_DEBUG, 'true');\n }\n\n this.createdResourcesBySSpy.push(func);\n\n const serviceKey = `Sqs#${queueName}`;\n\n this.addMappingToFunction(func, {\n key: queue.queueArn,\n value: serviceKey,\n });\n\n this.serviceKeys.push(serviceKey);\n func.addEnvironment(envVariableNames.SSPY_SUBSCRIBED_TO_SQS, 'true');\n }\n\n private internalSpySqs(node: lambda.CfnEventSourceMapping) {\n const queue = this.findElement<sqs.Queue>(\n (n: IConstruct) =>\n n instanceof sqs.Queue &&\n (n as sqs.Queue).queueArn === node.eventSourceArn\n );\n\n const func = this.findElement<lambda.Function>(\n (n: IConstruct) =>\n n instanceof lambda.Function &&\n (n as lambda.Function).functionName === node.functionName\n );\n\n if (queue && func) {\n const queueName = this.getConstructName(queue);\n\n const serviceKey = `Sqs#${queueName}`;\n\n this.addMappingToFunction(func, {\n key: queue.queueArn,\n value: serviceKey,\n });\n\n this.serviceKeys.push(serviceKey);\n func.addEnvironment(envVariableNames.SSPY_SUBSCRIBED_TO_SQS, 'true');\n }\n }\n\n private createFunctionForSubscription(index: number) {\n const func = new lambdaNode.NodejsFunction(this, `Subscription${index}`, {\n memorySize: 512,\n timeout: Duration.seconds(5),\n runtime: lambda.Runtime.NODEJS_22_X,\n handler: 'handler',\n entry: this.getAssetLocation('functions/sendMessage.js'),\n environment: {\n NODE_OPTIONS: '--enable-source-maps',\n },\n });\n this.setupForIoT(func);\n return func;\n }\n\n private internalSpyS3(s3Bucket: s3.Bucket) {\n s3Bucket.addEventNotification(\n s3.EventType.OBJECT_CREATED_PUT,\n new s3notif.LambdaDestination(this.lambdaSubscriptionMain.function)\n );\n\n const name = this.getConstructName(s3Bucket);\n\n const serviceKey = `S3#${name}`;\n this.lambdaSubscriptionMain.mapping[s3Bucket.bucketArn] = serviceKey;\n this.serviceKeys.push(serviceKey);\n }\n\n private internalSpyDynamodb(table: dynamoDb.Table | dynamoDb.TableV2) {\n // enable DynamoDB streams with a hack\n (table.node.defaultChild as dynamoDb.CfnTable).streamSpecification = {\n streamViewType: dynamoDb.StreamViewType.NEW_AND_OLD_IMAGES,\n };\n (table as any).tableStreamArn = (\n table.node.defaultChild as dynamoDb.CfnTable\n ).attrStreamArn;\n\n this.lambdaSubscriptionMain.function.addEventSource(\n new dynamoDbStream.DynamoEventSource(table, {\n startingPosition: lambda.StartingPosition.LATEST,\n batchSize: 1,\n retryAttempts: 0,\n })\n );\n\n const name = this.getConstructName(table);\n\n const serviceKey = `DynamoDB#${name}`;\n this.lambdaSubscriptionMain.mapping[table.tableArn] = serviceKey;\n this.serviceKeys.push(serviceKey);\n }\n\n private internalSpyEventBusRule(rule: events.Rule) {\n const { eventBusName } = rule.node.defaultChild as events.CfnRule;\n let bridgeName = 'Default';\n if (!!eventBusName) {\n const eventBridge = this.getEventBridge(eventBusName);\n\n if (!eventBridge) {\n throw new Error(`Can not find EventBridge with name \"${eventBusName}\"`);\n }\n bridgeName = this.getConstructName(eventBridge);\n }\n\n const functionSubscription = this.provideFunctionForSubscription(\n (s) => !s.usedForEventBridge\n );\n functionSubscription.usedForEventBridge = true;\n\n rule.addTarget(new targets.LambdaFunction(functionSubscription.function));\n\n const ruleName = this.getConstructName(rule);\n const serviceKey = `EventBridgeRule#${bridgeName}#${ruleName}`;\n functionSubscription.mapping.eventBridge = serviceKey;\n this.serviceKeys.push(serviceKey);\n }\n\n private internalSpyEventBus(eventBus: events.EventBus) {\n const functionSubscription = this.provideFunctionForSubscription(\n (s) => !s.usedForEventBridge\n );\n functionSubscription.usedForEventBridge = true;\n\n const bridgeName = this.getConstructName(eventBus);\n const rule = new events.Rule(this, `RuleAll${bridgeName}`, {\n eventBus,\n eventPattern: { version: ['0'] },\n targets: [new targets.LambdaFunction(functionSubscription.function)],\n });\n\n this.createdResourcesBySSpy.push(rule);\n const serviceKey = `EventBridge#${bridgeName}`;\n functionSubscription.mapping.eventBridge = serviceKey;\n this.serviceKeys.push(serviceKey);\n }\n\n private internalSpySnsTopic(topic: sns.Topic) {\n const functionSubscription = this.provideFunctionForSubscription(\n (s) => !s.subsribedTopics.includes(topic)\n );\n\n const subscription = topic.addSubscription(\n new snsSubs.LambdaSubscription(functionSubscription.function)\n );\n this.createdResourcesBySSpy.push(subscription);\n const topicName = this.getConstructName(topic);\n const serviceKey = `SnsTopic#${topicName}`;\n functionSubscription.mapping[topic.topicArn] = serviceKey;\n this.serviceKeys.push(serviceKey);\n functionSubscription.subsribedTopics.push(topic);\n }\n\n private internalSpySnsSubscription(subscription: sns.Subscription) {\n if (!subscription.node.scope) {\n return;\n }\n\n const topic = this.getTopic(\n (subscription.node.defaultChild as sns.CfnSubscription).topicArn\n );\n\n if (!topic) {\n throw new Error('Can not find Topic');\n }\n\n const functionSubscription = this.provideFunctionForSubscription(\n (s) => !s.subsribedTopics.includes(topic)\n );\n\n const { filterPolicy } = subscription.node\n .defaultChild as sns.CfnSubscription;\n\n const subscriptionClone = topic.addSubscription(\n new snsSubs.LambdaSubscription(functionSubscription.function)\n );\n (subscriptionClone.node.defaultChild as sns.CfnSubscription).filterPolicy =\n filterPolicy;\n\n this.createdResourcesBySSpy.push(subscriptionClone);\n\n const topicName = this.getConstructName(topic);\n const targetName = this.getConstructName(subscription.node.scope);\n\n functionSubscription.subsribedTopics.push(topic);\n const serviceKey = `SnsSubscription#${topicName}#${targetName}`;\n functionSubscription.mapping[topic.topicArn] = serviceKey;\n this.serviceKeys.push(serviceKey);\n }\n\n private provideFunctionForSubscription(\n filterFunction?: (subscription: LambdaSubscription) => boolean\n ) {\n let functionSubscription: LambdaSubscription | undefined;\n\n if (filterFunction) {\n functionSubscription = this.lambdaSubscriptionPool.find(filterFunction);\n } else if (this.lambdaSubscriptionPool.length > 0) {\n functionSubscription = this.lambdaSubscriptionPool[0];\n }\n\n if (!functionSubscription) {\n functionSubscription = {\n subsribedTopics: [],\n usedForEventBridge: false,\n mapping: {},\n function: this.createFunctionForSubscription(\n this.lambdaSubscriptionPool.length\n ),\n };\n this.lambdaSubscriptionPool.push(functionSubscription);\n }\n return functionSubscription;\n }\n\n private setupForIoT(func: lambda.Function) {\n func.addEnvironment(\n envVariableNames.SSPY_ROOT_STACK,\n this.cleanName(this.findRootStack(Stack.of(this)).node.id)\n );\n func.addEnvironment(envVariableNames.SSPY_IOT_ENDPOINT, this.iotEndpoint);\n\n func.addToRolePolicy(\n new aws_iam.PolicyStatement({\n actions: ['iot:*'],\n effect: Effect.ALLOW,\n resources: ['*'],\n })\n );\n }\n\n private internalSpyLambda(func: lambda.Function) {\n const { layer, spyWrapperPath } = this.getExtensionForRuntime(\n func.runtime,\n func.architecture || Architecture.X86_64\n )!;\n if (!layer) {\n return;\n }\n func.addLayers(layer);\n\n const functionName = this.getConstructName(func);\n\n func.addEnvironment(envVariableNames.SSPY_FUNCTION_NAME, functionName);\n func.addEnvironment('AWS_LAMBDA_EXEC_WRAPPER', spyWrapperPath);\n\n if (this.props?.debugMode) {\n func.addEnvironment(envVariableNames.SSPY_DEBUG, 'true');\n }\n\n this.setupForIoT(func);\n\n this.serviceKeys.push(`Function#${functionName}#Request`);\n this.serviceKeys.push(`Function#${functionName}#Error`);\n this.serviceKeys.push(`Function#${functionName}#Console`);\n this.serviceKeys.push(`Function#${functionName}#Response`);\n\n this.addMappingToFunction(func);\n }\n\n public getConstructName(construct: IConstruct) {\n let constructName = construct.node.path;\n const { node } = Stack.of(this);\n\n if (constructName.startsWith(node.id)) {\n constructName = constructName.substring(node.id.length + 1);\n }\n\n return this.cleanName(constructName);\n }\n\n private cleanName(name: string) {\n //snake case to camel case including dash and first letter to upper case\n return name\n .replace(/[-_]+/g, ' ')\n .replace(/[^\\w\\s]/g, '')\n .replace(/\\s(.)/g, ($1) => $1.toUpperCase())\n .replace(/\\s/g, '')\n .replace(/^(.)/, ($1) => $1.toUpperCase());\n }\n\n private getTopic(topicArn: string): sns.Topic | undefined {\n const topic = this.findElement<sns.Topic>(\n (node: IConstruct) =>\n node instanceof sns.Topic && (node as sns.Topic).topicArn === topicArn\n );\n\n return topic;\n }\n\n private getEventBridge(eventBusName: string): events.IEventBus | undefined {\n const eventBridge = this.findElement<events.IEventBus>(\n (node: IConstruct) =>\n (node instanceof events.EventBus ||\n node.constructor.name === 'ImportedEventBus') &&\n (node as events.IEventBus).eventBusName === eventBusName\n );\n\n return eventBridge;\n }\n\n private findRootStack(stack: Stack): Stack {\n if (stack.nested) {\n const parentStack = (stack as NestedStack).nestedStackParent;\n if (parentStack) return this.findRootStack(parentStack);\n return stack;\n } else {\n return stack;\n }\n }\n\n private findElement<T extends IConstruct = IConstruct>(\n filterFunc: (node: IConstruct) => boolean,\n parent?: IConstruct\n ): T | undefined {\n if (!parent) {\n parent = this.findRootStack(Stack.of(this));\n }\n\n for (const node of parent.node.children) {\n if (filterFunc(node)) {\n return node as T;\n }\n const elementFoundInChild = this.findElement<T>(filterFunc, node);\n if (elementFoundInChild) {\n return elementFoundInChild;\n }\n }\n\n return undefined;\n }\n\n private addMappingToFunction(\n func: lambda.Function,\n keyValue?: { key: string; value: string }\n ) {\n for (const fs of this.lambdasSpied) {\n if (fs.function === func) {\n if (keyValue) {\n fs.mapping[keyValue.key] = keyValue.value;\n }\n return;\n }\n }\n\n const fs: LambdaSpied = {\n function: func,\n mapping: {},\n };\n\n if (keyValue) {\n fs.mapping[keyValue.key] = keyValue.value;\n }\n\n this.lambdasSpied.push(fs);\n }\n\n private getAssetLocation(location: string) {\n const loc = path.join(__dirname, '../lib/' + location);\n\n if (fs.existsSync(loc)) {\n return loc;\n }\n\n const loc2 = path.join(__dirname, '../../lib/' + location);\n\n if (fs.existsSync(loc2)) {\n return loc2;\n }\n\n throw new Error(`Location ${loc} and ${loc2} does not exists.`);\n }\n}\n\ntype LambdaSubscription = {\n subsribedTopics: sns.Topic[];\n usedForEventBridge: boolean;\n function: lambdaNode.NodejsFunction;\n mapping: Record<string, string>;\n};\n\ntype LambdaSpied = {\n function: lambda.Function;\n mapping: Record<string, string>;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"ServerlessSpy.mjs","names":["props?: ServerlessSpyProps","filterWithDefaults: Required<SpyFilter>","nodes: IConstruct[]","functionSubscription: LambdaSubscription | undefined","fs","fs: LambdaSpied"],"sources":["../../src/ServerlessSpy.ts"],"sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\nimport { PythonLayerVersion } from '@aws-cdk/aws-lambda-python-alpha';\nimport {\n aws_iam,\n BundlingFileAccess,\n CfnOutput,\n custom_resources,\n Duration,\n NestedStack,\n Stack,\n} from 'aws-cdk-lib';\nimport * as dynamoDb from 'aws-cdk-lib/aws-dynamodb';\nimport * as events from 'aws-cdk-lib/aws-events';\nimport * as targets from 'aws-cdk-lib/aws-events-targets';\nimport { Effect } from 'aws-cdk-lib/aws-iam';\nimport * as lambda from 'aws-cdk-lib/aws-lambda';\nimport {\n Architecture,\n ILayerVersion,\n SingletonFunction,\n} from 'aws-cdk-lib/aws-lambda';\nimport * as dynamoDbStream from 'aws-cdk-lib/aws-lambda-event-sources';\nimport { SqsEventSource } from 'aws-cdk-lib/aws-lambda-event-sources';\nimport * as lambdaNode from 'aws-cdk-lib/aws-lambda-nodejs';\nimport { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs';\nimport * as s3 from 'aws-cdk-lib/aws-s3';\nimport * as s3notif from 'aws-cdk-lib/aws-s3-notifications';\nimport * as sns from 'aws-cdk-lib/aws-sns';\nimport * as snsSubs from 'aws-cdk-lib/aws-sns-subscriptions';\nimport * as sqs from 'aws-cdk-lib/aws-sqs';\nimport { Construct, IConstruct } from 'constructs';\nimport { envVariableNames } from './common/envVariableNames';\n\nexport interface ServerlessSpyProps {\n readonly generateSpyEventsFileLocation?: string;\n readonly spySqsWithNoSubscriptionAndDropAllMessages?: boolean;\n readonly debugMode?: boolean;\n}\n\nexport interface SpyFilter {\n readonly spyLambda?: boolean;\n readonly spySqs?: boolean;\n readonly spySnsTopic?: boolean;\n readonly spySnsSubsription?: boolean;\n readonly spyEventBridge?: boolean;\n readonly spyEventBridgeRule?: boolean;\n readonly spyS3?: boolean;\n readonly spyDynamoDB?: boolean;\n}\n\nconst isLambdaFunction = (node: IConstruct): node is lambda.Function =>\n 'functionName' in node && 'functionArn' in node && 'runtime' in node;\n\nconst serverlessSpyIotEndpointCrNamePrefix = 'ServerlessSpyIotEndpoint';\n\nexport class ServerlessSpy extends Construct {\n private createdResourcesBySSpy: IConstruct[] = [];\n private lambdaSubscriptionPool: LambdaSubscription[] = [];\n private lambdaSubscriptionMain: LambdaSubscription;\n private lambdasSpied: LambdaSpied[] = [];\n public serviceKeys: string[] = [];\n private spiedNodes: IConstruct[] = [];\n private layerMap: Partial<Record<string, ILayerVersion>> = {};\n private readonly iotEndpoint: string;\n\n constructor(\n scope: Construct,\n id: string,\n private props?: ServerlessSpyProps\n ) {\n super(scope, id);\n\n const rootStack = this.cleanName(\n this.findRootStack(Stack.of(this)).node.id\n );\n\n const getIoTEndpoint = new custom_resources.AwsCustomResource(\n this,\n serverlessSpyIotEndpointCrNamePrefix,\n {\n onCreate: {\n service: 'Iot',\n action: 'describeEndpoint',\n physicalResourceId:\n custom_resources.PhysicalResourceId.fromResponse('endpointAddress'),\n parameters: {\n endpointType: 'iot:Data-ATS',\n },\n },\n onUpdate: {\n service: 'Iot',\n action: 'describeEndpoint',\n physicalResourceId:\n custom_resources.PhysicalResourceId.fromResponse('endpointAddress'),\n parameters: {\n endpointType: 'iot:Data-ATS',\n },\n },\n installLatestAwsSdk: false,\n policy: custom_resources.AwsCustomResourcePolicy.fromSdkCalls({\n resources: custom_resources.AwsCustomResourcePolicy.ANY_RESOURCE,\n }),\n functionName: serverlessSpyIotEndpointCrNamePrefix + rootStack,\n }\n );\n this.iotEndpoint = getIoTEndpoint.getResponseField('endpointAddress');\n\n this.createdResourcesBySSpy.push(getIoTEndpoint);\n\n new CfnOutput(this, 'ServerlessSpyIoTEndpoint', {\n key: 'ServerlessSpyWsUrl',\n value: `${this.iotEndpoint}/${rootStack}`,\n });\n\n this.lambdaSubscriptionMain = this.provideFunctionForSubscription();\n }\n\n private getDefaultLambdaEnvironmentVariables(): { [key: string]: string } {\n return {\n NODE_OPTIONS: '--enable-source-maps',\n };\n }\n\n /**\n * Initalize spying on resources given as parameter.\n * @param nodes Which reources and their children to spy on.\n */\n public spyNodes(nodes: IConstruct[]) {\n for (const node of nodes) {\n let ns = this.getAllNodes(node);\n this.internalSpyNodes(ns);\n }\n\n this.finalizeSpy();\n }\n\n /**\n * Initalize spying on resources.\n * @param filter Limit which resources to spy on.\n */\n public spy(filter?: SpyFilter) {\n let nodes = this.getAllNodes(Stack.of(this));\n\n const filterWithDefaults: Required<SpyFilter> = {\n spyLambda: true,\n spySqs: true,\n spySnsTopic: true,\n spySnsSubsription: true,\n spyEventBridge: true,\n spyEventBridgeRule: true,\n spyS3: true,\n spyDynamoDB: true,\n ...filter,\n };\n\n const CRID =\n 'AWS' +\n custom_resources.AwsCustomResource.PROVIDER_FUNCTION_UUID.replace(\n /-/gi,\n ''\n ).substring(0, 16);\n\n nodes = nodes.filter((node) => {\n if (\n // Ignore the custom resource and the Provider (as well as any other Providers using the same provider function), otherwise we cause\n // circular dependencies\n node.node.id.startsWith(CRID) ||\n node.node.id === 'Provider' ||\n // Ignore singleton functions as they can cause very odd behavior and crashes\n node instanceof SingletonFunction\n ) {\n if (this.props?.debugMode) {\n console.info(`Skipping ${node.node.id}`);\n }\n return false;\n } else if (\n filterWithDefaults.spyLambda &&\n (node instanceof lambda.Function ||\n node instanceof NodejsFunction ||\n isLambdaFunction(node))\n ) {\n return true;\n } else if (filterWithDefaults.spySnsTopic && node instanceof sns.Topic) {\n return true;\n } else if (\n filterWithDefaults.spySnsSubsription &&\n node instanceof sns.Subscription\n ) {\n return true;\n } else if (filterWithDefaults.spyS3 && node instanceof s3.Bucket) {\n return true;\n } else if (\n filterWithDefaults.spyDynamoDB &&\n node instanceof dynamoDb.Table\n ) {\n return true;\n } else if (\n filterWithDefaults.spyDynamoDB &&\n node instanceof dynamoDb.TableV2\n ) {\n return true;\n } else if (\n filterWithDefaults.spyEventBridge &&\n node instanceof events.EventBus\n ) {\n return true;\n } else if (\n filterWithDefaults.spyEventBridgeRule &&\n node instanceof events.Rule\n ) {\n return true;\n } else if (\n filterWithDefaults.spySqs &&\n node instanceof lambda.CfnEventSourceMapping\n ) {\n return true;\n } else if (\n filterWithDefaults.spySqs &&\n this.props?.spySqsWithNoSubscriptionAndDropAllMessages &&\n node instanceof sqs.Queue\n ) {\n return true;\n }\n\n return false;\n });\n\n this.internalSpyNodes(nodes);\n this.finalizeSpy();\n }\n\n private internalSpyNodes(nodes: IConstruct[]) {\n for (const node of nodes) {\n this.internalSpyNode(node);\n }\n }\n\n private finalizeSpy() {\n //set mapping property for all functions we created\n for (const func of this.lambdaSubscriptionPool) {\n func.function.addEnvironment(\n envVariableNames.SSPY_INFRA_MAPPING,\n JSON.stringify(func.mapping)\n );\n }\n\n //set mapping property for all functions we spy on\n for (const func of this.lambdasSpied) {\n func.function.addEnvironment(\n envVariableNames.SSPY_INFRA_MAPPING,\n JSON.stringify(func.mapping)\n );\n }\n\n if (this.props?.generateSpyEventsFileLocation) {\n this.writeSpyEventsClass(this.props?.generateSpyEventsFileLocation);\n }\n }\n\n private getExtensionAssetLocation() {\n let extensionAssetLocation = path.join(\n __dirname,\n '../extension/dist/layer'\n );\n\n const extensionAssetLocationAlt = path.join(\n __dirname,\n '../lib/extension/dist/layer'\n );\n\n if (!fs.existsSync(extensionAssetLocation)) {\n if (!fs.existsSync(extensionAssetLocationAlt)) {\n throw new Error(\n `Folder with assets for extension does not exists at ${extensionAssetLocation} or at ${extensionAssetLocationAlt} `\n );\n } else {\n extensionAssetLocation = extensionAssetLocationAlt;\n }\n }\n\n const extensionAssetLocationWrapper = path.join(\n extensionAssetLocation,\n 'spy-wrapper'\n );\n if (!fs.existsSync(extensionAssetLocationWrapper)) {\n throw new Error(\n `Wrapper script for extension does not exists ${extensionAssetLocation}`\n );\n }\n\n const extensionAssetLocationCode = path.join(\n extensionAssetLocation,\n `nodejs/node_modules/interceptor.js`\n );\n if (!fs.existsSync(extensionAssetLocationCode)) {\n throw new Error(\n `Code for extension does not exists ${extensionAssetLocationCode}`\n );\n }\n return extensionAssetLocation;\n }\n\n private getLanguageExtensionAssetLocation(language: string) {\n const rootDir = path.join(__dirname, '..');\n\n let extensionAssetLocation = path.join(rootDir, `extensions/${language}`);\n\n const extensionAssetLocationAlt = path.join(\n rootDir,\n `lib/extensions/${language}`\n );\n\n if (!fs.existsSync(extensionAssetLocation)) {\n if (!fs.existsSync(extensionAssetLocationAlt)) {\n throw new Error(\n `Folder with assets for extension for ${language} does not exists at ${extensionAssetLocation} or at ${extensionAssetLocationAlt} `\n );\n } else {\n extensionAssetLocation = extensionAssetLocationAlt;\n }\n }\n\n const extensionAssetLocationWrapper = path.join(\n // extensionAssetLocation.substring(\n // 0,\n // extensionAssetLocation.lastIndexOf(path.sep)\n // ),\n extensionAssetLocation,\n 'spy-wrapper'\n );\n if (!fs.existsSync(extensionAssetLocationWrapper)) {\n throw new Error(\n `Wrapper script for extension does not exists at ${extensionAssetLocationWrapper}`\n );\n }\n\n return extensionAssetLocation;\n }\n\n /**\n * Write SpyEvents class, which helps with writing the code for tests.\n * @param fileLocation\n */\n private writeSpyEventsClass(fileLocation: string) {\n fs.mkdirSync(path.dirname(fileLocation), { recursive: true });\n\n const properties = this.serviceKeys\n .map((sk) => ` ${sk.replace(/#/g, '')}: '${sk}' = '${sk}';\\n`)\n .join('');\n\n const code = `/* eslint-disable */\\nexport class ServerlessSpyEvents {\\n${properties}}\\n`;\n\n fs.writeFileSync(fileLocation, code);\n }\n\n private getAllNodes(parent: IConstruct) {\n const nodes: IConstruct[] = [];\n nodes.push(parent);\n this.getAllNodesRecursive(parent, nodes);\n return nodes;\n }\n\n private getAllNodesRecursive(parent: IConstruct, nodes: IConstruct[]) {\n for (const node of parent.node.children) {\n nodes.push(node);\n this.getAllNodesRecursive(node, nodes);\n }\n }\n\n private internalSpyNode(node: IConstruct) {\n if (this.spiedNodes.includes(node)) {\n return;\n }\n\n this.spiedNodes.push(node);\n\n if (this.createdResourcesBySSpy.includes(node)) {\n return;\n }\n\n if (this.lambdaSubscriptionPool.find((s) => s.function === node)) {\n return;\n }\n\n if (this.props?.debugMode) {\n console.info('Spy on node', this.getConstructName(node));\n }\n\n if (\n node instanceof lambda.Function ||\n node instanceof NodejsFunction ||\n isLambdaFunction(node)\n ) {\n this.internalSpyLambda(node);\n } else if (node instanceof sns.Topic) {\n this.internalSpySnsTopic(node);\n } else if (node instanceof sns.Subscription) {\n this.internalSpySnsSubscription(node);\n } else if (node instanceof s3.Bucket) {\n this.internalSpyS3(node);\n } else if (node instanceof dynamoDb.Table) {\n this.internalSpyDynamodb(node);\n } else if (node instanceof dynamoDb.TableV2) {\n this.internalSpyDynamodb(node);\n } else if (node instanceof events.EventBus) {\n this.internalSpyEventBus(node);\n } else if (node instanceof events.Rule) {\n this.internalSpyEventBusRule(node);\n } else if (node instanceof lambda.CfnEventSourceMapping) {\n this.internalSpySqs(node);\n } else if (node instanceof sqs.Queue) {\n if (this.props?.spySqsWithNoSubscriptionAndDropAllMessages) {\n this.internalSpySpySqsWithNoSubscription(node);\n }\n }\n }\n\n private getExtensionForRuntime(\n runtime: lambda.Runtime,\n architecture: lambda.Architecture\n ): { layer: lambda.ILayerVersion; spyWrapperPath: string } | undefined {\n const layerKey =\n `sspy_extension_${runtime.toString()}_${architecture.name.toString()}`.replace(\n /\\./g,\n '_'\n );\n\n let layer = this.layerMap[layerKey];\n let spyWrapperPath = '/opt/spy-wrapper';\n\n switch (runtime.name) {\n case lambda.Runtime.PYTHON_3_8.name:\n case lambda.Runtime.PYTHON_3_9.name:\n case lambda.Runtime.PYTHON_3_10.name:\n case lambda.Runtime.PYTHON_3_11.name:\n case lambda.Runtime.PYTHON_3_12.name:\n spyWrapperPath = '/opt/python/spy-wrapper';\n layer =\n layer ||\n new PythonLayerVersion(this, layerKey, {\n compatibleRuntimes: [runtime],\n compatibleArchitectures: [architecture],\n entry: this.getLanguageExtensionAssetLocation('python'),\n bundling: {\n bundlingFileAccess: BundlingFileAccess.VOLUME_COPY,\n },\n });\n break;\n case lambda.Runtime.NODEJS_12_X.name:\n case lambda.Runtime.NODEJS_14_X.name:\n case lambda.Runtime.NODEJS_16_X.name:\n case lambda.Runtime.NODEJS_18_X.name:\n case lambda.Runtime.NODEJS_20_X.name:\n case lambda.Runtime.NODEJS_22_X.name:\n layer =\n layer ||\n new lambda.LayerVersion(this, layerKey, {\n compatibleRuntimes: [runtime],\n compatibleArchitectures: [architecture],\n code: lambda.Code.fromAsset(this.getExtensionAssetLocation()),\n });\n break;\n default:\n console.log(`No extensions available for ${runtime.toString()}`);\n return undefined;\n }\n\n this.layerMap[layerKey] = layer;\n this.createdResourcesBySSpy.push(layer);\n return { layer, spyWrapperPath };\n }\n\n private internalSpySpySqsWithNoSubscription(queue: sqs.Queue) {\n const subscription = this.findElement<lambda.CfnEventSourceMapping>(\n (n: IConstruct) =>\n n instanceof lambda.CfnEventSourceMapping &&\n (n as lambda.CfnEventSourceMapping).eventSourceArn === queue.queueArn\n );\n\n if (subscription) {\n return; //already have subscription\n }\n\n const queueName = this.getConstructName(queue);\n const func = new NodejsFunction(\n this,\n `${queueName}SqsSubscriptionAndDropAllMessages`,\n {\n memorySize: 512,\n timeout: Duration.seconds(5),\n runtime: lambda.Runtime.NODEJS_22_X,\n handler: 'handler',\n entry: this.getAssetLocation(\n 'functions/sqsSubscriptionAndDropAllMessages.js'\n ),\n environment: this.getDefaultLambdaEnvironmentVariables(),\n }\n );\n func.addEventSource(new SqsEventSource(queue));\n this.setupForIoT(func);\n const { layer, spyWrapperPath } = this.getExtensionForRuntime(\n func.runtime,\n func.architecture\n )!;\n func.addLayers(layer);\n\n func.addEnvironment('AWS_LAMBDA_EXEC_WRAPPER', spyWrapperPath);\n\n if (this.props?.debugMode) {\n func.addEnvironment(envVariableNames.SSPY_DEBUG, 'true');\n }\n\n this.createdResourcesBySSpy.push(func);\n\n const serviceKey = `Sqs#${queueName}`;\n\n this.addMappingToFunction(func, {\n key: queue.queueArn,\n value: serviceKey,\n });\n\n this.serviceKeys.push(serviceKey);\n func.addEnvironment(envVariableNames.SSPY_SUBSCRIBED_TO_SQS, 'true');\n }\n\n private internalSpySqs(node: lambda.CfnEventSourceMapping) {\n const queue = this.findElement<sqs.Queue>(\n (n: IConstruct) =>\n n instanceof sqs.Queue &&\n (n as sqs.Queue).queueArn === node.eventSourceArn\n );\n\n const func = this.findElement<lambda.Function>(\n (n: IConstruct) =>\n n instanceof lambda.Function &&\n (n as lambda.Function).functionName === node.functionName\n );\n\n if (queue && func) {\n const queueName = this.getConstructName(queue);\n\n const serviceKey = `Sqs#${queueName}`;\n\n this.addMappingToFunction(func, {\n key: queue.queueArn,\n value: serviceKey,\n });\n\n this.serviceKeys.push(serviceKey);\n func.addEnvironment(envVariableNames.SSPY_SUBSCRIBED_TO_SQS, 'true');\n }\n }\n\n private createFunctionForSubscription(index: number) {\n const func = new lambdaNode.NodejsFunction(this, `Subscription${index}`, {\n memorySize: 512,\n timeout: Duration.seconds(5),\n runtime: lambda.Runtime.NODEJS_22_X,\n handler: 'handler',\n entry: this.getAssetLocation('functions/sendMessage.js'),\n environment: {\n NODE_OPTIONS: '--enable-source-maps',\n },\n });\n this.setupForIoT(func);\n return func;\n }\n\n private internalSpyS3(s3Bucket: s3.Bucket) {\n s3Bucket.addEventNotification(\n s3.EventType.OBJECT_CREATED_PUT,\n new s3notif.LambdaDestination(this.lambdaSubscriptionMain.function)\n );\n\n const name = this.getConstructName(s3Bucket);\n\n const serviceKey = `S3#${name}`;\n this.lambdaSubscriptionMain.mapping[s3Bucket.bucketArn] = serviceKey;\n this.serviceKeys.push(serviceKey);\n }\n\n private internalSpyDynamodb(table: dynamoDb.Table | dynamoDb.TableV2) {\n // enable DynamoDB streams with a hack\n (table.node.defaultChild as dynamoDb.CfnTable).streamSpecification = {\n streamViewType: dynamoDb.StreamViewType.NEW_AND_OLD_IMAGES,\n };\n\n Object.assign(table, {\n tableStreamArn: (table.node.defaultChild as dynamoDb.CfnTable)\n .attrStreamArn,\n });\n\n this.lambdaSubscriptionMain.function.addEventSource(\n new dynamoDbStream.DynamoEventSource(table, {\n startingPosition: lambda.StartingPosition.LATEST,\n batchSize: 1,\n retryAttempts: 0,\n })\n );\n\n const name = this.getConstructName(table);\n\n const serviceKey = `DynamoDB#${name}`;\n this.lambdaSubscriptionMain.mapping[table.tableArn] = serviceKey;\n this.serviceKeys.push(serviceKey);\n }\n\n private internalSpyEventBusRule(rule: events.Rule) {\n const { eventBusName } = rule.node.defaultChild as events.CfnRule;\n let bridgeName = 'Default';\n if (!!eventBusName) {\n const eventBridge = this.getEventBridge(eventBusName);\n\n if (!eventBridge) {\n throw new Error(`Can not find EventBridge with name \"${eventBusName}\"`);\n }\n bridgeName = this.getConstructName(eventBridge);\n }\n\n const functionSubscription = this.provideFunctionForSubscription(\n (s) => !s.usedForEventBridge\n );\n functionSubscription.usedForEventBridge = true;\n\n rule.addTarget(new targets.LambdaFunction(functionSubscription.function));\n\n const ruleName = this.getConstructName(rule);\n const serviceKey = `EventBridgeRule#${bridgeName}#${ruleName}`;\n functionSubscription.mapping.eventBridge = serviceKey;\n this.serviceKeys.push(serviceKey);\n }\n\n private internalSpyEventBus(eventBus: events.EventBus) {\n const functionSubscription = this.provideFunctionForSubscription(\n (s) => !s.usedForEventBridge\n );\n functionSubscription.usedForEventBridge = true;\n\n const bridgeName = this.getConstructName(eventBus);\n const rule = new events.Rule(this, `RuleAll${bridgeName}`, {\n eventBus,\n eventPattern: { version: ['0'] },\n targets: [new targets.LambdaFunction(functionSubscription.function)],\n });\n\n this.createdResourcesBySSpy.push(rule);\n const serviceKey = `EventBridge#${bridgeName}`;\n functionSubscription.mapping.eventBridge = serviceKey;\n this.serviceKeys.push(serviceKey);\n }\n\n private internalSpySnsTopic(topic: sns.Topic) {\n const functionSubscription = this.provideFunctionForSubscription(\n (s) => !s.subsribedTopics.includes(topic)\n );\n\n const subscription = topic.addSubscription(\n new snsSubs.LambdaSubscription(functionSubscription.function)\n );\n this.createdResourcesBySSpy.push(subscription);\n const topicName = this.getConstructName(topic);\n const serviceKey = `SnsTopic#${topicName}`;\n functionSubscription.mapping[topic.topicArn] = serviceKey;\n this.serviceKeys.push(serviceKey);\n functionSubscription.subsribedTopics.push(topic);\n }\n\n private internalSpySnsSubscription(subscription: sns.Subscription) {\n if (!subscription.node.scope) {\n return;\n }\n\n const topic = this.getTopic(\n (subscription.node.defaultChild as sns.CfnSubscription).topicArn\n );\n\n if (!topic) {\n throw new Error('Can not find Topic');\n }\n\n const functionSubscription = this.provideFunctionForSubscription(\n (s) => !s.subsribedTopics.includes(topic)\n );\n\n const { filterPolicy } = subscription.node\n .defaultChild as sns.CfnSubscription;\n\n const subscriptionClone = topic.addSubscription(\n new snsSubs.LambdaSubscription(functionSubscription.function)\n );\n (subscriptionClone.node.defaultChild as sns.CfnSubscription).filterPolicy =\n filterPolicy;\n\n this.createdResourcesBySSpy.push(subscriptionClone);\n\n const topicName = this.getConstructName(topic);\n const targetName = this.getConstructName(subscription.node.scope);\n\n functionSubscription.subsribedTopics.push(topic);\n const serviceKey = `SnsSubscription#${topicName}#${targetName}`;\n functionSubscription.mapping[topic.topicArn] = serviceKey;\n this.serviceKeys.push(serviceKey);\n }\n\n private provideFunctionForSubscription(\n filterFunction?: (subscription: LambdaSubscription) => boolean\n ) {\n let functionSubscription: LambdaSubscription | undefined;\n\n if (filterFunction) {\n functionSubscription = this.lambdaSubscriptionPool.find(filterFunction);\n } else if (this.lambdaSubscriptionPool.length > 0) {\n functionSubscription = this.lambdaSubscriptionPool[0];\n }\n\n if (!functionSubscription) {\n functionSubscription = {\n subsribedTopics: [],\n usedForEventBridge: false,\n mapping: {},\n function: this.createFunctionForSubscription(\n this.lambdaSubscriptionPool.length\n ),\n };\n this.lambdaSubscriptionPool.push(functionSubscription);\n }\n return functionSubscription;\n }\n\n private setupForIoT(func: lambda.Function) {\n func.addEnvironment(\n envVariableNames.SSPY_ROOT_STACK,\n this.cleanName(this.findRootStack(Stack.of(this)).node.id)\n );\n func.addEnvironment(envVariableNames.SSPY_IOT_ENDPOINT, this.iotEndpoint);\n\n func.addToRolePolicy(\n new aws_iam.PolicyStatement({\n actions: ['iot:*'],\n effect: Effect.ALLOW,\n resources: ['*'],\n })\n );\n }\n\n private internalSpyLambda(func: lambda.Function) {\n const { layer, spyWrapperPath } = this.getExtensionForRuntime(\n func.runtime,\n func.architecture || Architecture.X86_64\n )!;\n if (!layer) {\n return;\n }\n func.addLayers(layer);\n\n const functionName = this.getConstructName(func);\n\n func.addEnvironment(envVariableNames.SSPY_FUNCTION_NAME, functionName);\n func.addEnvironment('AWS_LAMBDA_EXEC_WRAPPER', spyWrapperPath);\n\n if (this.props?.debugMode) {\n func.addEnvironment(envVariableNames.SSPY_DEBUG, 'true');\n }\n\n this.setupForIoT(func);\n\n this.serviceKeys.push(`Function#${functionName}#Request`);\n this.serviceKeys.push(`Function#${functionName}#Error`);\n this.serviceKeys.push(`Function#${functionName}#Console`);\n this.serviceKeys.push(`Function#${functionName}#Response`);\n\n this.addMappingToFunction(func);\n }\n\n public getConstructName(construct: IConstruct) {\n let constructName = construct.node.path;\n const { node } = Stack.of(this);\n\n if (constructName.startsWith(node.id)) {\n constructName = constructName.substring(node.id.length + 1);\n }\n\n return this.cleanName(constructName);\n }\n\n private cleanName(name: string) {\n //snake case to camel case including dash and first letter to upper case\n return name\n .replace(/[-_]+/g, ' ')\n .replace(/[^\\w\\s]/g, '')\n .replace(/\\s(.)/g, ($1) => $1.toUpperCase())\n .replace(/\\s/g, '')\n .replace(/^(.)/, ($1) => $1.toUpperCase());\n }\n\n private getTopic(topicArn: string): sns.Topic | undefined {\n const topic = this.findElement<sns.Topic>(\n (node: IConstruct) =>\n node instanceof sns.Topic && (node as sns.Topic).topicArn === topicArn\n );\n\n return topic;\n }\n\n private getEventBridge(eventBusName: string): events.IEventBus | undefined {\n const eventBridge = this.findElement<events.IEventBus>(\n (node: IConstruct) =>\n (node instanceof events.EventBus ||\n node.constructor.name === 'ImportedEventBus') &&\n (node as events.IEventBus).eventBusName === eventBusName\n );\n\n return eventBridge;\n }\n\n private findRootStack(stack: Stack): Stack {\n if (stack.nested) {\n const parentStack = (stack as NestedStack).nestedStackParent;\n if (parentStack) return this.findRootStack(parentStack);\n return stack;\n } else {\n return stack;\n }\n }\n\n private findElement<T extends IConstruct = IConstruct>(\n filterFunc: (node: IConstruct) => boolean,\n parent?: IConstruct\n ): T | undefined {\n if (!parent) {\n parent = this.findRootStack(Stack.of(this));\n }\n\n for (const node of parent.node.children) {\n if (filterFunc(node)) {\n return node as T;\n }\n const elementFoundInChild = this.findElement<T>(filterFunc, node);\n if (elementFoundInChild) {\n return elementFoundInChild;\n }\n }\n\n return undefined;\n }\n\n private addMappingToFunction(\n func: lambda.Function,\n keyValue?: { key: string; value: string }\n ) {\n for (const fs of this.lambdasSpied) {\n if (fs.function === func) {\n if (keyValue) {\n fs.mapping[keyValue.key] = keyValue.value;\n }\n return;\n }\n }\n\n const fs: LambdaSpied = {\n function: func,\n mapping: {},\n };\n\n if (keyValue) {\n fs.mapping[keyValue.key] = keyValue.value;\n }\n\n this.lambdasSpied.push(fs);\n }\n\n private getAssetLocation(location: string) {\n const loc = path.join(__dirname, '../lib/' + location);\n\n if (fs.existsSync(loc)) {\n return loc;\n }\n\n const loc2 = path.join(__dirname, '../../lib/' + location);\n\n if (fs.existsSync(loc2)) {\n return loc2;\n }\n\n throw new Error(`Location ${loc} and ${loc2} does not exists.`);\n }\n}\n\ntype LambdaSubscription = {\n subsribedTopics: sns.Topic[];\n usedForEventBridge: boolean;\n function: lambdaNode.NodejsFunction;\n mapping: Record<string, string>;\n};\n\ntype LambdaSpied = {\n function: lambda.Function;\n mapping: Record<string, string>;\n};\n"],"mappings":"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"}
package/package.json CHANGED
@@ -138,7 +138,7 @@
138
138
  "require": "./lib/index.js"
139
139
  },
140
140
  "license": "MPL-2.0",
141
- "version": "2.3.16",
141
+ "version": "2.3.18",
142
142
  "types": "lib/index.d.ts",
143
143
  "stability": "stable",
144
144
  "jsii": {