diff --git a/build.gradle b/build.gradle index f7faf76..3b240a2 100644 --- a/build.gradle +++ b/build.gradle @@ -28,7 +28,7 @@ dependencies { implementation 'io.github.acm19:aws-request-signing-apache-interceptor:2.3.1' implementation 'com.amazonaws:aws-lambda-java-core:1.2.3' - implementation 'com.amazonaws:aws-lambda-java-events:3.7.0' + implementation 'com.amazonaws:aws-lambda-java-events:3.11.5' implementation 'com.google.code.gson:gson:2.10.1' diff --git a/infrastructure/lib/constructs/snsMonitor.ts b/infrastructure/lib/constructs/snsMonitor.ts index 8c7e5de..6f95d4b 100644 --- a/infrastructure/lib/constructs/snsMonitor.ts +++ b/infrastructure/lib/constructs/snsMonitor.ts @@ -2,8 +2,9 @@ import { Construct } from 'constructs'; import * as sns from "aws-cdk-lib/aws-sns"; import * as subscriptions from "aws-cdk-lib/aws-sns-subscriptions"; import * as actions from "aws-cdk-lib/aws-cloudwatch-actions"; -import { Canary } from 'aws-cdk-lib/aws-synthetics'; import {OpenSearchLambda} from "./lambda"; +import Project from '../enums/project'; + export interface SnsMonitorsProps { readonly region: string; @@ -33,7 +34,7 @@ export class SnsMonitors extends Construct { // The email list for receiving alerts this.emailList = [ - 'insert@mail.here' + Project.SNS_ALERT_EMAIL ]; // Create alarms diff --git a/infrastructure/lib/enums/project.ts b/infrastructure/lib/enums/project.ts index 55f4b9c..77f45bf 100644 --- a/infrastructure/lib/enums/project.ts +++ b/infrastructure/lib/enums/project.ts @@ -9,5 +9,6 @@ enum Project{ RESTRICTED_PREFIX = '', LAMBDA_PACKAGE = 'opensearch-metrics-1.0.zip', EC2_AMI_SSM = '', + SNS_ALERT_EMAIL = 'insert@test.mail' } export default Project; diff --git a/infrastructure/lib/infrastructure-stack.ts b/infrastructure/lib/infrastructure-stack.ts index adf43ac..5137cb2 100644 --- a/infrastructure/lib/infrastructure-stack.ts +++ b/infrastructure/lib/infrastructure-stack.ts @@ -43,7 +43,9 @@ export class InfrastructureStack extends Stack { // Create Secrets Manager - const openSearchMetricsSecretsStack = new OpenSearchMetricsSecrets(app, "OpenSearchMetrics-Secrets"); + const openSearchMetricsSecretsStack = new OpenSearchMetricsSecrets(app, "OpenSearchMetrics-Secrets", { + secretName: 'metrics-creds' + }); // Create Monitoring Dashboard @@ -52,7 +54,7 @@ export class InfrastructureStack extends Stack { account: Project.AWS_ACCOUNT, workflowComponent: openSearchMetricsWorkflowStack.workflowComponent, lambdaPackage: Project.LAMBDA_PACKAGE, - secrets: openSearchMetricsSecretsStack.secretsObject, + secrets: openSearchMetricsSecretsStack.secret, vpcStack: vpcStack }); diff --git a/infrastructure/lib/stacks/secrets.ts b/infrastructure/lib/stacks/secrets.ts index 250b03e..84cd497 100644 --- a/infrastructure/lib/stacks/secrets.ts +++ b/infrastructure/lib/stacks/secrets.ts @@ -2,13 +2,17 @@ import {Stack} from "aws-cdk-lib"; import { Construct } from 'constructs'; import {Secret} from "aws-cdk-lib/aws-secretsmanager"; +export interface SecretProps { + readonly secretName: string +} + export class OpenSearchMetricsSecrets extends Stack { - readonly secretsObject: Secret; + readonly secret: Secret; - constructor(scope: Construct, id: string) { + constructor(scope: Construct, id: string, props: SecretProps ) { super(scope, id); - this.secretsObject = new Secret(this, 'MetricsCreds', { - secretName: 'metrics-creds', + this.secret = new Secret(this, `MetricsCreds-${props.secretName}`, { + secretName: props.secretName, }); } } diff --git a/infrastructure/package-lock.json b/infrastructure/package-lock.json index e4c9c66..2cfd42d 100644 --- a/infrastructure/package-lock.json +++ b/infrastructure/package-lock.json @@ -1266,6 +1266,7 @@ "yaml", "mime-types" ], + "license": "Apache-2.0", "dependencies": { "@aws-cdk/asset-awscli-v1": "^2.2.202", "@aws-cdk/asset-kubectl-v20": "^2.1.2", diff --git a/infrastructure/test/monitoring-stack.test.ts b/infrastructure/test/monitoring-stack.test.ts index a4f99f4..5c99213 100644 --- a/infrastructure/test/monitoring-stack.test.ts +++ b/infrastructure/test/monitoring-stack.test.ts @@ -27,13 +27,15 @@ test('Monitoring Stack Test', () => { vpcStack: vpcStack, lambdaPackage: Project.LAMBDA_PACKAGE }); - const openSearchMetricsSecretsStack = new OpenSearchMetricsSecrets(app, "OpenSearchMetrics-Secrets"); + const openSearchMetricsSecretsStack = new OpenSearchMetricsSecrets(app, "OpenSearchMetrics-Secrets", { + secretName: 'metrics-creds' + }); const openSearchMetricsMonitoringStack = new OpenSearchMetricsMonitoringStack(app, "OpenSearchMetrics-Monitoring", { region: Project.REGION, account: Project.AWS_ACCOUNT, workflowComponent: openSearchMetricsWorkflowStack.workflowComponent, lambdaPackage: Project.LAMBDA_PACKAGE, - secrets: openSearchMetricsSecretsStack.secretsObject, + secrets: openSearchMetricsSecretsStack.secret, vpcStack: vpcStack }); const template = Template.fromStack(openSearchMetricsMonitoringStack); @@ -63,10 +65,7 @@ test('Monitoring Stack Test', () => { "Statement": [ { "Action": "secretsmanager:GetSecretValue", - "Effect": "Allow", - "Resource": { - "Fn::ImportValue": "OpenSearchMetrics-Secrets:ExportsOutputRefMetricsCreds2260E61E4655F9C2" - } + "Effect": "Allow" }, { "Action": [ diff --git a/infrastructure/test/secrets-stack.test.ts b/infrastructure/test/secrets-stack.test.ts index bbdbb2e..edbd6f1 100644 --- a/infrastructure/test/secrets-stack.test.ts +++ b/infrastructure/test/secrets-stack.test.ts @@ -4,7 +4,9 @@ import {OpenSearchMetricsSecrets} from "../lib/stacks/secrets"; test('Secrets Stack Test', () => { const app = new App(); - const openSearchMetricsSecretsStack = new OpenSearchMetricsSecrets(app, "OpenSearchMetrics-Secrets"); + const openSearchMetricsSecretsStack = new OpenSearchMetricsSecrets(app, "OpenSearchMetrics-Secrets", { + secretName: 'metrics-creds' + }); const template = Template.fromStack(openSearchMetricsSecretsStack); template.resourceCountIs('AWS::SecretsManager::Secret', 1); template.hasResourceProperties('AWS::SecretsManager::Secret', { diff --git a/src/main/java/org/opensearchmetrics/lambda/SlackLambda.java b/src/main/java/org/opensearchmetrics/lambda/SlackLambda.java index 59bc761..e0909eb 100644 --- a/src/main/java/org/opensearchmetrics/lambda/SlackLambda.java +++ b/src/main/java/org/opensearchmetrics/lambda/SlackLambda.java @@ -1,17 +1,14 @@ package org.opensearchmetrics.lambda; +import org.opensearchmetrics.model.alarm.AlarmData; import org.opensearchmetrics.util.SecretsManagerUtil; import org.opensearchmetrics.datasource.DataSourceType; import com.google.common.annotations.VisibleForTesting; import lombok.NonNull; import lombok.extern.slf4j.Slf4j; -import lombok.Data; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.amazonaws.services.lambda.runtime.events.SNSEvent; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import org.apache.http.HttpResponse; @@ -40,22 +37,6 @@ public SlackLambda() { this.mapper = COMPONENT.getObjectMapper(); } - @JsonInclude(JsonInclude.Include.NON_NULL) - @JsonIgnoreProperties(ignoreUnknown = true) - @Data - private static class AlarmObject { - @JsonProperty("AlarmName") - private String alarmName; - @JsonProperty("AlarmDescription") - private String alarmDescription; - @JsonProperty("StateChangeTime") - private String stateChangeTime; - @JsonProperty("Region") - private String region; - @JsonProperty("AlarmArn") - private String alarmArn; - } - @Override public Void handleRequest(SNSEvent event, Context context) { String slackWebhookURL; @@ -80,8 +61,8 @@ public Void handleRequest(SNSEvent event, Context context) { } private void sendMessageToSlack(String message, String slackWebhookURL, String slackChannel, String slackUsername) throws IOException { - AlarmObject alarmObject = - mapper.readValue(message, AlarmObject.class); + AlarmData alarmObject = + mapper.readValue(message, AlarmData.class); String alarmMessage = ":alert: OpenSearch Metrics Dashboard Monitoring alarm activated. Please investigate the issue. \n" + "- Name: " + alarmObject.getAlarmName() + "\n" + "- Description: " + alarmObject.getAlarmDescription() + "\n" + diff --git a/src/main/java/org/opensearchmetrics/metrics/release/ReleaseInputs.java b/src/main/java/org/opensearchmetrics/metrics/release/ReleaseInputs.java index 965b4d2..6875d29 100644 --- a/src/main/java/org/opensearchmetrics/metrics/release/ReleaseInputs.java +++ b/src/main/java/org/opensearchmetrics/metrics/release/ReleaseInputs.java @@ -4,9 +4,11 @@ public enum ReleaseInputs { VERSION_3_0_0("3.0.0", "open", "main"), VERSION_2_12_0("2.12.0", "closed", "2.12"), VERSION_2_13_0("2.13.0", "closed", "2.13"), - - VERSION_2_14_0("2.14.0", "open", "2.x"), - VERSION_1_3_15("1.3.15", "closed", "1.3"); + VERSION_2_14_0("2.14.0", "closed", "2.14"), + VERSION_2_15_0("2.15.0", "open", "2.x"), + VERSION_1_3_15("1.3.15", "closed", "1.3"), + VERSION_1_3_16("1.3.16", "closed", "1.3"), + VERSION_1_3_17("1.3.17", "open", "1.3"); private final String version; private final String state; diff --git a/src/main/java/org/opensearchmetrics/model/alarm/AlarmData.java b/src/main/java/org/opensearchmetrics/model/alarm/AlarmData.java new file mode 100644 index 0000000..812b47c --- /dev/null +++ b/src/main/java/org/opensearchmetrics/model/alarm/AlarmData.java @@ -0,0 +1,18 @@ +package org.opensearchmetrics.model.alarm; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +@Data +public class AlarmData { + @JsonProperty("AlarmName") + private String alarmName; + @JsonProperty("AlarmDescription") + private String alarmDescription; + @JsonProperty("StateChangeTime") + private String stateChangeTime; + @JsonProperty("Region") + private String region; + @JsonProperty("AlarmArn") + private String alarmArn; +} diff --git a/src/main/java/org/opensearchmetrics/util/SecretsManagerUtil.java b/src/main/java/org/opensearchmetrics/util/SecretsManagerUtil.java index b3a1f27..98ca8b6 100644 --- a/src/main/java/org/opensearchmetrics/util/SecretsManagerUtil.java +++ b/src/main/java/org/opensearchmetrics/util/SecretsManagerUtil.java @@ -11,10 +11,7 @@ import lombok.Data; import lombok.extern.slf4j.Slf4j; -import java.io.ByteArrayInputStream; import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; import java.util.Optional; @Slf4j diff --git a/src/test/java/org/opensearchmetrics/metrics/release/ReleaseInputsTest.java b/src/test/java/org/opensearchmetrics/metrics/release/ReleaseInputsTest.java index 4aaa64e..d4852e6 100644 --- a/src/test/java/org/opensearchmetrics/metrics/release/ReleaseInputsTest.java +++ b/src/test/java/org/opensearchmetrics/metrics/release/ReleaseInputsTest.java @@ -13,16 +13,22 @@ public void testGetVersion() { assertEquals("2.12.0", ReleaseInputs.VERSION_2_12_0.getVersion()); assertEquals("2.13.0", ReleaseInputs.VERSION_2_13_0.getVersion()); assertEquals("2.14.0", ReleaseInputs.VERSION_2_14_0.getVersion()); + assertEquals("2.15.0", ReleaseInputs.VERSION_2_15_0.getVersion()); assertEquals("1.3.15", ReleaseInputs.VERSION_1_3_15.getVersion()); + assertEquals("1.3.16", ReleaseInputs.VERSION_1_3_16.getVersion()); + assertEquals("1.3.17", ReleaseInputs.VERSION_1_3_17.getVersion()); } @Test public void testGetState() { assertEquals("open", ReleaseInputs.VERSION_3_0_0.getState()); assertEquals("closed", ReleaseInputs.VERSION_2_12_0.getState()); - assertEquals("open", ReleaseInputs.VERSION_2_14_0.getState()); assertEquals("closed", ReleaseInputs.VERSION_2_13_0.getState()); + assertEquals("closed", ReleaseInputs.VERSION_2_14_0.getState()); + assertEquals("open", ReleaseInputs.VERSION_2_15_0.getState()); assertEquals("closed", ReleaseInputs.VERSION_1_3_15.getState()); + assertEquals("closed", ReleaseInputs.VERSION_1_3_16.getState()); + assertEquals("open", ReleaseInputs.VERSION_1_3_17.getState()); } @Test @@ -30,18 +36,23 @@ public void testGetBranch() { assertEquals("main", ReleaseInputs.VERSION_3_0_0.getBranch()); assertEquals("2.12", ReleaseInputs.VERSION_2_12_0.getBranch()); assertEquals("2.13", ReleaseInputs.VERSION_2_13_0.getBranch()); - assertEquals("2.x", ReleaseInputs.VERSION_2_14_0.getBranch()); + assertEquals("2.14", ReleaseInputs.VERSION_2_14_0.getBranch()); + assertEquals("2.x", ReleaseInputs.VERSION_2_15_0.getBranch()); assertEquals("1.3", ReleaseInputs.VERSION_1_3_15.getBranch()); + assertEquals("1.3", ReleaseInputs.VERSION_1_3_16.getBranch()); } @Test public void testGetAllReleaseInputs() { ReleaseInputs[] releaseInputs = ReleaseInputs.getAllReleaseInputs(); - assertEquals(5, releaseInputs.length); + assertEquals(8, releaseInputs.length); assertEquals(ReleaseInputs.VERSION_3_0_0, releaseInputs[0]); assertEquals(ReleaseInputs.VERSION_2_12_0, releaseInputs[1]); assertEquals(ReleaseInputs.VERSION_2_13_0, releaseInputs[2]); assertEquals(ReleaseInputs.VERSION_2_14_0, releaseInputs[3]); - assertEquals(ReleaseInputs.VERSION_1_3_15, releaseInputs[4]); + assertEquals(ReleaseInputs.VERSION_2_15_0, releaseInputs[4]); + assertEquals(ReleaseInputs.VERSION_1_3_15, releaseInputs[5]); + assertEquals(ReleaseInputs.VERSION_1_3_16, releaseInputs[6]); + assertEquals(ReleaseInputs.VERSION_1_3_17, releaseInputs[7]); } } diff --git a/src/test/java/org/opensearchmetrics/model/alarm/AlarmDataTest.java b/src/test/java/org/opensearchmetrics/model/alarm/AlarmDataTest.java new file mode 100644 index 0000000..aa20f1b --- /dev/null +++ b/src/test/java/org/opensearchmetrics/model/alarm/AlarmDataTest.java @@ -0,0 +1,52 @@ +package org.opensearchmetrics.model.alarm; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class AlarmDataTest { + @Mock + ObjectMapper objectMapper; + + private AlarmData alarmData; + + @BeforeEach + void setUp() { + MockitoAnnotations.openMocks(this); + alarmData = new AlarmData(); + } + + @Test + public void testAlarmName() { + alarmData.setAlarmName("testName"); + assertEquals("testName", alarmData.getAlarmName()); + } + + @Test + public void testAlarmDescription() { + alarmData.setAlarmDescription("testDescription"); + assertEquals("testDescription", alarmData.getAlarmDescription()); + } + + @Test + public void testStateChangeTime() { + alarmData.setStateChangeTime("testStateChangeTime"); + assertEquals("testStateChangeTime", alarmData.getStateChangeTime()); + } + + @Test + public void testRegion() { + alarmData.setRegion("testRegion"); + assertEquals("testRegion", alarmData.getRegion()); + } + + @Test + public void testAlarmArn() { + alarmData.setAlarmArn("testArn"); + assertEquals("testArn", alarmData.getAlarmArn()); + } +}