Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: added new migration script to make existing audit logs archivable #3268

Merged
merged 1 commit into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions utils/archivableAuditLogsMigration/.env_example
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Copy to .env

LOCAL_AWS_ENDPOINT=http://127.0.0.1:4566

AWS_ACCESS_KEY_ID=test
AWS_SECRET_ACCESS_KEY=test
AWS_REGION=ca-central-1
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/* eslint-disable no-console */
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { ScanCommand, ScanCommandOutput, TransactWriteCommand } from "@aws-sdk/lib-dynamodb";
import { config } from "dotenv";

const main = async () => {
try {
const dynamodbClient = new DynamoDBClient({
region: process.env.AWS_REGION ?? "ca-central-1",
...(process.env.LOCAL_AWS_ENDPOINT && { endpoint: process.env.LOCAL_AWS_ENDPOINT }),
});

let lastEvaluatedKey = null;
let numberOfMigratedAuditLogs = 0;

while (lastEvaluatedKey !== undefined) {
const scanResults: ScanCommandOutput = await dynamodbClient.send(
new ScanCommand({
TableName: "AuditLogs",
ExclusiveStartKey: lastEvaluatedKey ?? undefined,
Limit: 100, // The upcoming `TransactWriteCommand` operation can only update 100 items per request
FilterExpression: "attribute_not_exists(#status)",
ProjectionExpression: "UserID,#rangeKey",
ExpressionAttributeNames: {
"#status": "Status",
"#rangeKey": "Event#SubjectID#TimeStamp",
},
})
);

if (scanResults.Items && scanResults.Items.length > 0) {
await dynamodbClient.send(
new TransactWriteCommand({
TransactItems: scanResults.Items.map((item) => {
return {
Update: {
TableName: "AuditLogs",
Key: {
UserID: item["UserID"],
["Event#SubjectID#TimeStamp"]: item["Event#SubjectID#TimeStamp"],
},
UpdateExpression: "SET #status = :status",
ExpressionAttributeNames: {
"#status": "Status",
},
ExpressionAttributeValues: {
":status": "Archivable",
},
},
};
}),
})
);

numberOfMigratedAuditLogs += scanResults.Items.length;

process.stdout.write(
`Migration in progress ... ${numberOfMigratedAuditLogs} audit logs have been updated.\r`
);
}

lastEvaluatedKey = scanResults.LastEvaluatedKey;
}

console.log("\nMigration completed successfully!");
} catch (error) {
console.log(error);
}
};

// config() adds the .env variables to process.env
config();

main();
18 changes: 18 additions & 0 deletions utils/archivableAuditLogsMigration/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "archivable_audit_logs_migration",
"version": "0.1.0",
"description": "Update existing audit logs to make them archivable",
"main": "add_archivable_status_field_to_audit_logs.ts",
"scripts": {
"make-audit-logs-archivable": "tsx add_archivable_status_field_to_audit_logs.ts"
},
"keywords": [],
"author": "Clément Janin",
"dependencies": {
"@aws-sdk/client-dynamodb": "^3.518.0",
"@aws-sdk/lib-dynamodb": "^3.518.0",
"dotenv": "^16.3.1",
"tsx": "^3.14.0"
},
"packageManager": "[email protected]"
}
21 changes: 21 additions & 0 deletions utils/archivableAuditLogsMigration/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig to read more about this file */

/* Language and Environment */
"target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,

/* Modules */
"module": "commonjs" /* Specify what module code is generated. */,

/* Interop Constraints */
"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */,
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,

/* Type Checking */
"strict": true /* Enable all strict type-checking options. */,

/* Completeness */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
}
}
Loading
Loading