Skip to content

Commit

Permalink
Merge branch 'main' into wf-val
Browse files Browse the repository at this point in the history
  • Loading branch information
daniel-belcher authored Jul 31, 2024
2 parents 24735aa + 82bc5dd commit 9758746
Show file tree
Hide file tree
Showing 24 changed files with 448 additions and 69 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,3 @@ build_run
# tests
coverage
__snapshots__
bin
2 changes: 2 additions & 0 deletions bin/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
"yargs": "^17.7.1"
},
"devDependencies": {
"@aws-sdk/client-resource-groups-tagging-api": "^3.621.0",
"simple-git": "^3.25.0",
"typescript": "^5.0.4"
}
}
1 change: 1 addition & 0 deletions bin/cli/src/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export * from "./destroy";
export * from "./docs";
export * from "./e2e";
export * from "./install";
export * from "./logs";
export * from "./open";
export * from "./test";
export * from "./ui";
Expand Down
148 changes: 148 additions & 0 deletions bin/cli/src/commands/logs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import { Argv } from "yargs";
import { LabeledProcessRunner } from "../lib/";
import simpleGit from "simple-git";
import {
ResourceGroupsTaggingAPIClient,
GetResourcesCommand,
TagFilter,
} from "@aws-sdk/client-resource-groups-tagging-api";
import {
LambdaClient,
GetFunctionCommand,
GetFunctionConfigurationCommand,
} from "@aws-sdk/client-lambda";
import prompts from "prompts";

const lambdaClient = new LambdaClient({ region: process.env.REGION_A });

const runner = new LabeledProcessRunner();

export const logs = {
command: "logs",
describe: "Stream a lambda's cloudwatch logs.",
builder: (yargs: Argv) =>
yargs
.option("stage", { type: "string", demandOption: false })
.option("functionName", {
alias: "f",
type: "string",
demandOption: true,
}),
handler: async (options: { stage?: string; functionName: string }) => {
let { stage, functionName } = options;
if (!stage) {
const git = simpleGit();
const branchSummary = await git.branch();
stage = branchSummary.current;
}
// Find all lambdas for the project and stage
const lambdas = await getLambdasWithTags([
{
Key: "PROJECT",
Value: process.env.project!,
},
{
Key: "STAGE",
Value: stage,
},
]);

// Filter out any lambdas that dont contain the functionName string
const filteredLambdas = lambdas.filter((lambda) =>
lambda.toLowerCase().includes(functionName.toLowerCase()),
);

// Set the target lambda, asking the user if necessary
let lambda: string;
if (filteredLambdas.length > 1) {
const response = await prompts({
type: "select",
name: "selectedLambda",
message: "Which Lambda function's logs do you want to stream?",
choices: filteredLambdas.map((lambda) => ({
title: lambda,
value: lambda,
})),
});
lambda = response.selectedLambda;
} else if (filteredLambdas.length === 1) {
lambda = filteredLambdas[0];
} else {
console.error("No Lambda functions found with the specified tags.");
return;
}

// Find the lambda log group name by checking the lambda's config
const lambdaLogGroup = await getLambdaLogGroup(lambda);

// Stream the logs
await runner.run_command_and_output(
"stream awslogs",
["awslogs", "get", lambdaLogGroup, "-s10m", "--watch"],
".",
);
},
};

interface Tag {
Key: string;
Value: string;
}

async function getLambdasWithTags(tags: Tag[]): Promise<string[]> {
const taggingClient = new ResourceGroupsTaggingAPIClient({
region: process.env.REGION_A,
});

// Ensure tags are valid
const tagFilters: TagFilter[] = tags
.filter((tag): tag is Tag => !!tag.Key && !!tag.Value) // Ensure no undefined keys or values
.map((tag) => ({
Key: tag.Key,
Values: [tag.Value],
}));

const command = new GetResourcesCommand({
ResourceTypeFilters: ["lambda"],
TagFilters: tagFilters,
});

try {
const data = await taggingClient.send(command);
if (!data.ResourceTagMappingList) {
return [];
}

// Extract Lambda function ARNs from the response
const lambdaArns = data.ResourceTagMappingList.map(
(resource) => resource.ResourceARN!,
);

// Fetch Lambda function names from their ARNs
const lambdaNames = await Promise.all(
lambdaArns.map(async (arn) => {
const functionCommand = new GetFunctionCommand({ FunctionName: arn });
const functionData = await lambdaClient.send(functionCommand);
return functionData.Configuration?.FunctionName || "";
}),
);

return lambdaNames;
} catch (error) {
console.error("Error retrieving Lambda functions with tags:", error);
return [];
}
}

