Skip to content

Commit

Permalink
feat: upgrade secrets metric publisher Lambda to Node.js 18 (#417)
Browse files Browse the repository at this point in the history
Closes #393

Upgrades the second of the two Lambda handlers we have. Manually verified in a test account by manually invoking the Lambda with a valid event (e.g. `{"secretId": "test-secret"}`) and verifying that the metrics were emitted to CloudWatch.

---

_By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license_
  • Loading branch information
echeung-amzn authored Aug 29, 2023
1 parent 0f5ff75 commit 4fab44d
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 53 deletions.
89 changes: 41 additions & 48 deletions assets/SecretsManagerMetricsPublisher/index.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
const aws = require("aws-sdk");
const { CloudWatchClient, PutMetricDataCommand } = require('@aws-sdk/client-cloudwatch');
const { SecretsManagerClient, DescribeSecretCommand } = require('@aws-sdk/client-secrets-manager');

const region = process.env.AWS_REGION;
const millisPerDay = 1000 * 60 * 60 * 24;

const clientOptions = {
region,
maxRetries: 5,
httpOptions: {
connectTimeout: 3 * 1000,
timeout: 3 * 1000,
},
signingRegion: region,
retryMode: 'standard',
};

const cloudwatch = new aws.CloudWatch(clientOptions);
const sm = new aws.SecretsManager(clientOptions);
const cloudwatchClient = new CloudWatchClient(clientOptions);
const secretsManagerClient = new SecretsManagerClient(clientOptions);

function daysSince(date, now = Date.now()) {
const millis = now - date.getTime();
Expand All @@ -22,19 +19,18 @@ function daysSince(date, now = Date.now()) {
}

exports.handler = async (event, context) => {
console.debug("event:", JSON.stringify(event));
console.debug("context:", JSON.stringify(context));
console.info(`Retrieving secret for event ${JSON.stringify(event)}`);
console.debug(`context: ${JSON.stringify(context)}`);

console.info(`retrieving secret: ${event.secretId}`);
const secret = await sm
.describeSecret({
const secret = await secretsManagerClient.send(
new DescribeSecretCommand({
SecretId: event.secretId,
})
.promise();
);

console.debug("found secret: ", JSON.stringify(secret));
console.debug(`Found secret: ${JSON.stringify(secret)}`);
if (!secret.Name || !secret.CreatedDate) {
throw new Error("invalid secret response");
throw new Error("Invalid secret response");
}

// use retrieved secret name in case secretId was an arn
Expand All @@ -43,40 +39,37 @@ exports.handler = async (event, context) => {
const lastRotatedDate = secret.LastRotatedDate ?? secret.CreatedDate;
const now = Date.now();

const metricData = [
{
MetricName: "DaysSinceLastChange",
Dimensions: [
{
Name: "SecretName",
Value: secretName,
},
],
Unit: "Count",
Value: daysSince(lastChangedDate, now),
},
{
MetricName: "DaysSinceLastRotation",
Dimensions: [
{
Name: "SecretName",
Value: secretName,
},
],
Unit: "Count",
Value: daysSince(lastRotatedDate, now),
},
];

const params = {
Namespace: "SecretsManager",
MetricData: metricData,
MetricData: [
{
MetricName: "DaysSinceLastChange",
Dimensions: [
{
Name: "SecretName",
Value: secretName,
},
],
Unit: "Count",
Value: daysSince(lastChangedDate, now),
},
{
MetricName: "DaysSinceLastRotation",
Dimensions: [
{
Name: "SecretName",
Value: secretName,
},
],
Unit: "Count",
Value: daysSince(lastRotatedDate, now),
},
],
};

console.debug("putMetricData params: ", JSON.stringify(params));

console.info(`publishing metrics for secret: ${event.secretId}`);
await cloudwatch.putMetricData(params).promise();
console.debug(`putMetricData params: ${JSON.stringify(params)}`);
console.info(`Publishing metrics for secret "${event.secretId}"`);
const command = new PutMetricDataCommand(params);
await cloudwatchClient.send(command);

return Promise.resolve();
};
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export class SecretsManagerMetricsPublisher extends Construct {
"Custom metrics publisher for SecretsManager Secrets (MonitoringCDKConstructs)",
handler: "index.handler",
memorySize: 128,
runtime: Runtime.NODEJS_14_X,
runtime: Runtime.NODEJS_18_X,
timeout: Duration.seconds(60),
logRetention: RetentionDays.ONE_DAY,
});
Expand Down
4 changes: 2 additions & 2 deletions test/facade/__snapshots__/MonitoringAspect.test.ts.snap

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 4fab44d

Please sign in to comment.