@infrascan/aws-lambda-scanner
Version:
Infrascan scanner definition for AWS Lambda
490 lines (486 loc) • 13.9 kB
JavaScript
// src/generated/getters.ts
import {
evaluateSelectorGlobally,
resolveFunctionCallParameters
} from "@infrascan/core";
import { LambdaServiceException } from "@aws-sdk/client-lambda";
import {
ListFunctionsCommand
} from "@aws-sdk/client-lambda";
import {
GetFunctionCommand
} from "@aws-sdk/client-lambda";
import {
ListEventSourceMappingsCommand
} from "@aws-sdk/client-lambda";
import debug from "debug";
async function ListFunctions(client, stateConnector, context) {
const getterDebug = debug("lambda:ListFunctions");
const state = [];
getterDebug("Fetching state");
let pagingToken;
do {
const preparedParams = {};
preparedParams["Marker"] = pagingToken;
try {
const cmd = new ListFunctionsCommand(preparedParams);
const result = await client.send(cmd);
state.push({
_metadata: {
account: context.account,
region: context.region,
timestamp: Date.now()
},
_parameters: preparedParams,
_result: result
});
pagingToken = result["NextMarker"];
if (pagingToken != null) {
getterDebug("Found pagination token in response");
} else {
getterDebug("No pagination token found in response");
}
} catch (err) {
if (err instanceof LambdaServiceException) {
if (err?.$retryable) {
console.log("Encountered retryable error", err);
} else {
console.log("Encountered unretryable error", err);
}
} else {
console.log("Encountered unexpected error", err);
}
pagingToken = void 0;
}
} while (pagingToken != null);
getterDebug("Recording state");
await stateConnector.onServiceScanCompleteCallback(
context.account,
context.region,
"Lambda",
"ListFunctions",
state
);
}
async function GetFunction(client, stateConnector, context) {
const getterDebug = debug("lambda:GetFunction");
const state = [];
getterDebug("Fetching state");
const resolvers = [
{
Key: "FunctionName",
Selector: "Lambda|ListFunctions|[]._result.Functions[].FunctionArn"
}
];
const parameterQueue = await resolveFunctionCallParameters(
context.account,
context.region,
resolvers,
stateConnector
);
for (const parameters of parameterQueue) {
const preparedParams = parameters;
try {
const cmd = new GetFunctionCommand(preparedParams);
const result = await client.send(cmd);
state.push({
_metadata: {
account: context.account,
region: context.region,
timestamp: Date.now()
},
_parameters: preparedParams,
_result: result
});
} catch (err) {
if (err instanceof LambdaServiceException) {
if (err?.$retryable) {
console.log("Encountered retryable error", err);
} else {
console.log("Encountered unretryable error", err);
}
} else {
console.log("Encountered unexpected error", err);
}
}
}
getterDebug("Recording state");
await stateConnector.onServiceScanCompleteCallback(
context.account,
context.region,
"Lambda",
"GetFunction",
state
);
}
async function ListEventSourceMappings(client, stateConnector, context) {
const getterDebug = debug("lambda:ListEventSourceMappings");
const state = [];
getterDebug("Fetching state");
const resolvers = [
{
Key: "FunctionName",
Selector: "Lambda|ListFunctions|[]._result.Functions[].FunctionArn"
}
];
const parameterQueue = await resolveFunctionCallParameters(
context.account,
context.region,
resolvers,
stateConnector
);
for (const parameters of parameterQueue) {
let pagingToken;
do {
const preparedParams = parameters;
preparedParams["Marker"] = pagingToken;
try {
const cmd = new ListEventSourceMappingsCommand(preparedParams);
const result = await client.send(
cmd
);
state.push({
_metadata: {
account: context.account,
region: context.region,
timestamp: Date.now()
},
_parameters: preparedParams,
_result: result
});
pagingToken = result["NextMarker"];
if (pagingToken != null) {
getterDebug("Found pagination token in response");
} else {
getterDebug("No pagination token found in response");
}
} catch (err) {
if (err instanceof LambdaServiceException) {
if (err?.$retryable) {
console.log("Encountered retryable error", err);
} else {
console.log("Encountered unretryable error", err);
}
} else {
console.log("Encountered unexpected error", err);
}
pagingToken = void 0;
}
} while (pagingToken != null);
}
getterDebug("Recording state");
await stateConnector.onServiceScanCompleteCallback(
context.account,
context.region,
"Lambda",
"ListEventSourceMappings",
state
);
}
async function getIamRoles(stateConnector) {
const iamDebug = debug("lambda:iam");
iamDebug("Pulling IAM roles from state");
const state = [];
const GetFunctionRoleState = await evaluateSelectorGlobally(
"Lambda|GetFunction|[]._result.Configuration | [].{roleArn:Role,executor:FunctionArn}",
stateConnector
);
state.push(...GetFunctionRoleState);
return state;
}
// src/generated/client.ts
import { LambdaClient as LambdaClient2 } from "@aws-sdk/client-lambda";
import debug2 from "debug";
var clientDebug = debug2("lambda:client");
function getClient(credentials, context, retryStrategy) {
clientDebug("Creating instance with context", context);
return new LambdaClient2({
credentials,
region: context.region,
retryStrategy
});
}
// src/graph.ts
import { evaluateSelector, toLowerCase, Size, Time } from "@infrascan/core";
var LambdaFunctionEntity = {
version: "0.1.1",
debugLabel: "lambda",
provider: "aws",
command: "ListFunctions",
category: "lambda",
subcategory: "function",
nodeType: "lambda-function",
selector: "Lambda|GetFunction|[]",
getState(state, context) {
return evaluateSelector(
context.account,
context.region,
LambdaFunctionEntity.selector,
state
);
},
translate(val) {
return [
Object.assign(val._result, {
$metadata: val._metadata,
$parameters: val._parameters
})
];
},
components: {
$metadata(val) {
return {
version: LambdaFunctionEntity.version,
timestamp: val.$metadata.timestamp
};
},
$graph(val) {
return {
id: val.Configuration.FunctionArn,
label: val.Configuration.FunctionName,
nodeClass: "visual",
nodeType: LambdaFunctionEntity.nodeType,
parent: `${val.$metadata.account}-${val.$metadata.region}`
};
},
$source(val) {
return {
command: LambdaFunctionEntity.command,
parameters: val.$parameters
};
},
tenant(val) {
return {
tenantId: val.$metadata.account,
provider: LambdaFunctionEntity.provider,
partition: val.$metadata.partition
};
},
location(val) {
return {
code: val.$metadata.region
};
},
resource(val) {
return {
id: val.Configuration.FunctionArn,
name: val.Configuration.FunctionName,
category: LambdaFunctionEntity.category,
subcategory: LambdaFunctionEntity.subcategory,
description: val.Configuration?.Description
};
},
tags(val) {
if (val.Tags == null) {
return [];
}
return Object.entries(val.Tags).map(([key, value]) => ({
key,
value
}));
},
iam(val) {
return {
roles: val.Configuration?.Role != null ? [
{
label: "default",
arn: val.Configuration.Role
}
] : []
};
},
encryption(val) {
return {
keyId: val.Configuration?.KMSKeyArn
};
},
deadLetter(val) {
return {
targetId: val.Configuration?.DeadLetterConfig?.TargetArn
};
},
lambda(val) {
return {
concurrency: {
reservedConcurrentExecutions: val.Concurrency?.ReservedConcurrentExecutions
},
type: val.Configuration?.PackageType != null ? toLowerCase(val.Configuration?.PackageType) : void 0,
supportedArchitectures: val.Configuration?.Architectures,
code: {
size: val.Configuration?.CodeSize != null ? {
value: val.Configuration?.CodeSize,
unit: Size.Bytes
} : void 0,
sha256: val.Configuration?.CodeSha256,
imageUri: val.Code?.ImageUri,
location: val.Code?.Location,
repositoryType: val.Code?.RepositoryType,
resolvedImageUri: val.Code?.ResolvedImageUri
},
function: {
handler: val.Configuration?.Handler,
runtime: val.Configuration?.Runtime,
memorySize: val.Configuration?.MemorySize != null ? {
value: val.Configuration?.MemorySize,
unit: Size.Megabytes
} : void 0,
timeout: val.Configuration?.Timeout != null ? {
value: val.Configuration?.Timeout,
unit: Time.Seconds
} : void 0,
layers: val.Configuration?.Layers?.map((layer) => ({
arn: layer.Arn,
size: layer.CodeSize != null ? {
value: layer.CodeSize,
unit: Size.Bytes
} : void 0
})),
environment: val.Configuration?.Environment?.Variables ? Object.entries(val.Configuration.Environment.Variables).map(
([key, value]) => ({
key,
value
})
) : []
}
};
},
network(val) {
return {
vpc: {
id: val.Configuration?.VpcConfig?.VpcId
},
securityGroups: val.Configuration?.VpcConfig?.SecurityGroupIds,
targetSubnets: val.Configuration?.VpcConfig?.SubnetIds
};
}
}
};
var LambdaEventSourceEntity = {
version: "0.1.0",
debugLabel: "lambda-event-source",
provider: "aws",
command: "ListFunctions",
category: "lambda",
subcategory: "event-source",
nodeType: "lambda-event-source",
selector: "Lambda|ListEventSourceMappings|[]",
getState(state, context) {
return evaluateSelector(
context.account,
context.region,
LambdaEventSourceEntity.selector,
state
);
},
translate(val) {
return val._result.EventSourceMappings?.map((config) => ({
...config,
$metadata: val._metadata,
$parameters: val._parameters
})) ?? [];
},
components: {
$metadata(val) {
return {
version: LambdaEventSourceEntity.version,
timestamp: val.$metadata.timestamp
};
},
$graph(val) {
return {
id: val.EventSourceArn,
label: val.UUID,
nodeClass: "informational",
nodeType: LambdaEventSourceEntity.nodeType,
parent: `${val.$metadata.account}-${val.$metadata.region}`
};
},
$source(val) {
return {
command: LambdaEventSourceEntity.command,
parameters: val.$parameters
};
},
tenant(val) {
return {
tenantId: val.$metadata.account,
provider: LambdaEventSourceEntity.provider,
partition: val.$metadata.partition
};
},
location(val) {
return {
code: val.$metadata.region
};
},
resource(val) {
return {
id: val.EventSourceArn,
name: val.UUID,
category: LambdaEventSourceEntity.category,
subcategory: LambdaEventSourceEntity.subcategory
};
},
eventSource(val) {
return {
functionArn: val.FunctionArn,
sources: {
managedKafka: val.AmazonManagedKafkaEventSourceConfig,
selfManagedKafka: val.SelfManagedKafkaEventSourceConfig,
documentDb: val.DocumentDBEventSourceConfig,
selfManagedSource: val.SelfManagedEventSource,
queues: val.Queues,
topics: val.Topics
},
processingConfig: {
parallelizationFactor: val.ParallelizationFactor,
destinationConfig: val.DestinationConfig,
scaling: val.ScalingConfig
},
status: {
state: val.State,
stateTransitionReason: val.StateTransitionReason,
lastResult: val.LastProcessingResult
},
errorHandling: {
maxRetryAttempts: val.MaximumRetryAttempts,
bisectBatchOnFailure: val.BisectBatchOnFunctionError
},
reader: {
filter: val.FilterCriteria,
batchSize: val.BatchSize,
maximumBatchWindow: val.MaximumBatchingWindowInSeconds ? {
unit: "s",
value: val.MaximumBatchingWindowInSeconds
} : void 0,
tumblingWindow: val.TumblingWindowInSeconds ? {
unit: "s",
value: val.TumblingWindowInSeconds
} : void 0,
maximumRecordAge: val.MaximumRecordAgeInSeconds ? {
unit: "s",
value: val.MaximumRecordAgeInSeconds
} : void 0,
startingPosition: val.StartingPosition,
startingPositionTimestamp: val.StartingPositionTimestamp?.toISOString()
},
sourceAccessConfigurations: val.SourceAccessConfigurations
};
}
}
};
// src/index.ts
var LambdaScanner = {
provider: "aws",
service: "lambda",
key: "Lambda",
getClient,
callPerRegion: true,
getters: [ListFunctions, GetFunction, ListEventSourceMappings],
getIamRoles,
entities: [LambdaFunctionEntity, LambdaEventSourceEntity]
};
var index_default = LambdaScanner;
export {
index_default as default
};