async function getLambdaLogGroup(functionName: string) {
const response = await lambdaClient.send(
new GetFunctionConfigurationCommand({
FunctionName: functionName,
}),
);
if (response?.LoggingConfig?.LogGroup) {
return response.LoggingConfig.LogGroup;
} else {
throw new Error("Error finding log group for function " + functionName);
}
}
2 changes: 2 additions & 0 deletions bin/cli/src/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
docs,
e2e,
install,
logs,
openApp,
openKibana,
test,
Expand All @@ -18,6 +19,7 @@ yargs
.command(docs)
.command(e2e)
.command(install)
.command(logs)
.command(openApp)
.command(openKibana)
.command(test)
Expand Down
Binary file modified bun.lockb
Binary file not shown.
2 changes: 1 addition & 1 deletion lib/lambda/setupIndex.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ describe("handler", () => {
);
expect(os.createIndex).toHaveBeenCalledWith(
"test-domain",
"legacyinsights",
"test-namespace-legacyinsights",
);

expect(os.updateFieldMapping).toHaveBeenCalledTimes(1);
Expand Down
2 changes: 1 addition & 1 deletion lib/lambda/setupIndex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export const handler: Handler = async (event, __, callback) => {
});
await manageIndexResource({
osDomain: event.osDomain,
index: "legacyinsights",
index: `${event.indexNamespace}legacyinsights`,
});
} catch (error: any) {
response.statusCode = 500;
Expand Down
27 changes: 16 additions & 11 deletions lib/local-constructs/cloudwatch-to-s3/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,22 @@ export class CloudWatchToS3 extends Construct {
removalPolicy: cdk.RemovalPolicy.DESTROY,
});

this.logBucket.addToResourcePolicy(
new PolicyStatement({
effect: Effect.DENY,
principals: [new AnyPrincipal()],
actions: ["s3:*"],
resources: [this.logBucket.bucketArn, `${this.logBucket.bucketArn}/*`],
conditions: {
Bool: { "aws:SecureTransport": "false" },
},
}),
);
if (!bucket) {
this.logBucket.addToResourcePolicy(
new PolicyStatement({
effect: Effect.DENY,
principals: [new AnyPrincipal()],
actions: ["s3:*"],
resources: [
this.logBucket.bucketArn,
`${this.logBucket.bucketArn}/*`,
],
conditions: {
Bool: { "aws:SecureTransport": "false" },
},
}),
);
}

// Create a Firehose role
const firehoseRole = new Role(this, "FirehoseRole", {
Expand Down
3 changes: 2 additions & 1 deletion lib/packages/shared-types/forms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,8 @@ type Effects =
}
| {
type: "setValue";
newValue: unknown;
newValue: string | string[];
fieldName: string;
};

export interface DependencyRule {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,10 @@ export const transform = (id: string) => {
changedDate: getDateStringOrNullFromEpoc(data.changedDate),
subject: null,
description: null,
makoChangedDate: !!data.timestamp
? new Date(data.timestamp).toISOString()
: null,
makoChangedDate:
typeof data.timestamp === "number"
? new Date(data.timestamp).toISOString()
: null,
// ----------
};
} else {
Expand All @@ -72,9 +73,10 @@ export const transform = (id: string) => {
submitterName:
data.submitterName === "-- --" ? null : data.submitterName,
origin: "OneMAC",
makoChangedDate: !!data.timestamp
? new Date(data.timestamp).toISOString()
: null,
makoChangedDate:
typeof data.timestamp === "number"
? new Date(data.timestamp).toISOString()
: null,
};
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ export const transform = (id: string) => {
return {
id,
appkParentId: null,
makoChangedDate: !!data.timestamp
appkParent: true,
makoChangedDate: data.timestamp
? new Date(data.timestamp).toISOString()
: null,
};
Expand Down
54 changes: 50 additions & 4 deletions lib/stacks/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ export class Data extends cdk.NestedStack {
nodeToNodeEncryptionOptions: { enabled: true },
domainEndpointOptions: {
enforceHttps: true,
tlsSecurityPolicy: "Policy-Min-TLS-1-2-2019-07",
tlsSecurityPolicy: "Policy-Min-TLS-1-2-PFS-2023-10",
},
cognitoOptions: {
enabled: true,
Expand Down Expand Up @@ -237,6 +237,52 @@ export class Data extends cdk.NestedStack {
.slice(0, 3)
.map((subnet) => subnet.subnetId),
},
logPublishingOptions: {
AUDIT_LOGS: {
enabled: true,
cloudWatchLogsLogGroupArn: new cdk.aws_logs.LogGroup(
this,
"OpenSearchAuditLogGroup",
{
logGroupName: `/aws/opensearch/${project}-${stage}-audit-logs`,
removalPolicy: cdk.RemovalPolicy.DESTROY,
},
).logGroupArn,
},
INDEX_SLOW_LOGS: {
enabled: true,
cloudWatchLogsLogGroupArn: new cdk.aws_logs.LogGroup(
this,
"OpenSearchIndexSlowLogGroup",
{
logGroupName: `/aws/opensearch/${project}-${stage}-index-slow-logs`,
removalPolicy: cdk.RemovalPolicy.DESTROY,
},
).logGroupArn,
},
SEARCH_SLOW_LOGS: {
enabled: true,
cloudWatchLogsLogGroupArn: new cdk.aws_logs.LogGroup(
this,
"OpenSearchSearchSlowLogGroup",
{
logGroupName: `/aws/opensearch/${project}-${stage}-search-slow-logs`,
removalPolicy: cdk.RemovalPolicy.DESTROY,
},
).logGroupArn,
},
ES_APPLICATION_LOGS: {
enabled: true,
cloudWatchLogsLogGroupArn: new cdk.aws_logs.LogGroup(
this,
"OpenSearchApplicationLogGroup",
{
logGroupName: `/aws/opensearch/${project}-${stage}-application-logs`,
removalPolicy: cdk.RemovalPolicy.DESTROY,
},
).logGroupArn,
},
},
},
);

Expand Down Expand Up @@ -300,7 +346,7 @@ export class Data extends cdk.NestedStack {
securityGroups: [lambdaSecurityGroup],
environment: {
brokerString,
region: this.region,
region: cdk.Stack.of(this).region,
osDomain: `https://${openSearchDomain.attrDomainEndpoint}`,
},
bundling: {
Expand All @@ -321,7 +367,7 @@ export class Data extends cdk.NestedStack {
serviceToken: customResourceProvider.serviceToken,
properties: {
OsDomain: `https://${openSearchDomain.attrDomainEndpoint}`,
IamRoleName: `arn:aws:iam::${this.account}:role/*`,
IamRoleName: `arn:aws:iam::${cdk.Stack.of(this).account}:role/*`,
MasterRoleToAssume: openSearchMasterRole.roleArn,
OsRoleName: "all_access",
},
Expand Down Expand Up @@ -506,7 +552,7 @@ export class Data extends cdk.NestedStack {
new cdk.aws_iam.PolicyStatement({
actions: ["lambda:InvokeFunction"],
resources: [
`arn:aws:lambda:${this.region}:${this.account}:function:${project}-${stage}-${stack}-*`,
`arn:aws:lambda:${cdk.Stack.of(this).region}:${cdk.Stack.of(this).account}:function:${project}-${stage}-${stack}-*`,
],
}),
],
Expand Down
Loading

0 comments on commit 9758746

Please sign in to comment.