From 0ff5ba0e7213a1a7f356720305ad24d758546c33 Mon Sep 17 00:00:00 2001 From: zhichao-aws Date: Thu, 24 Aug 2023 18:23:00 +0800 Subject: [PATCH 01/28] Microsoft teams (#676) * Added feature support for microsoft teams webhoo Signed-off-by: danielkyalo599 * Added feature support for microsoft teams webhook ,removed valid webhooks Signed-off-by: danielkyalo599 * Added feature support for Microsoft teams webhook Signed-off-by: danielkyalo599 * Refactored feature support for ms teams and added unit and integTest Signed-off-by: danielkyalo599 * fix build in core Signed-off-by: zhichao-aws * fix core-spi build Signed-off-by: zhichao-aws * fix notifications main code Signed-off-by: zhichao-aws * fix mappings, add IT Signed-off-by: zhichao-aws * add auto upgrade mapping logic Signed-off-by: zhichao-aws * put load mapping to initialize step Signed-off-by: zhichao-aws * add schema_version field Signed-off-by: zhichao-aws * add integ test Signed-off-by: zhichao-aws * adjust with auto upgrade mapping logic Signed-off-by: zhichao-aws * add bwc Signed-off-by: zhichao-aws * modify bwc Signed-off-by: zhichao-aws * modify bwc Signed-off-by: zhichao-aws * resolve comments Signed-off-by: zhichao-aws * add license header Signed-off-by: zhichao-aws * fix microsoft teams sample url in IT to adapt url validation Signed-off-by: zhichao-aws --------- Signed-off-by: danielkyalo599 Signed-off-by: zhichao-aws Co-authored-by: danielkyalo599 Signed-off-by: Aniruddh --- .../spi/model/destination/DestinationType.kt | 2 +- .../destination/MicrosoftTeamsDestination.kt | 13 ++ .../spi/utils/ValidationHelpersTests.kt | 5 + .../src/main/config/notifications-core.yml | 2 +- .../core/NotificationCoreImpl.kt | 2 +- .../core/client/DestinationHttpClient.kt | 5 +- .../core/setting/PluginSettings.kt | 1 + .../transport/DestinationTransportProvider.kt | 1 + .../core/NotificationCoreImplTests.kt | 1 + .../MicrosoftTeamsDestinationTests.kt | 182 ++++++++++++++++++ .../core/settings/PluginSettingsTests.kt | 1 + .../index/ConfigIndexingActions.kt | 9 +- .../notifications/index/ConfigQueryHelper.kt | 3 + .../notifications/metrics/Metrics.kt | 4 + .../NotificationConfigRestHandler.kt | 1 + .../send/SendMessageActionHelper.kt | 19 +- .../notifications-config-mapping.yml | 12 +- .../opensearch/integtest/IntegTestHelpers.kt | 3 + .../integtest/SecurityNotificationIT.kt | 3 +- .../NotificationsBackwardsCompatibilityIT.kt | 3 + .../config/CreateNotificationConfigIT.kt | 53 ++++- .../MicrosoftTeamsNotificationConfigCrudIT.kt | 158 +++++++++++++++ .../config/QueryNotificationConfigIT.kt | 35 +++- .../config/SlackNotificationConfigCrudIT.kt | 2 +- .../features/GetNotificationChannelListIT.kt | 3 +- .../send/SendTestMessageRestHandlerIT.kt | 33 +++- .../notifications/ObjectEqualsHelpers.kt | 6 + .../index/ConfigIndexingActionsTests.kt | 45 +++++ 28 files changed, 575 insertions(+), 32 deletions(-) create mode 100644 notifications/core-spi/src/main/kotlin/org/opensearch/notifications/spi/model/destination/MicrosoftTeamsDestination.kt create mode 100644 notifications/core/src/test/kotlin/org/opensearch/notifications/core/destinations/MicrosoftTeamsDestinationTests.kt create mode 100644 notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/MicrosoftTeamsNotificationConfigCrudIT.kt create mode 100644 notifications/notifications/src/test/kotlin/org/opensearch/notifications/index/ConfigIndexingActionsTests.kt diff --git a/notifications/core-spi/src/main/kotlin/org/opensearch/notifications/spi/model/destination/DestinationType.kt b/notifications/core-spi/src/main/kotlin/org/opensearch/notifications/spi/model/destination/DestinationType.kt index f915e174..9ed9a8ca 100644 --- a/notifications/core-spi/src/main/kotlin/org/opensearch/notifications/spi/model/destination/DestinationType.kt +++ b/notifications/core-spi/src/main/kotlin/org/opensearch/notifications/spi/model/destination/DestinationType.kt @@ -8,5 +8,5 @@ package org.opensearch.notifications.spi.model.destination * Supported notification destinations */ enum class DestinationType { - CHIME, SLACK, CUSTOM_WEBHOOK, SMTP, SES, SNS + CHIME, SLACK, MICROSOFT_TEAMS, CUSTOM_WEBHOOK, SMTP, SES, SNS } diff --git a/notifications/core-spi/src/main/kotlin/org/opensearch/notifications/spi/model/destination/MicrosoftTeamsDestination.kt b/notifications/core-spi/src/main/kotlin/org/opensearch/notifications/spi/model/destination/MicrosoftTeamsDestination.kt new file mode 100644 index 00000000..7200795f --- /dev/null +++ b/notifications/core-spi/src/main/kotlin/org/opensearch/notifications/spi/model/destination/MicrosoftTeamsDestination.kt @@ -0,0 +1,13 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.notifications.spi.model.destination + +/** + * This class holds the contents of a Microsoft Teams destination + */ +class MicrosoftTeamsDestination( + url: String, +) : WebhookDestination(url, DestinationType.MICROSOFT_TEAMS) diff --git a/notifications/core-spi/src/test/kotlin/org/opensearch/notifications/spi/utils/ValidationHelpersTests.kt b/notifications/core-spi/src/test/kotlin/org/opensearch/notifications/spi/utils/ValidationHelpersTests.kt index 0d803730..57f4e129 100644 --- a/notifications/core-spi/src/test/kotlin/org/opensearch/notifications/spi/utils/ValidationHelpersTests.kt +++ b/notifications/core-spi/src/test/kotlin/org/opensearch/notifications/spi/utils/ValidationHelpersTests.kt @@ -22,6 +22,7 @@ internal class ValidationHelpersTests { private val LOCAL_HOST_EXTENDED = "https://localhost:6060/service" private val WEBHOOK_URL = "https://test-webhook.com:1234/subdirectory?param1=value1¶m2=¶m3=value3" private val CHIME_URL = "https://domain.com/sample_chime_url#1234567890" + private val MICROSOFT_TEAMS_WEBHOOK_URL = "https://test.webhook.office.com/webhookb2/12345678/IncomingWebhook/87654321" private val hostDenyList = listOf( "127.0.0.0/8", @@ -99,4 +100,8 @@ internal class ValidationHelpersTests { fun `validator identifies chime url as valid`() { assert(isValidUrl(CHIME_URL)) } + @Test + fun `validator identifies microsoft teams url as valid`() { + assert(isValidUrl(MICROSOFT_TEAMS_WEBHOOK_URL)) + } } diff --git a/notifications/core/src/main/config/notifications-core.yml b/notifications/core/src/main/config/notifications-core.yml index 57b2d613..9ae7ed40 100644 --- a/notifications/core/src/main/config/notifications-core.yml +++ b/notifications/core/src/main/config/notifications-core.yml @@ -15,5 +15,5 @@ opensearch.notifications.core: connection_timeout: 5000 # in milliseconds socket_timeout: 50000 host_deny_list: [] - allowed_config_types: ["slack","chime","webhook","email","sns","ses_account","smtp_account","email_group"] + allowed_config_types: ["slack","chime","microsoft_teams","webhook","email","sns","ses_account","smtp_account","email_group"] tooltip_support: true diff --git a/notifications/core/src/main/kotlin/org/opensearch/notifications/core/NotificationCoreImpl.kt b/notifications/core/src/main/kotlin/org/opensearch/notifications/core/NotificationCoreImpl.kt index 615cee1e..3cb2771e 100644 --- a/notifications/core/src/main/kotlin/org/opensearch/notifications/core/NotificationCoreImpl.kt +++ b/notifications/core/src/main/kotlin/org/opensearch/notifications/core/NotificationCoreImpl.kt @@ -16,7 +16,7 @@ import java.security.PrivilegedAction /** * This is a client facing NotificationCoreImpl class to send the messages - * to the NotificationCoreImpl channels like chime, slack, webhooks, email etc + * to the NotificationCoreImpl channels like chime, slack, Microsoft Teams, webhooks, email etc */ object NotificationCoreImpl : NotificationCore { /** diff --git a/notifications/core/src/main/kotlin/org/opensearch/notifications/core/client/DestinationHttpClient.kt b/notifications/core/src/main/kotlin/org/opensearch/notifications/core/client/DestinationHttpClient.kt index e65fe95f..e186eefe 100644 --- a/notifications/core/src/main/kotlin/org/opensearch/notifications/core/client/DestinationHttpClient.kt +++ b/notifications/core/src/main/kotlin/org/opensearch/notifications/core/client/DestinationHttpClient.kt @@ -31,6 +31,7 @@ import org.opensearch.notifications.core.utils.validateUrlHost import org.opensearch.notifications.spi.model.MessageContent import org.opensearch.notifications.spi.model.destination.ChimeDestination import org.opensearch.notifications.spi.model.destination.CustomWebhookDestination +import org.opensearch.notifications.spi.model.destination.MicrosoftTeamsDestination import org.opensearch.notifications.spi.model.destination.SlackDestination import org.opensearch.notifications.spi.model.destination.WebhookDestination import java.io.IOException @@ -159,12 +160,14 @@ class DestinationHttpClient { val keyName = when (destination) { // Slack webhook request body has required "text" as key name https://api.slack.com/messaging/webhooks // Chime webhook request body has required "Content" as key name + // Microsoft Teams webhook request body has required "text" as key name https://learn.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/what-are-webhooks-and-connectors // Customer webhook allows input as json or plain text, so we just return the message as it is is SlackDestination -> "text" is ChimeDestination -> "Content" + is MicrosoftTeamsDestination -> "text" is CustomWebhookDestination -> return message.textDescription else -> throw IllegalArgumentException( - "Invalid destination type is provided, Only Slack, Chime and CustomWebhook are allowed" + "Invalid destination type is provided, Only Slack, Chime, Microsoft Teams and CustomWebhook are allowed" ) } diff --git a/notifications/core/src/main/kotlin/org/opensearch/notifications/core/setting/PluginSettings.kt b/notifications/core/src/main/kotlin/org/opensearch/notifications/core/setting/PluginSettings.kt index d965f7d4..75bbeb1b 100644 --- a/notifications/core/src/main/kotlin/org/opensearch/notifications/core/setting/PluginSettings.kt +++ b/notifications/core/src/main/kotlin/org/opensearch/notifications/core/setting/PluginSettings.kt @@ -157,6 +157,7 @@ internal object PluginSettings { private val DEFAULT_ALLOWED_CONFIG_TYPES = listOf( "slack", "chime", + "microsoft_teams", "webhook", "email", "sns", diff --git a/notifications/core/src/main/kotlin/org/opensearch/notifications/core/transport/DestinationTransportProvider.kt b/notifications/core/src/main/kotlin/org/opensearch/notifications/core/transport/DestinationTransportProvider.kt index ed682951..24f6a174 100644 --- a/notifications/core/src/main/kotlin/org/opensearch/notifications/core/transport/DestinationTransportProvider.kt +++ b/notifications/core/src/main/kotlin/org/opensearch/notifications/core/transport/DestinationTransportProvider.kt @@ -24,6 +24,7 @@ internal object DestinationTransportProvider { var destinationTransportMap = mapOf( DestinationType.SLACK to webhookDestinationTransport, DestinationType.CHIME to webhookDestinationTransport, + DestinationType.MICROSOFT_TEAMS to webhookDestinationTransport, DestinationType.CUSTOM_WEBHOOK to webhookDestinationTransport, DestinationType.SMTP to smtpDestinationTransport, DestinationType.SNS to snsDestinationTransport, diff --git a/notifications/core/src/test/kotlin/org/opensearch/notifications/core/NotificationCoreImplTests.kt b/notifications/core/src/test/kotlin/org/opensearch/notifications/core/NotificationCoreImplTests.kt index 872840ec..bd9da840 100644 --- a/notifications/core/src/test/kotlin/org/opensearch/notifications/core/NotificationCoreImplTests.kt +++ b/notifications/core/src/test/kotlin/org/opensearch/notifications/core/NotificationCoreImplTests.kt @@ -14,6 +14,7 @@ class NotificationCoreImplTests { private val defaultConfigTypes = listOf( "slack", "chime", + "microsoft_teams", "webhook", "email", "sns", diff --git a/notifications/core/src/test/kotlin/org/opensearch/notifications/core/destinations/MicrosoftTeamsDestinationTests.kt b/notifications/core/src/test/kotlin/org/opensearch/notifications/core/destinations/MicrosoftTeamsDestinationTests.kt new file mode 100644 index 00000000..1fffa8da --- /dev/null +++ b/notifications/core/src/test/kotlin/org/opensearch/notifications/core/destinations/MicrosoftTeamsDestinationTests.kt @@ -0,0 +1,182 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.notifications.core.destinations + +import io.mockk.every +import io.mockk.mockk +import io.mockk.mockkStatic +import org.apache.hc.client5.http.classic.methods.HttpPost +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient +import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse +import org.apache.hc.core5.http.io.entity.StringEntity +import org.easymock.EasyMock +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.Arguments +import org.junit.jupiter.params.provider.MethodSource +import org.opensearch.core.rest.RestStatus +import org.opensearch.notifications.core.NotificationCoreImpl +import org.opensearch.notifications.core.client.DestinationHttpClient +import org.opensearch.notifications.core.transport.DestinationTransportProvider +import org.opensearch.notifications.core.transport.WebhookDestinationTransport +import org.opensearch.notifications.spi.model.DestinationMessageResponse +import org.opensearch.notifications.spi.model.MessageContent +import org.opensearch.notifications.spi.model.destination.ChimeDestination +import org.opensearch.notifications.spi.model.destination.DestinationType +import org.opensearch.notifications.spi.model.destination.MicrosoftTeamsDestination +import java.net.MalformedURLException +import java.util.stream.Stream + +internal class MicrosoftTeamsDestinationTests { + companion object { + @JvmStatic + fun escapeSequenceToRaw(): Stream = + Stream.of( + Arguments.of("\n", """\n"""), + Arguments.of("\t", """\t"""), + Arguments.of("\b", """\b"""), + Arguments.of("\r", """\r"""), + Arguments.of("\"", """\""""), + ) + } + + @BeforeEach + fun setup() { + // Stubbing isHostInDenylist() so it doesn't attempt to resolve hosts that don't exist in the unit tests + mockkStatic("org.opensearch.notifications.spi.utils.ValidationHelpersKt") + every { org.opensearch.notifications.spi.utils.isHostInDenylist(any(), any()) } returns false + } + + @Test + fun `test MicrosoftTeams message null entity response`() { + val mockHttpClient: CloseableHttpClient = EasyMock.createMock(CloseableHttpClient::class.java) + + // The DestinationHttpClient replaces a null entity with "{}". + val expectedWebhookResponse = DestinationMessageResponse(RestStatus.OK.status, "{}") + + val httpResponse = mockk() + EasyMock.expect(mockHttpClient.execute(EasyMock.anyObject(HttpPost::class.java))).andReturn(httpResponse) + + every { httpResponse.code } returns RestStatus.OK.status + every { httpResponse.entity } returns null + EasyMock.replay(mockHttpClient) + + val httpClient = DestinationHttpClient(mockHttpClient) + val webhookDestinationTransport = WebhookDestinationTransport(httpClient) + DestinationTransportProvider.destinationTransportMap = mapOf(DestinationType.MICROSOFT_TEAMS to webhookDestinationTransport) + + val title = "test MicrosoftTeams" + val messageText = "Message gughjhjlkh Body emoji test: :) :+1: " + + "link test: http://sample.com email test: marymajor@example.com All member callout: " + + "@All All Present member callout: @Present" + val url = "https://abc/com" + + val destination = MicrosoftTeamsDestination(url) + val message = MessageContent(title, messageText) + + val actualMicrosoftTeamsResponse: DestinationMessageResponse = NotificationCoreImpl.sendMessage(destination, message, "ref") + + assertEquals(expectedWebhookResponse.statusText, actualMicrosoftTeamsResponse.statusText) + assertEquals(expectedWebhookResponse.statusCode, actualMicrosoftTeamsResponse.statusCode) + } + + @Test + fun `test MicrosoftTeams message empty entity response`() { + val mockHttpClient: CloseableHttpClient = EasyMock.createMock(CloseableHttpClient::class.java) + val expectedWebhookResponse = DestinationMessageResponse(RestStatus.OK.status, "{}") + + val httpResponse = mockk() + EasyMock.expect(mockHttpClient.execute(EasyMock.anyObject(HttpPost::class.java))).andReturn(httpResponse) + every { httpResponse.code } returns RestStatus.OK.status + every { httpResponse.entity } returns StringEntity("") + EasyMock.replay(mockHttpClient) + + val httpClient = DestinationHttpClient(mockHttpClient) + val webhookDestinationTransport = WebhookDestinationTransport(httpClient) + DestinationTransportProvider.destinationTransportMap = mapOf(DestinationType.MICROSOFT_TEAMS to webhookDestinationTransport) + + val title = "test MicrosoftTeams" + val messageText = "{\"Content\":\"Message gughjhjlkh Body emoji test: :) :+1: " + + "link test: http://sample.com email test: marymajor@example.com All member callout: " + + "@All All Present member callout: @Present\"}" + val url = "https://abc/com" + + val destination = MicrosoftTeamsDestination(url) + val message = MessageContent(title, messageText) + + val actualMicrosoftTeamsResponse: DestinationMessageResponse = NotificationCoreImpl.sendMessage(destination, message, "ref") + + assertEquals(expectedWebhookResponse.statusText, actualMicrosoftTeamsResponse.statusText) + assertEquals(expectedWebhookResponse.statusCode, actualMicrosoftTeamsResponse.statusCode) + } + + @Test + fun `test MicrosoftTeams message non-empty entity response`() { + val responseContent = "It worked!" + val mockHttpClient: CloseableHttpClient = EasyMock.createMock(CloseableHttpClient::class.java) + val expectedWebhookResponse = DestinationMessageResponse(RestStatus.OK.status, responseContent) + + val httpResponse = mockk() + EasyMock.expect(mockHttpClient.execute(EasyMock.anyObject(HttpPost::class.java))).andReturn(httpResponse) + every { httpResponse.code } returns RestStatus.OK.status + every { httpResponse.entity } returns StringEntity(responseContent) + EasyMock.replay(mockHttpClient) + + val httpClient = DestinationHttpClient(mockHttpClient) + val webhookDestinationTransport = WebhookDestinationTransport(httpClient) + DestinationTransportProvider.destinationTransportMap = mapOf(DestinationType.MICROSOFT_TEAMS to webhookDestinationTransport) + + val title = "test MicrosoftTeams" + val messageText = "{\"Content\":\"Message gughjhjlkh Body emoji test: :) :+1: " + + "link test: http://sample.com email test: marymajor@example.com All member callout: " + + "@All All Present member callout: @Present\"}" + val url = "https://abc/com" + + val destination = MicrosoftTeamsDestination(url) + val message = MessageContent(title, messageText) + + val actualMicrosoftTeamsResponse: DestinationMessageResponse = NotificationCoreImpl.sendMessage(destination, message, "ref") + + assertEquals(expectedWebhookResponse.statusText, actualMicrosoftTeamsResponse.statusText) + assertEquals(expectedWebhookResponse.statusCode, actualMicrosoftTeamsResponse.statusCode) + } + + @Test + fun `test url missing should throw IllegalArgumentException with message`() { + val exception = Assertions.assertThrows(IllegalArgumentException::class.java) { + MicrosoftTeamsDestination("") + } + assertEquals("url is null or empty", exception.message) + } + + @Test + fun testUrlInvalidMessage() { + assertThrows { + ChimeDestination("invalidUrl") + } + } + + @ParameterizedTest + @MethodSource("escapeSequenceToRaw") + fun `test build webhook request body for microsoft teams should have title included and prevent escape`( + escapeSequence: String, + rawString: String + ) { + val httpClient = DestinationHttpClient() + val title = "test MicrosoftTeams" + val messageText = "line1${escapeSequence}line2" + val url = "https://abc/com" + val expectedRequestBody = """{"text":"$title\n\nline1${rawString}line2"}""" + val destination = MicrosoftTeamsDestination(url) + val message = MessageContent(title, messageText) + val actualRequestBody = httpClient.buildRequestBody(destination, message) + assertEquals(expectedRequestBody, actualRequestBody) + } +} diff --git a/notifications/core/src/test/kotlin/org/opensearch/notifications/core/settings/PluginSettingsTests.kt b/notifications/core/src/test/kotlin/org/opensearch/notifications/core/settings/PluginSettingsTests.kt index 098da401..147516d9 100644 --- a/notifications/core/src/test/kotlin/org/opensearch/notifications/core/settings/PluginSettingsTests.kt +++ b/notifications/core/src/test/kotlin/org/opensearch/notifications/core/settings/PluginSettingsTests.kt @@ -54,6 +54,7 @@ internal class PluginSettingsTests { listOf( "slack", "chime", + "microsoft_teams", "webhook", "email", "sns", diff --git a/notifications/notifications/src/main/kotlin/org/opensearch/notifications/index/ConfigIndexingActions.kt b/notifications/notifications/src/main/kotlin/org/opensearch/notifications/index/ConfigIndexingActions.kt index 21242476..741f8e79 100644 --- a/notifications/notifications/src/main/kotlin/org/opensearch/notifications/index/ConfigIndexingActions.kt +++ b/notifications/notifications/src/main/kotlin/org/opensearch/notifications/index/ConfigIndexingActions.kt @@ -4,7 +4,6 @@ */ package org.opensearch.notifications.index - import org.opensearch.OpenSearchStatusException import org.opensearch.commons.authuser.User import org.opensearch.commons.notifications.action.CreateNotificationConfigRequest @@ -23,6 +22,7 @@ import org.opensearch.commons.notifications.model.Chime import org.opensearch.commons.notifications.model.ConfigType import org.opensearch.commons.notifications.model.Email import org.opensearch.commons.notifications.model.EmailGroup +import org.opensearch.commons.notifications.model.MicrosoftTeams import org.opensearch.commons.notifications.model.NotificationConfig import org.opensearch.commons.notifications.model.NotificationConfigInfo import org.opensearch.commons.notifications.model.NotificationConfigSearchResult @@ -39,7 +39,6 @@ import org.opensearch.notifications.model.DocMetadata import org.opensearch.notifications.model.NotificationConfigDoc import org.opensearch.notifications.security.UserAccess import java.time.Instant - /** * NotificationConfig indexing operation actions. */ @@ -65,6 +64,10 @@ object ConfigIndexingActions { // TODO: URL validation with rules } + private fun validateMicrosoftTeamsConfig(microsoftTeams: MicrosoftTeams, user: User?) { + require(microsoftTeams.url.contains(Regex("https://.*\\.webhook\\.office\\.com"))) + } + @Suppress("UnusedPrivateMember") private fun validateWebhookConfig(webhook: Webhook, user: User?) { // TODO: URL validation with rules @@ -162,6 +165,7 @@ object ConfigIndexingActions { ) ConfigType.SLACK -> validateSlackConfig(config.configData as Slack, user) ConfigType.CHIME -> validateChimeConfig(config.configData as Chime, user) + ConfigType.MICROSOFT_TEAMS -> validateMicrosoftTeamsConfig(config.configData as MicrosoftTeams, user) ConfigType.WEBHOOK -> validateWebhookConfig(config.configData as Webhook, user) ConfigType.EMAIL -> validateEmailConfig(config.configData as Email, user) ConfigType.SMTP_ACCOUNT -> validateSmtpAccountConfig(config.configData as SmtpAccount, user) @@ -369,6 +373,7 @@ object ConfigIndexingActions { return listOf( ConfigType.SLACK.tag, ConfigType.CHIME.tag, + ConfigType.MICROSOFT_TEAMS.tag, ConfigType.WEBHOOK.tag, ConfigType.EMAIL.tag, ConfigType.SNS.tag diff --git a/notifications/notifications/src/main/kotlin/org/opensearch/notifications/index/ConfigQueryHelper.kt b/notifications/notifications/src/main/kotlin/org/opensearch/notifications/index/ConfigQueryHelper.kt index 93049399..bdccce08 100644 --- a/notifications/notifications/src/main/kotlin/org/opensearch/notifications/index/ConfigQueryHelper.kt +++ b/notifications/notifications/src/main/kotlin/org/opensearch/notifications/index/ConfigQueryHelper.kt @@ -28,6 +28,7 @@ import org.opensearch.commons.notifications.NotificationConstants.URL_TAG import org.opensearch.commons.notifications.model.ConfigType.CHIME import org.opensearch.commons.notifications.model.ConfigType.EMAIL import org.opensearch.commons.notifications.model.ConfigType.EMAIL_GROUP +import org.opensearch.commons.notifications.model.ConfigType.MICROSOFT_TEAMS import org.opensearch.commons.notifications.model.ConfigType.SES_ACCOUNT import org.opensearch.commons.notifications.model.ConfigType.SLACK import org.opensearch.commons.notifications.model.ConfigType.SMTP_ACCOUNT @@ -69,6 +70,7 @@ object ConfigQueryHelper { "$DESCRIPTION_TAG.$KEYWORD_SUFFIX", "${SLACK.tag}.$URL_TAG.$KEYWORD_SUFFIX", "${CHIME.tag}.$URL_TAG.$KEYWORD_SUFFIX", + "${MICROSOFT_TEAMS.tag}.$URL_TAG.$KEYWORD_SUFFIX", "${WEBHOOK.tag}.$URL_TAG.$KEYWORD_SUFFIX", "${SMTP_ACCOUNT.tag}.$HOST_TAG.$KEYWORD_SUFFIX", "${SMTP_ACCOUNT.tag}.$FROM_ADDRESS_TAG.$KEYWORD_SUFFIX", @@ -82,6 +84,7 @@ object ConfigQueryHelper { DESCRIPTION_TAG, "${SLACK.tag}.$URL_TAG", "${CHIME.tag}.$URL_TAG", + "${MICROSOFT_TEAMS.tag}.$URL_TAG", "${WEBHOOK.tag}.$URL_TAG", "${SMTP_ACCOUNT.tag}.$HOST_TAG", "${SMTP_ACCOUNT.tag}.$FROM_ADDRESS_TAG", diff --git a/notifications/notifications/src/main/kotlin/org/opensearch/notifications/metrics/Metrics.kt b/notifications/notifications/src/main/kotlin/org/opensearch/notifications/metrics/Metrics.kt index 91c93178..b27cd353 100644 --- a/notifications/notifications/src/main/kotlin/org/opensearch/notifications/metrics/Metrics.kt +++ b/notifications/notifications/src/main/kotlin/org/opensearch/notifications/metrics/Metrics.kt @@ -185,6 +185,10 @@ enum class Metrics(val metricName: String, val counter: Counter<*>) { "notifications.message_destination.chime", BasicCounter() ), + NOTIFICATIONS_MESSAGE_DESTINATION_MICROSOFT_TEAMS( + "notifications.message_destination.microsoft_teams", + BasicCounter() + ), NOTIFICATIONS_MESSAGE_DESTINATION_WEBHOOK( "notifications.message_destination.webhook", BasicCounter() diff --git a/notifications/notifications/src/main/kotlin/org/opensearch/notifications/resthandler/NotificationConfigRestHandler.kt b/notifications/notifications/src/main/kotlin/org/opensearch/notifications/resthandler/NotificationConfigRestHandler.kt index de8e4a48..e83e797e 100644 --- a/notifications/notifications/src/main/kotlin/org/opensearch/notifications/resthandler/NotificationConfigRestHandler.kt +++ b/notifications/notifications/src/main/kotlin/org/opensearch/notifications/resthandler/NotificationConfigRestHandler.kt @@ -116,6 +116,7 @@ internal class NotificationConfigRestHandler : PluginBaseHandler() { * email_group.recipient_list.recipient=abc,xyz (Text filter field) * slack.url=domain (Text filter field) * chime.url=domain (Text filter field) + * microsoft_teams.url=domain (Text filter field) * webhook.url=domain (Text filter field) * smtp_account.host=domain (Text filter field) * smtp_account.from_address=abc,xyz (Text filter field) diff --git a/notifications/notifications/src/main/kotlin/org/opensearch/notifications/send/SendMessageActionHelper.kt b/notifications/notifications/src/main/kotlin/org/opensearch/notifications/send/SendMessageActionHelper.kt index 19b0f2f8..083c01b0 100644 --- a/notifications/notifications/src/main/kotlin/org/opensearch/notifications/send/SendMessageActionHelper.kt +++ b/notifications/notifications/src/main/kotlin/org/opensearch/notifications/send/SendMessageActionHelper.kt @@ -29,6 +29,7 @@ import org.opensearch.commons.notifications.model.EmailGroup import org.opensearch.commons.notifications.model.EmailRecipientStatus import org.opensearch.commons.notifications.model.EventSource import org.opensearch.commons.notifications.model.EventStatus +import org.opensearch.commons.notifications.model.MicrosoftTeams import org.opensearch.commons.notifications.model.NotificationEvent import org.opensearch.commons.notifications.model.SesAccount import org.opensearch.commons.notifications.model.Slack @@ -49,6 +50,7 @@ import org.opensearch.notifications.spi.model.MessageContent import org.opensearch.notifications.spi.model.destination.BaseDestination import org.opensearch.notifications.spi.model.destination.ChimeDestination import org.opensearch.notifications.spi.model.destination.CustomWebhookDestination +import org.opensearch.notifications.spi.model.destination.MicrosoftTeamsDestination import org.opensearch.notifications.spi.model.destination.SesDestination import org.opensearch.notifications.spi.model.destination.SlackDestination import org.opensearch.notifications.spi.model.destination.SmtpDestination @@ -227,6 +229,7 @@ object SendMessageActionHelper { ConfigType.NONE -> null ConfigType.SLACK -> sendSlackMessage(configData as Slack, message, eventStatus, eventSource.referenceId) ConfigType.CHIME -> sendChimeMessage(configData as Chime, message, eventStatus, eventSource.referenceId) + ConfigType.MICROSOFT_TEAMS -> sendMicrosoftTeamsMessage(configData as MicrosoftTeams, message, eventStatus, eventSource.referenceId) ConfigType.WEBHOOK -> sendWebhookMessage( configData as Webhook, message, @@ -390,6 +393,21 @@ object SendMessageActionHelper { return eventStatus.copy(deliveryStatus = DeliveryStatus(status.statusCode.toString(), status.statusText)) } + /** + * send message to Microsoft Teams destination + */ + private fun sendMicrosoftTeamsMessage( + microsoftTeams: MicrosoftTeams, + message: MessageContent, + eventStatus: EventStatus, + referenceId: String + ): EventStatus { + Metrics.NOTIFICATIONS_MESSAGE_DESTINATION_MICROSOFT_TEAMS.counter.increment() + val destination = MicrosoftTeamsDestination(microsoftTeams.url) + val status = sendMessageThroughSpi(destination, message, referenceId) + return eventStatus.copy(deliveryStatus = DeliveryStatus(status.statusCode.toString(), status.statusText)) + } + /** * send message to custom webhook destination */ @@ -585,7 +603,6 @@ object SendMessageActionHelper { DestinationMessageResponse(RestStatus.FAILED_DEPENDENCY.status, "Failed to send notification") } } - /** * Collects all child configs of the channel configurations (like email) * @param channels list of NotificationConfigDocInfo diff --git a/notifications/notifications/src/main/resources/notifications-config-mapping.yml b/notifications/notifications/src/main/resources/notifications-config-mapping.yml index 133fc28c..073d0f98 100644 --- a/notifications/notifications/src/main/resources/notifications-config-mapping.yml +++ b/notifications/notifications/src/main/resources/notifications-config-mapping.yml @@ -8,7 +8,7 @@ # "dynamic" is set to "false" so that only specified fields are indexed instead of all fields. dynamic: false _meta: - schema_version: 1 + schema_version: 2 properties: metadata: type: object @@ -54,6 +54,14 @@ properties: fields: keyword: type: keyword + microsoft_teams: # Microsoft Teams configuration + type: object + properties: + url: + type: text + fields: + keyword: + type: keyword webhook: # webhook configuration type: object properties: @@ -134,4 +142,4 @@ properties: type: text fields: keyword: - type: keyword + type: keyword \ No newline at end of file diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/IntegTestHelpers.kt b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/IntegTestHelpers.kt index 885b16d4..fefc8a61 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/IntegTestHelpers.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/IntegTestHelpers.kt @@ -121,6 +121,9 @@ fun getCreateNotificationRequestJsonString( ConfigType.CHIME -> """ "chime":{"url":"https://chime.domain.com/sample_chime_url#$randomString"} """.trimIndent() + ConfigType.MICROSOFT_TEAMS -> """ + "microsoft_teams":{"url":"https://microsoftTeams.domain.webhook.office.com/sample_microsoft_teams_url#$randomString"} + """.trimIndent() ConfigType.WEBHOOK -> """ "webhook":{"url":"https://web.domain.com/sample_web_url#$randomString"} """.trimIndent() diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/SecurityNotificationIT.kt b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/SecurityNotificationIT.kt index 504acdb6..e2d89769 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/SecurityNotificationIT.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/SecurityNotificationIT.kt @@ -361,6 +361,7 @@ class SecurityNotificationIT : PluginRestTestCase() { val slackId = createConfig(configType = ConfigType.SLACK) val chimeId = createConfig(configType = ConfigType.CHIME) + val microsoftTeamsId = createConfig(configType = ConfigType.MICROSOFT_TEAMS) val webhookId = createConfig(configType = ConfigType.WEBHOOK) val emailGroupId = createConfig(configType = ConfigType.EMAIL_GROUP) val smtpAccountId = createConfig(configType = ConfigType.SMTP_ACCOUNT) @@ -371,7 +372,7 @@ class SecurityNotificationIT : PluginRestTestCase() { ) Thread.sleep(1000) - val channelIds = setOf(slackId, chimeId, webhookId, emailId) + val channelIds = setOf(slackId, chimeId, microsoftTeamsId, webhookId, emailId) val response = executeRequest( RestRequest.Method.GET.name, "${NotificationPlugin.PLUGIN_BASE_URI}/channels", diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/bwc/NotificationsBackwardsCompatibilityIT.kt b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/bwc/NotificationsBackwardsCompatibilityIT.kt index 5e808c78..6e7eee5f 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/bwc/NotificationsBackwardsCompatibilityIT.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/bwc/NotificationsBackwardsCompatibilityIT.kt @@ -5,6 +5,7 @@ package org.opensearch.integtest.bwc +import org.junit.Assert import org.opensearch.common.settings.Settings import org.opensearch.core.rest.RestStatus import org.opensearch.integtest.PluginRestTestCase @@ -52,6 +53,8 @@ class NotificationsBackwardsCompatibilityIT : PluginRestTestCase() { } ClusterType.UPGRADED -> { verifyConfigsExist(setOf(configId)) + createTestNotificationsConfig(randomAlphaOfLength(10)) + Assert.assertEquals(2, getCurrentMappingsSchemaVersion()) } } break diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/CreateNotificationConfigIT.kt b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/CreateNotificationConfigIT.kt index 50e5baa9..64805e9d 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/CreateNotificationConfigIT.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/CreateNotificationConfigIT.kt @@ -12,6 +12,7 @@ import org.opensearch.client.WarningFailureException import org.opensearch.commons.notifications.model.Chime import org.opensearch.commons.notifications.model.ConfigType import org.opensearch.commons.notifications.model.MethodType +import org.opensearch.commons.notifications.model.MicrosoftTeams import org.opensearch.commons.notifications.model.NotificationConfig import org.opensearch.commons.notifications.model.Slack import org.opensearch.commons.notifications.model.SmtpAccount @@ -19,7 +20,6 @@ import org.opensearch.commons.notifications.model.Webhook import org.opensearch.core.rest.RestStatus import org.opensearch.integtest.PluginRestTestCase import org.opensearch.notifications.NotificationPlugin.Companion.PLUGIN_BASE_URI -import org.opensearch.notifications.index.NotificationConfigIndex import org.opensearch.notifications.verifySingleConfigEquals import org.opensearch.rest.RestRequest @@ -103,6 +103,46 @@ class CreateNotificationConfigIT : PluginRestTestCase() { verifySingleConfigEquals(configId, referenceObject, getConfigResponse) } + fun `test Create microsoft teams notification config with ID`() { + // Create sample config request reference + val configId = "sample_config_id" + val sampleMicrosoftTeams = MicrosoftTeams("https://domain.webhook.office.com/1234567") + val referenceObject = NotificationConfig( + "this is a sample config name", + "this is a sample config description", + ConfigType.MICROSOFT_TEAMS, + isEnabled = true, + configData = sampleMicrosoftTeams + ) + + // Create Microsoft Teams notification config + val createRequestJsonString = """ + { + "config_id":"$configId", + "config":{ + "name":"${referenceObject.name}", + "description":"${referenceObject.description}", + "config_type":"microsoft_teams", + "is_enabled":${referenceObject.isEnabled}, + "microsoft_teams":{"url":"${(referenceObject.configData as MicrosoftTeams).url}"} + } + } + """.trimIndent() + val createdConfigId = createConfigWithRequestJsonString(createRequestJsonString) + Assert.assertEquals(configId, createdConfigId) + Thread.sleep(1000) + + // Get Microsoft Teams notification config + + val getConfigResponse = executeRequest( + RestRequest.Method.GET.name, + "$PLUGIN_BASE_URI/configs/$configId", + "", + RestStatus.OK.status + ) + verifySingleConfigEquals(configId, referenceObject, getConfigResponse) + } + fun `test Create webhook notification config with existing ID fails`() { // Create sample config request reference val sampleWebhook = Webhook("https://domain.com/sample_webhook_url#1234567890") @@ -274,7 +314,7 @@ class CreateNotificationConfigIT : PluginRestTestCase() { Assert.assertEquals(0, getCurrentMappingsSchemaVersion()) createConfig() - Assert.assertEquals(1, getCurrentMappingsSchemaVersion()) + Assert.assertEquals(2, getCurrentMappingsSchemaVersion()) } fun `test _meta field not exists in current mappings`() { @@ -324,13 +364,8 @@ class CreateNotificationConfigIT : PluginRestTestCase() { assert(e is WarningFailureException) } - val getMappingRequest = Request(RestRequest.Method.GET.name, "$indexName/_mappings") - val responseBefore = executeRequest(getMappingRequest, RestStatus.OK.status, client()) - val mappingsObjectBefore = responseBefore.get(indexName).asJsonObject.get("mappings").asJsonObject - Assert.assertNull("mappings should not have _meta field", mappingsObjectBefore.get(NotificationConfigIndex._META)) + Assert.assertEquals(1, getCurrentMappingsSchemaVersion()) createConfig() - val responseAfter = executeRequest(getMappingRequest, RestStatus.OK.status, client()) - val mappingsObjectAfter = responseAfter.get(indexName).asJsonObject.get("mappings").asJsonObject - Assert.assertEquals(mappingsObjectAfter, mappingsObjectBefore) + Assert.assertEquals(2, getCurrentMappingsSchemaVersion()) } } diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/MicrosoftTeamsNotificationConfigCrudIT.kt b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/MicrosoftTeamsNotificationConfigCrudIT.kt new file mode 100644 index 00000000..2707d0c6 --- /dev/null +++ b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/MicrosoftTeamsNotificationConfigCrudIT.kt @@ -0,0 +1,158 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.opensearch.integtest.config + +import org.junit.Assert +import org.opensearch.commons.notifications.model.ConfigType +import org.opensearch.commons.notifications.model.MicrosoftTeams +import org.opensearch.commons.notifications.model.NotificationConfig +import org.opensearch.core.rest.RestStatus +import org.opensearch.integtest.PluginRestTestCase +import org.opensearch.notifications.NotificationPlugin.Companion.PLUGIN_BASE_URI +import org.opensearch.notifications.verifySingleConfigEquals +import org.opensearch.rest.RestRequest + +class MicrosoftTeamsNotificationConfigCrudIT : PluginRestTestCase() { + + fun `test Create, Get, Update, Delete microsoft teams notification config using REST client`() { + // Create sample config request reference + val sampleMicrosoftTeams = MicrosoftTeams("https://domain.webhook.office.com/webhook2/test") + val referenceObject = NotificationConfig( + "this is a sample config name", + "this is a sample config description", + ConfigType.MICROSOFT_TEAMS, + isEnabled = true, + configData = sampleMicrosoftTeams + ) + + // Create Microsoft Teams notification config + val createRequestJsonString = """ + { + "config":{ + "name":"${referenceObject.name}", + "description":"${referenceObject.description}", + "config_type":"microsoft_teams", + "is_enabled":${referenceObject.isEnabled}, + "microsoft_teams":{"url":"${(referenceObject.configData as MicrosoftTeams).url}"} + } + } + """.trimIndent() + val configId = createConfigWithRequestJsonString(createRequestJsonString) + Assert.assertNotNull(configId) + Thread.sleep(1000) + + // Get Microsoft Teams notification config + + val getConfigResponse = executeRequest( + RestRequest.Method.GET.name, + "$PLUGIN_BASE_URI/configs/$configId", + "", + RestStatus.OK.status + ) + verifySingleConfigEquals(configId, referenceObject, getConfigResponse) + Thread.sleep(100) + + // Get all notification config + + val getAllConfigResponse = executeRequest( + RestRequest.Method.GET.name, + "$PLUGIN_BASE_URI/configs", + "", + RestStatus.OK.status + ) + verifySingleConfigEquals(configId, referenceObject, getAllConfigResponse) + Thread.sleep(100) + + // Updated notification config object + val updatedMicrosoftTeams = MicrosoftTeams("https://updated.domain.webhook.office.com/webhook2/test") + val updatedObject = NotificationConfig( + "this is a updated config name", + "this is a updated config description", + ConfigType.MICROSOFT_TEAMS, + isEnabled = true, + configData = updatedMicrosoftTeams + ) + + // Update Microsoft Teams notification config + val updateRequestJsonString = """ + { + "config":{ + "name":"${updatedObject.name}", + "description":"${updatedObject.description}", + "config_type":"microsoft_teams", + "is_enabled":${updatedObject.isEnabled}, + "microsoft_teams":{"url":"${(updatedObject.configData as MicrosoftTeams).url}"} + } + } + """.trimIndent() + val updateResponse = executeRequest( + RestRequest.Method.PUT.name, + "$PLUGIN_BASE_URI/configs/$configId", + updateRequestJsonString, + RestStatus.OK.status + ) + Assert.assertEquals(configId, updateResponse.get("config_id").asString) + Thread.sleep(1000) + + // Get updated Microsoft Teams notification config + + val getUpdatedConfigResponse = executeRequest( + RestRequest.Method.GET.name, + "$PLUGIN_BASE_URI/configs/$configId", + "", + RestStatus.OK.status + ) + verifySingleConfigEquals(configId, updatedObject, getUpdatedConfigResponse) + Thread.sleep(100) + + // Delete Microsoft Teams notification config + val deleteResponse = deleteConfig(configId) + Assert.assertEquals("OK", deleteResponse.get("delete_response_list").asJsonObject.get(configId).asString) + Thread.sleep(1000) + + // Get Microsoft Teams notification config after delete + + executeRequest( + RestRequest.Method.GET.name, + "$PLUGIN_BASE_URI/configs/$configId", + "", + RestStatus.NOT_FOUND.status + ) + Thread.sleep(100) + } + + fun `test Bad Request for multiple config data for microsoft teams using REST Client`() { + // Create sample config request reference + val sampleMicrosoftTeams = MicrosoftTeams("https://domain.webhook.office.com/1234567") + val referenceObject = NotificationConfig( + "this is a sample config name", + "this is a sample config description", + ConfigType.MICROSOFT_TEAMS, + isEnabled = true, + configData = sampleMicrosoftTeams + ) + + // Create Microsoft Teams notification config + val createRequestJsonString = """ + { + "config":{ + "name":"${referenceObject.name}", + "description":"${referenceObject.description}", + "config_type":"microsoft_teams", + "is_enabled":${referenceObject.isEnabled}, + "chime":{"url":"https://dummy.com"} + "microsoft_teams":{"url":"${(referenceObject.configData as MicrosoftTeams).url}"} + } + } + """.trimIndent() + executeRequest( + RestRequest.Method.POST.name, + "$PLUGIN_BASE_URI/configs", + createRequestJsonString, + RestStatus.BAD_REQUEST.status + ) + } +} diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/QueryNotificationConfigIT.kt b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/QueryNotificationConfigIT.kt index a926463d..47efbe32 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/QueryNotificationConfigIT.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/QueryNotificationConfigIT.kt @@ -261,12 +261,13 @@ class QueryNotificationConfigIT : PluginRestTestCase() { fun `test Get sorted notification config using single keyword sort_field(config_type)`() { val slackId = createConfig(configType = ConfigType.SLACK) val chimeId = createConfig(configType = ConfigType.CHIME) + val microsoftTeamsId = createConfig(configType = ConfigType.MICROSOFT_TEAMS) val webhookId = createConfig(configType = ConfigType.WEBHOOK) val emailGroupId = createConfig(configType = ConfigType.EMAIL_GROUP) val smtpAccountId = createConfig(configType = ConfigType.SMTP_ACCOUNT) Thread.sleep(1000) - val sortedConfigIds = listOf(chimeId, emailGroupId, slackId, smtpAccountId, webhookId) + val sortedConfigIds = listOf(chimeId, emailGroupId, microsoftTeamsId, slackId, smtpAccountId, webhookId) // Get all notification configs with default sort_order(asc) val getDefaultOrderConfigResponse = executeRequest( @@ -338,6 +339,7 @@ class QueryNotificationConfigIT : PluginRestTestCase() { fun `test Get filtered notification config using keyword filter_param_list(config_type)`() { val slackId = createConfig(configType = ConfigType.SLACK) val chimeId = createConfig(configType = ConfigType.CHIME) + val microsoftTeamsId = createConfig(configType = ConfigType.MICROSOFT_TEAMS) val webhookId = createConfig(configType = ConfigType.WEBHOOK) val emailGroupId = createConfig(configType = ConfigType.EMAIL_GROUP) val smtpAccountId = createConfig(configType = ConfigType.SMTP_ACCOUNT) @@ -354,13 +356,13 @@ class QueryNotificationConfigIT : PluginRestTestCase() { Thread.sleep(100) // Get notification configs with 2 item type - val getSlackOrChimeResponse = executeRequest( + val getMicrosoftTeamsOrChimeResponse = executeRequest( RestRequest.Method.GET.name, - "$PLUGIN_BASE_URI/configs?config_type=slack,chime", + "$PLUGIN_BASE_URI/configs?config_type=microsoft_teams,chime", "", RestStatus.OK.status ) - verifyMultiConfigIdEquals(setOf(slackId, chimeId), getSlackOrChimeResponse, 2) + verifyMultiConfigIdEquals(setOf(microsoftTeamsId, chimeId), getMicrosoftTeamsOrChimeResponse, 2) Thread.sleep(100) // Get notification configs with 3 item type @@ -547,6 +549,7 @@ class QueryNotificationConfigIT : PluginRestTestCase() { fun `test Get filtered notification config using keyword filter_param_list(internal config fields)`() { val slackId = createConfig(configType = ConfigType.SLACK) val chimeId = createConfig(configType = ConfigType.CHIME) + val microsoftTeamsId = createConfig(configType = ConfigType.MICROSOFT_TEAMS) val webhookId = createConfig(configType = ConfigType.WEBHOOK) val emailGroupId = createConfig(configType = ConfigType.EMAIL_GROUP) val smtpAccountId = createConfig(configType = ConfigType.SMTP_ACCOUNT) @@ -572,6 +575,16 @@ class QueryNotificationConfigIT : PluginRestTestCase() { verifySingleConfigIdEquals(chimeId, getChimeResponse, 1) Thread.sleep(100) + // Get notification configs using microsoft_teams.url + val getMicrosoftTeamsResponse = executeRequest( + RestRequest.Method.GET.name, + "$PLUGIN_BASE_URI/configs?microsoft_teams.url=$microsoftTeamsId", + "", + RestStatus.OK.status + ) + verifySingleConfigIdEquals(microsoftTeamsId, getMicrosoftTeamsResponse, 1) + Thread.sleep(100) + // Get notification configs using webhook.url val getWebhookResponse = executeRequest( RestRequest.Method.GET.name, @@ -606,14 +619,15 @@ class QueryNotificationConfigIT : PluginRestTestCase() { fun `test Get filtered notification config using query`() { val slackId = createConfig(configType = ConfigType.SLACK) val chimeId = createConfig(configType = ConfigType.CHIME) + val microsoftTeamsId = createConfig(configType = ConfigType.MICROSOFT_TEAMS) val webhookId = createConfig(configType = ConfigType.WEBHOOK) val emailGroupId = createConfig(configType = ConfigType.EMAIL_GROUP) val smtpAccountId = createConfig(configType = ConfigType.SMTP_ACCOUNT) - val allIds = setOf(slackId, chimeId, webhookId, emailGroupId, smtpAccountId) - val urlIds = setOf(slackId, chimeId, webhookId) + val allIds = setOf(slackId, chimeId, microsoftTeamsId, webhookId, emailGroupId, smtpAccountId) + val urlIds = setOf(slackId, chimeId, microsoftTeamsId, webhookId) val recipientIds = setOf(emailGroupId) val fromIds = setOf(emailGroupId, smtpAccountId) - val domainIds = setOf(slackId, chimeId, webhookId, smtpAccountId) + val domainIds = setOf(slackId, chimeId, microsoftTeamsId, webhookId, smtpAccountId) Thread.sleep(1000) // Get notification configs using query=slack @@ -680,14 +694,15 @@ class QueryNotificationConfigIT : PluginRestTestCase() { fun `test Get filtered notification config using text_query`() { val slackId = createConfig(configType = ConfigType.SLACK) val chimeId = createConfig(configType = ConfigType.CHIME) + val microsoftTeamsId = createConfig(configType = ConfigType.MICROSOFT_TEAMS) val webhookId = createConfig(configType = ConfigType.WEBHOOK) val emailGroupId = createConfig(configType = ConfigType.EMAIL_GROUP) val smtpAccountId = createConfig(configType = ConfigType.SMTP_ACCOUNT) - val allIds = setOf(slackId, chimeId, webhookId, emailGroupId, smtpAccountId) - val urlIds = setOf(slackId, chimeId, webhookId) + val allIds = setOf(slackId, chimeId, microsoftTeamsId, webhookId, emailGroupId, smtpAccountId) + val urlIds = setOf(slackId, chimeId, microsoftTeamsId, webhookId) val recipientIds = setOf(emailGroupId) val fromIds = setOf(emailGroupId, smtpAccountId) - val domainIds = setOf(slackId, chimeId, webhookId, smtpAccountId) + val domainIds = setOf(slackId, chimeId, microsoftTeamsId, webhookId, smtpAccountId) Thread.sleep(1000) // Get notification configs using text_query=slack should not return any item diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/SlackNotificationConfigCrudIT.kt b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/SlackNotificationConfigCrudIT.kt index 2b51f39a..86c64cf2 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/SlackNotificationConfigCrudIT.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/SlackNotificationConfigCrudIT.kt @@ -144,7 +144,7 @@ class SlackNotificationConfigCrudIT : PluginRestTestCase() { "config_type":"slack", "is_enabled":${referenceObject.isEnabled}, "chime":{"url":"https://dummy.com"} - "slack":{"url":"${(referenceObject.configData as Slack).url}"} + "slack":{"url":"${(referenceObject.configData as Slack).url} } } """.trimIndent() diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/features/GetNotificationChannelListIT.kt b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/features/GetNotificationChannelListIT.kt index 339ea038..283f7556 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/features/GetNotificationChannelListIT.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/features/GetNotificationChannelListIT.kt @@ -35,6 +35,7 @@ class GetNotificationChannelListIT : PluginRestTestCase() { fun `test getChannelList should return only channels`() { val slackId = createConfig(configType = ConfigType.SLACK) val chimeId = createConfig(configType = ConfigType.CHIME) + val microsoftTeamsId = createConfig(configType = ConfigType.MICROSOFT_TEAMS) val webhookId = createConfig(configType = ConfigType.WEBHOOK) val emailGroupId = createConfig(configType = ConfigType.EMAIL_GROUP) val smtpAccountId = createConfig(configType = ConfigType.SMTP_ACCOUNT) @@ -45,7 +46,7 @@ class GetNotificationChannelListIT : PluginRestTestCase() { ) Thread.sleep(1000) - val channelIds = setOf(slackId, chimeId, webhookId, emailId) + val channelIds = setOf(slackId, chimeId, microsoftTeamsId, webhookId, emailId) val response = executeRequest( RestRequest.Method.GET.name, "$PLUGIN_BASE_URI/channels", diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/send/SendTestMessageRestHandlerIT.kt b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/send/SendTestMessageRestHandlerIT.kt index bb1d0949..c36e2666 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/send/SendTestMessageRestHandlerIT.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/send/SendTestMessageRestHandlerIT.kt @@ -46,7 +46,6 @@ internal class SendTestMessageRestHandlerIT : PluginRestTestCase() { val error = sendResponse.get("error").asJsonObject Assert.assertNotNull(error.get("reason").asString) } - @Suppress("EmptyFunctionBlock") fun `test send test slack message`() { // Create webhook notification config @@ -79,6 +78,38 @@ internal class SendTestMessageRestHandlerIT : PluginRestTestCase() { val error = sendResponse.get("error").asJsonObject Assert.assertNotNull(error.get("reason").asString) } + @Suppress("EmptyFunctionBlock") + fun `test send test microsoft teams message`() { + // Create webhook notification config + val createRequestJsonString = """ + { + "config":{ + "name":"this is a sample config name", + "description":"this is a sample config description", + "config_type":"microsoft_teams", + "is_enabled":true, + "microsoft_teams":{ + "url":"https://hooks.webhook.office.com/webhook2/abcde" + } + } + } + """.trimIndent() + val configId = createConfigWithRequestJsonString(createRequestJsonString) + Assert.assertNotNull(configId) + Thread.sleep(1000) + + // send test message + val sendResponse = executeRequest( + RestRequest.Method.POST.name, + "$PLUGIN_BASE_URI/feature/test/$configId", + "", + RestStatus.INTERNAL_SERVER_ERROR.status + ) + + // verify failure response is with message + val error = sendResponse.get("error").asJsonObject + Assert.assertNotNull(error.get("reason").asString) + } @Suppress("EmptyFunctionBlock") fun `test send custom webhook message`() { diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/notifications/ObjectEqualsHelpers.kt b/notifications/notifications/src/test/kotlin/org/opensearch/notifications/ObjectEqualsHelpers.kt index 99b4f2cc..98d7e929 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/notifications/ObjectEqualsHelpers.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/notifications/ObjectEqualsHelpers.kt @@ -14,6 +14,7 @@ import org.opensearch.commons.notifications.model.Email import org.opensearch.commons.notifications.model.EmailGroup import org.opensearch.commons.notifications.model.EmailRecipient import org.opensearch.commons.notifications.model.MethodType +import org.opensearch.commons.notifications.model.MicrosoftTeams import org.opensearch.commons.notifications.model.NotificationConfig import org.opensearch.commons.notifications.model.SesAccount import org.opensearch.commons.notifications.model.Slack @@ -29,6 +30,10 @@ fun verifyEquals(chime: Chime, jsonObject: JsonObject) { Assert.assertEquals(chime.url, jsonObject.get("url").asString) } +fun verifyEquals(microsoftTeams: MicrosoftTeams, jsonObject: JsonObject) { + Assert.assertEquals(microsoftTeams.url, jsonObject.get("url").asString) +} + fun verifyEquals(webhook: Webhook, jsonObject: JsonObject) { Assert.assertEquals(webhook.url, jsonObject.get("url").asString) Assert.assertEquals(webhook.headerParams, Gson().fromJson(jsonObject.get("header_params"), HashMap::class.java)) @@ -83,6 +88,7 @@ fun verifyEquals(config: NotificationConfig, jsonObject: JsonObject) { when (config.configType) { ConfigType.SLACK -> verifyEquals((config.configData as Slack), jsonObject.get("slack").asJsonObject) ConfigType.CHIME -> verifyEquals((config.configData as Chime), jsonObject.get("chime").asJsonObject) + ConfigType.MICROSOFT_TEAMS -> verifyEquals((config.configData as MicrosoftTeams), jsonObject.get("microsoft_teams").asJsonObject) ConfigType.WEBHOOK -> verifyEquals((config.configData as Webhook), jsonObject.get("webhook").asJsonObject) ConfigType.EMAIL -> verifyEquals((config.configData as Email), jsonObject.get("email").asJsonObject) ConfigType.SMTP_ACCOUNT -> verifyEquals( diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/notifications/index/ConfigIndexingActionsTests.kt b/notifications/notifications/src/test/kotlin/org/opensearch/notifications/index/ConfigIndexingActionsTests.kt new file mode 100644 index 00000000..d2c6b0ee --- /dev/null +++ b/notifications/notifications/src/test/kotlin/org/opensearch/notifications/index/ConfigIndexingActionsTests.kt @@ -0,0 +1,45 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ +package org.opensearch.notifications.index + +import org.junit.jupiter.api.BeforeAll +import org.junit.jupiter.api.Test +import org.opensearch.commons.authuser.User +import org.opensearch.commons.notifications.model.MicrosoftTeams +import java.lang.reflect.Method +import kotlin.test.assertFails + +class ConfigIndexingActionsTests { + + @Test + fun `test validate microsoft teams`() { + val user = User() + var microsoftTeams = MicrosoftTeams("https://abcdefg.webhook.office.com/webhookb2/12345567abcdefg") + validateMicrosoftTeamsConfig.invoke(ConfigIndexingActions, microsoftTeams, user) + microsoftTeams = MicrosoftTeams("https://abcde.efg.webhook.office.com/webhookb2/12345567abcdefg") + validateMicrosoftTeamsConfig.invoke(ConfigIndexingActions, microsoftTeams, user) + microsoftTeams = MicrosoftTeams("http://abcdefg.webhook.office.com/webhookb2/12345567abcdefg") + assertFails { validateMicrosoftTeamsConfig.invoke(ConfigIndexingActions, microsoftTeams, user) } + microsoftTeams = MicrosoftTeams("https://abcdefg.webhook.abc.com/webhookb2/12345567abcdefg") + assertFails { validateMicrosoftTeamsConfig.invoke(ConfigIndexingActions, microsoftTeams, user) } + microsoftTeams = MicrosoftTeams("https://abcdefg.abc.com") + assertFails { validateMicrosoftTeamsConfig.invoke(ConfigIndexingActions, microsoftTeams, user) } + } + + companion object { + private lateinit var validateMicrosoftTeamsConfig: Method + + @BeforeAll + @JvmStatic + fun initialize() { + /* use reflection to get private method */ + validateMicrosoftTeamsConfig = ConfigIndexingActions::class.java.getDeclaredMethod( + "validateMicrosoftTeamsConfig", MicrosoftTeams::class.java, User::class.java + ) + + validateMicrosoftTeamsConfig.isAccessible = true + } + } +} From fbad72202a0b12a79dc75d16ac0f6783e7c9dd90 Mon Sep 17 00:00:00 2001 From: zhichao-aws Date: Tue, 29 Aug 2023 17:54:00 +0800 Subject: [PATCH 02/28] Add microsoft teams validation error message (#746) * add validation failure message for Microsoft Teams Signed-off-by: zhichao-aws * modify integtest Signed-off-by: zhichao-aws --------- Signed-off-by: zhichao-aws Signed-off-by: Aniruddh --- .../index/ConfigIndexingActions.kt | 4 +- .../MicrosoftTeamsNotificationConfigCrudIT.kt | 43 ++++++++++++++++++- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/notifications/notifications/src/main/kotlin/org/opensearch/notifications/index/ConfigIndexingActions.kt b/notifications/notifications/src/main/kotlin/org/opensearch/notifications/index/ConfigIndexingActions.kt index 741f8e79..2ef5b93a 100644 --- a/notifications/notifications/src/main/kotlin/org/opensearch/notifications/index/ConfigIndexingActions.kt +++ b/notifications/notifications/src/main/kotlin/org/opensearch/notifications/index/ConfigIndexingActions.kt @@ -65,7 +65,9 @@ object ConfigIndexingActions { } private fun validateMicrosoftTeamsConfig(microsoftTeams: MicrosoftTeams, user: User?) { - require(microsoftTeams.url.contains(Regex("https://.*\\.webhook\\.office\\.com"))) + require(microsoftTeams.url.contains(Regex("https://.*\\.webhook\\.office\\.com"))) { + "Wrong Microsoft Teams url. Should contain \"webhook.office.com\"" + } } @Suppress("UnusedPrivateMember") diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/MicrosoftTeamsNotificationConfigCrudIT.kt b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/MicrosoftTeamsNotificationConfigCrudIT.kt index 2707d0c6..f830ece4 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/MicrosoftTeamsNotificationConfigCrudIT.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/MicrosoftTeamsNotificationConfigCrudIT.kt @@ -6,11 +6,16 @@ package org.opensearch.integtest.config import org.junit.Assert +import org.opensearch.client.Request +import org.opensearch.client.RequestOptions +import org.opensearch.client.ResponseException import org.opensearch.commons.notifications.model.ConfigType import org.opensearch.commons.notifications.model.MicrosoftTeams import org.opensearch.commons.notifications.model.NotificationConfig import org.opensearch.core.rest.RestStatus import org.opensearch.integtest.PluginRestTestCase +import org.opensearch.integtest.getResponseBody +import org.opensearch.integtest.jsonify import org.opensearch.notifications.NotificationPlugin.Companion.PLUGIN_BASE_URI import org.opensearch.notifications.verifySingleConfigEquals import org.opensearch.rest.RestRequest @@ -124,6 +129,42 @@ class MicrosoftTeamsNotificationConfigCrudIT : PluginRestTestCase() { Thread.sleep(100) } + fun `test create config with wrong Microsoft Teams url and get error text`() { + val sampleMicrosoftTeams = MicrosoftTeams("https://domain.office.com/1234567") + val referenceObject = NotificationConfig( + "this is a sample config name", + "this is a sample config description", + ConfigType.MICROSOFT_TEAMS, + isEnabled = true, + configData = sampleMicrosoftTeams + ) + val createRequestJsonString = """ + { + "config":{ + "name":"${referenceObject.name}", + "description":"${referenceObject.description}", + "config_type":"microsoft_teams", + "is_enabled":${referenceObject.isEnabled}, + "microsoft_teams":{"url":"${(referenceObject.configData as MicrosoftTeams).url}"} + } + } + """.trimIndent() + val response = try { + val request = Request(RestRequest.Method.POST.name, "$PLUGIN_BASE_URI/configs") + request.setJsonEntity(createRequestJsonString) + val restOptionsBuilder = RequestOptions.DEFAULT.toBuilder() + restOptionsBuilder.addHeader("Content-Type", "application/json") + request.setOptions(restOptionsBuilder) + client().performRequest(request) + fail("Expected wrong Microsoft Teams URL.") + } catch (exception: ResponseException) { + Assert.assertEquals( + "Wrong Microsoft Teams url. Should contain \"webhook.office.com\"", + jsonify(getResponseBody(exception.response))["error"].asJsonObject["reason"].asString + ) + } + } + fun `test Bad Request for multiple config data for microsoft teams using REST Client`() { // Create sample config request reference val sampleMicrosoftTeams = MicrosoftTeams("https://domain.webhook.office.com/1234567") @@ -143,7 +184,7 @@ class MicrosoftTeamsNotificationConfigCrudIT : PluginRestTestCase() { "description":"${referenceObject.description}", "config_type":"microsoft_teams", "is_enabled":${referenceObject.isEnabled}, - "chime":{"url":"https://dummy.com"} + "chime":{"url":"https://dummy.com"}, "microsoft_teams":{"url":"${(referenceObject.configData as MicrosoftTeams).url}"} } } From dc36ba6185055dc3f9d24e6a3ffe08b6d72af32a Mon Sep 17 00:00:00 2001 From: Hailong Cui Date: Wed, 30 Aug 2023 17:02:26 +0800 Subject: [PATCH 03/28] onboard system and hidden index (#742) Signed-off-by: Hailong Cui Signed-off-by: Aniruddh --- .../opensearch/notifications/NotificationPlugin.kt | 13 ++++++++++++- .../notifications/index/NotificationConfigIndex.kt | 2 +- .../resources/notifications-config-settings.yml | 1 + 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/notifications/notifications/src/main/kotlin/org/opensearch/notifications/NotificationPlugin.kt b/notifications/notifications/src/main/kotlin/org/opensearch/notifications/NotificationPlugin.kt index 2ac0ebae..e15aa7d8 100644 --- a/notifications/notifications/src/main/kotlin/org/opensearch/notifications/NotificationPlugin.kt +++ b/notifications/notifications/src/main/kotlin/org/opensearch/notifications/NotificationPlugin.kt @@ -22,6 +22,7 @@ import org.opensearch.core.common.io.stream.NamedWriteableRegistry import org.opensearch.core.xcontent.NamedXContentRegistry import org.opensearch.env.Environment import org.opensearch.env.NodeEnvironment +import org.opensearch.indices.SystemIndexDescriptor import org.opensearch.notifications.action.CreateNotificationConfigAction import org.opensearch.notifications.action.DeleteNotificationConfigAction import org.opensearch.notifications.action.GetChannelListAction @@ -44,6 +45,7 @@ import org.opensearch.notifications.spi.NotificationCore import org.opensearch.notifications.spi.NotificationCoreExtension import org.opensearch.plugins.ActionPlugin import org.opensearch.plugins.Plugin +import org.opensearch.plugins.SystemIndexPlugin import org.opensearch.repositories.RepositoriesService import org.opensearch.rest.RestController import org.opensearch.rest.RestHandler @@ -56,7 +58,7 @@ import java.util.function.Supplier * Entry point of the OpenSearch Notifications plugin * This class initializes the rest handlers. */ -class NotificationPlugin : ActionPlugin, Plugin(), NotificationCoreExtension { +class NotificationPlugin : ActionPlugin, Plugin(), NotificationCoreExtension, SystemIndexPlugin { lateinit var clusterService: ClusterService // initialized in createComponents() @@ -80,6 +82,15 @@ class NotificationPlugin : ActionPlugin, Plugin(), NotificationCoreExtension { return PluginSettings.getAllSettings() } + override fun getSystemIndexDescriptors(settings: Settings?): Collection { + return listOf( + SystemIndexDescriptor( + NotificationConfigIndex.INDEX_NAME, + "System index for storing notification channels related configurations." + ) + ) + } + /** * {@inheritDoc} */ diff --git a/notifications/notifications/src/main/kotlin/org/opensearch/notifications/index/NotificationConfigIndex.kt b/notifications/notifications/src/main/kotlin/org/opensearch/notifications/index/NotificationConfigIndex.kt index c166a014..bc63de0e 100644 --- a/notifications/notifications/src/main/kotlin/org/opensearch/notifications/index/NotificationConfigIndex.kt +++ b/notifications/notifications/src/main/kotlin/org/opensearch/notifications/index/NotificationConfigIndex.kt @@ -67,7 +67,7 @@ internal object NotificationConfigIndex : ConfigOperations { const val SCHEMA_VERSION = "schema_version" private val log by logger(NotificationConfigIndex::class.java) - private const val INDEX_NAME = ".opensearch-notifications-config" + const val INDEX_NAME = ".opensearch-notifications-config" private const val MAPPING_FILE_NAME = "notifications-config-mapping.yml" private const val SETTINGS_FILE_NAME = "notifications-config-settings.yml" diff --git a/notifications/notifications/src/main/resources/notifications-config-settings.yml b/notifications/notifications/src/main/resources/notifications-config-settings.yml index 569523b1..1a2fa70a 100644 --- a/notifications/notifications/src/main/resources/notifications-config-settings.yml +++ b/notifications/notifications/src/main/resources/notifications-config-settings.yml @@ -8,3 +8,4 @@ index: number_of_shards: "1" # The data size is not expected to be big so keeping it 1 shard auto_expand_replicas: "0-2" + hidden: true \ No newline at end of file From 344a172b117e429614e58a725b70b992b19de575 Mon Sep 17 00:00:00 2001 From: Darshit Chanpura <35282393+DarshitChanpura@users.noreply.github.com> Date: Wed, 6 Sep 2023 21:50:18 -0400 Subject: [PATCH 04/28] Updates demo certs used in integ tests (#756) Signed-off-by: Darshit Chanpura Signed-off-by: Aniruddh --- .../test/resources/security/esnode-key.pem | 52 +++++++++--------- .../src/test/resources/security/esnode.pem | 49 ++++++++--------- .../src/test/resources/security/kirk-key.pem | 52 +++++++++--------- .../src/test/resources/security/kirk.pem | 49 +++++++++-------- .../src/test/resources/security/root-ca.pem | 48 ++++++++-------- .../src/test/resources/security/sample.pem | 51 ++++++++--------- .../src/test/resources/security/test-kirk.jks | Bin 3874 -> 4504 bytes 7 files changed, 150 insertions(+), 151 deletions(-) diff --git a/notifications/notifications/src/test/resources/security/esnode-key.pem b/notifications/notifications/src/test/resources/security/esnode-key.pem index 4ac2cb57..567f85c9 100644 --- a/notifications/notifications/src/test/resources/security/esnode-key.pem +++ b/notifications/notifications/src/test/resources/security/esnode-key.pem @@ -1,28 +1,28 @@ -----BEGIN PRIVATE KEY----- -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCWvn+O+rywfgMC -ud24mAclMDfuNA/IzCKLxl5usIE/PvUm7PPfXQ14LfQhNQXqOuaD9fiVM+HO1BzK -wmN3j4g7eHInR1cxENoNGKFa0Fr9EXnUv8sfwyobPD8NTu9eaH7T+d6f9oow+Q4n -xb9Xin5IRR/pcJ8v7zEjcXpZaZejcSU4iVZ0PR2Di4H9rfe9SEyR5wLrsVBePB3L -jaL1uK4bZF3n/JGgDe3BNy1PgPU+O+FCzQipBBTyJWQCjd4iTRXVbMa01PglAR85 -O9w6NXApBLyWdGRY6dGd8vMC2P4KlhnxlcgPZdglKniGTX+eTzT7Rszq77zjYrou -PLwSh9S7AgMBAAECggEABwiohxFoEIwws8XcdKqTWsbfNTw0qFfuHLuK2Htf7IWR -htlzn66F3F+4jnwc5IsPCoVFriCXnsEC/usHHSMTZkL+gJqxlNaGdin6DXS/aiOQ -nb69SaQfqNmsz4ApZyxVDqsQGkK0vAhDAtQVU45gyhp/nLLmmqP8lPzMirOEodmp -U9bA8t/ttrzng7SVAER42f6IVpW0iTKTLyFii0WZbq+ObViyqib9hVFrI6NJuQS+ -IelcZB0KsSi6rqIjXg1XXyMiIUcSlhq+GfEa18AYgmsbPwMbExate7/8Ci7ZtCbh -lx9bves2+eeqq5EMm3sMHyhdcg61yzd5UYXeZhwJkQKBgQDS9YqrAtztvLY2gMgv -d+wOjb9awWxYbQTBjx33kf66W+pJ+2j8bI/XX2CpZ98w/oq8VhMqbr9j5b8MfsrF -EoQvedA4joUo8sXd4j1mR2qKF4/KLmkgy6YYusNP2UrVSw7sh77bzce+YaVVoO/e -0wIVTHuD/QZ6fG6MasOqcbl6hwKBgQC27cQruaHFEXR/16LrMVAX+HyEEv44KOCZ -ij5OE4P7F0twb+okngG26+OJV3BtqXf0ULlXJ+YGwXCRf6zUZkld3NMy3bbKPgH6 -H/nf3BxqS2tudj7+DV52jKtisBghdvtlKs56oc9AAuwOs37DvhptBKUPdzDDqfys -Qchv5JQdLQKBgERev+pcqy2Bk6xmYHrB6wdseS/4sByYeIoi0BuEfYH4eB4yFPx6 -UsQCbVl6CKPgWyZe3ydJbU37D8gE78KfFagtWoZ56j4zMF2RDUUwsB7BNCDamce/ -OL2bCeG/Erm98cBG3lxufOX+z47I8fTNfkdY2k8UmhzoZwurLm73HJ3RAoGBAKsp -6yamuXF2FbYRhUXgjHsBbTD/vJO72/yO2CGiLRpi/5mjfkjo99269trp0C8sJSub -5PBiSuADXFsoRgUv+HI1UAEGaCTwxFTQWrRWdtgW3d0sE2EQDVWL5kmfT9TwSeat -mSoyAYR5t3tCBNkPJhbgA7pm4mASzHQ50VyxWs25AoGBAKPFx9X2oKhYQa+mW541 -bbqRuGFMoXIIcr/aeM3LayfLETi48o5NDr2NDP11j4yYuz26YLH0Dj8aKpWuehuH -uB27n6j6qu0SVhQi6mMJBe1JrKbzhqMKQjYOoy8VsC2gdj5pCUP/kLQPW7zm9diX -CiKTtKgPIeYdigor7V3AHcVT +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCm93kXteDQHMAv +bUPNPW5pyRHKDD42XGWSgq0k1D29C/UdyL21HLzTJa49ZU2ldIkSKs9JqbkHdyK0 +o8MO6L8dotLoYbxDWbJFW8bp1w6tDTU0HGkn47XVu3EwbfrTENg3jFu+Oem6a/50 +1SzITzJWtS0cn2dIFOBimTVpT/4Zv5qrXA6Cp4biOmoTYWhi/qQl8d0IaADiqoZ1 +MvZbZ6x76qTrRAbg+UWkpTEXoH1xTc8ndibR7+HP6OTqCKvo1NhE8uP4pY+fWd6b +6l+KLo3IKpfTbAIJXIO+M67FLtWKtttDao94B069skzKk6FPgW/OZh6PRCD0oxOa +vV+ld2SjAgMBAAECggEAQK1+uAOZeaSZggW2jQut+MaN4JHLi61RH2cFgU3COLgo +FIiNjFn8f2KKU3gpkt1It8PjlmprpYut4wHI7r6UQfuv7ZrmncRiPWHm9PB82+ZQ +5MXYqj4YUxoQJ62Cyz4sM6BobZDrjG6HHGTzuwiKvHHkbsEE9jQ4E5m7yfbVvM0O +zvwrSOM1tkZihKSTpR0j2+taji914tjBssbn12TMZQL5ItGnhR3luY8mEwT9MNkZ +xg0VcREoAH+pu9FE0vPUgLVzhJ3be7qZTTSRqv08bmW+y1plu80GbppePcgYhEow +dlW4l6XPJaHVSn1lSFHE6QAx6sqiAnBz0NoTPIaLyQKBgQDZqDOlhCRciMRicSXn +7yid9rhEmdMkySJHTVFOidFWwlBcp0fGxxn8UNSBcXdSy7GLlUtH41W9PWl8tp9U +hQiiXORxOJ7ZcB80uNKXF01hpPj2DpFPWyHFxpDkWiTAYpZl68rOlYujxZUjJIej +VvcykBC2BlEOG9uZv2kxcqLyJwKBgQDEYULTxaTuLIa17wU3nAhaainKB3vHxw9B +Ksy5p3ND43UNEKkQm7K/WENx0q47TA1mKD9i+BhaLod98mu0YZ+BCUNgWKcBHK8c +uXpauvM/pLhFLXZ2jvEJVpFY3J79FSRK8bwE9RgKfVKMMgEk4zOyZowS8WScOqiy +hnQn1vKTJQKBgElhYuAnl9a2qXcC7KOwRsJS3rcKIVxijzL4xzOyVShp5IwIPbOv +hnxBiBOH/JGmaNpFYBcBdvORE9JfA4KMQ2fx53agfzWRjoPI1/7mdUk5RFI4gRb/ +A3jZRBoopgFSe6ArCbnyQxzYzToG48/Wzwp19ZxYrtUR4UyJct6f5n27AoGBAJDh +KIpQQDOvCdtjcbfrF4aM2DPCfaGPzENJriwxy6oEPzDaX8Bu/dqI5Ykt43i/zQrX +GpyLaHvv4+oZVTiI5UIvcVO9U8hQPyiz9f7F+fu0LHZs6f7hyhYXlbe3XFxeop3f +5dTKdWgXuTTRF2L9dABkA2deS9mutRKwezWBMQk5AoGBALPtX0FrT1zIosibmlud +tu49A/0KZu4PBjrFMYTSEWGNJez3Fb2VsJwylVl6HivwbP61FhlYfyksCzQQFU71 ++x7Nmybp7PmpEBECr3deoZKQ/acNHn0iwb0It+YqV5+TquQebqgwK6WCLsMuiYKT +bg/ch9Rhxbq22yrVgWHh6epp -----END PRIVATE KEY----- diff --git a/notifications/notifications/src/test/resources/security/esnode.pem b/notifications/notifications/src/test/resources/security/esnode.pem index 7ba92534..a1fc20a7 100644 --- a/notifications/notifications/src/test/resources/security/esnode.pem +++ b/notifications/notifications/src/test/resources/security/esnode.pem @@ -1,28 +1,25 @@ -----BEGIN CERTIFICATE----- -MIIEyTCCA7GgAwIBAgIGAWLrc1O2MA0GCSqGSIb3DQEBCwUAMIGPMRMwEQYKCZIm -iZPyLGQBGRYDY29tMRcwFQYKCZImiZPyLGQBGRYHZXhhbXBsZTEZMBcGA1UECgwQ -RXhhbXBsZSBDb20gSW5jLjEhMB8GA1UECwwYRXhhbXBsZSBDb20gSW5jLiBSb290 -IENBMSEwHwYDVQQDDBhFeGFtcGxlIENvbSBJbmMuIFJvb3QgQ0EwHhcNMTgwNDIy -MDM0MzQ3WhcNMjgwNDE5MDM0MzQ3WjBeMRIwEAYKCZImiZPyLGQBGRYCZGUxDTAL -BgNVBAcMBHRlc3QxDTALBgNVBAoMBG5vZGUxDTALBgNVBAsMBG5vZGUxGzAZBgNV -BAMMEm5vZGUtMC5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC -AQoCggEBAJa+f476vLB+AwK53biYByUwN+40D8jMIovGXm6wgT8+9Sbs899dDXgt -9CE1Beo65oP1+JUz4c7UHMrCY3ePiDt4cidHVzEQ2g0YoVrQWv0RedS/yx/DKhs8 -Pw1O715oftP53p/2ijD5DifFv1eKfkhFH+lwny/vMSNxellpl6NxJTiJVnQ9HYOL -gf2t971ITJHnAuuxUF48HcuNovW4rhtkXef8kaAN7cE3LU+A9T474ULNCKkEFPIl -ZAKN3iJNFdVsxrTU+CUBHzk73Do1cCkEvJZ0ZFjp0Z3y8wLY/gqWGfGVyA9l2CUq -eIZNf55PNPtGzOrvvONiui48vBKH1LsCAwEAAaOCAVkwggFVMIG8BgNVHSMEgbQw -gbGAFJI1DOAPHitF9k0583tfouYSl0BzoYGVpIGSMIGPMRMwEQYKCZImiZPyLGQB -GRYDY29tMRcwFQYKCZImiZPyLGQBGRYHZXhhbXBsZTEZMBcGA1UECgwQRXhhbXBs -ZSBDb20gSW5jLjEhMB8GA1UECwwYRXhhbXBsZSBDb20gSW5jLiBSb290IENBMSEw -HwYDVQQDDBhFeGFtcGxlIENvbSBJbmMuIFJvb3QgQ0GCAQEwHQYDVR0OBBYEFKyv -78ZmFjVKM9g7pMConYH7FVBHMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgXg -MCAGA1UdJQEB/wQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjA1BgNVHREELjAsiAUq -AwQFBYISbm9kZS0wLmV4YW1wbGUuY29tgglsb2NhbGhvc3SHBH8AAAEwDQYJKoZI -hvcNAQELBQADggEBAIOKuyXsFfGv1hI/Lkpd/73QNqjqJdxQclX57GOMWNbOM5H0 -5/9AOIZ5JQsWULNKN77aHjLRr4owq2jGbpc/Z6kAd+eiatkcpnbtbGrhKpOtoEZy -8KuslwkeixpzLDNISSbkeLpXz4xJI1ETMN/VG8ZZP1bjzlHziHHDu0JNZ6TnNzKr -XzCGMCohFfem8vnKNnKUneMQMvXd3rzUaAgvtf7Hc2LTBlf4fZzZF1EkwdSXhaMA -1lkfHiqOBxtgeDLxCHESZ2fqgVqsWX+t3qHQfivcPW6txtDyrFPRdJOGhiMGzT/t -e/9kkAtQRgpTb3skYdIOOUOV0WGQ60kJlFhAzIs= +MIIEPDCCAySgAwIBAgIUZjrlDPP8azRDPZchA/XEsx0X2iIwDQYJKoZIhvcNAQEL +BQAwgY8xEzARBgoJkiaJk/IsZAEZFgNjb20xFzAVBgoJkiaJk/IsZAEZFgdleGFt +cGxlMRkwFwYDVQQKDBBFeGFtcGxlIENvbSBJbmMuMSEwHwYDVQQLDBhFeGFtcGxl +IENvbSBJbmMuIFJvb3QgQ0ExITAfBgNVBAMMGEV4YW1wbGUgQ29tIEluYy4gUm9v +dCBDQTAeFw0yMzA4MjkwNDIzMTJaFw0zMzA4MjYwNDIzMTJaMFcxCzAJBgNVBAYT +AmRlMQ0wCwYDVQQHDAR0ZXN0MQ0wCwYDVQQKDARub2RlMQ0wCwYDVQQLDARub2Rl +MRswGQYDVQQDDBJub2RlLTAuZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUA +A4IBDwAwggEKAoIBAQCm93kXteDQHMAvbUPNPW5pyRHKDD42XGWSgq0k1D29C/Ud +yL21HLzTJa49ZU2ldIkSKs9JqbkHdyK0o8MO6L8dotLoYbxDWbJFW8bp1w6tDTU0 +HGkn47XVu3EwbfrTENg3jFu+Oem6a/501SzITzJWtS0cn2dIFOBimTVpT/4Zv5qr +XA6Cp4biOmoTYWhi/qQl8d0IaADiqoZ1MvZbZ6x76qTrRAbg+UWkpTEXoH1xTc8n +dibR7+HP6OTqCKvo1NhE8uP4pY+fWd6b6l+KLo3IKpfTbAIJXIO+M67FLtWKtttD +ao94B069skzKk6FPgW/OZh6PRCD0oxOavV+ld2SjAgMBAAGjgcYwgcMwRwYDVR0R +BEAwPogFKgMEBQWCEm5vZGUtMC5leGFtcGxlLmNvbYIJbG9jYWxob3N0hxAAAAAA +AAAAAAAAAAAAAAABhwR/AAABMAsGA1UdDwQEAwIF4DAdBgNVHSUEFjAUBggrBgEF +BQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU0/qDQaY10jIo +wCjLUpz/HfQXyt8wHwYDVR0jBBgwFoAUF4ffoFrrZhKn1dD4uhJFPLcrAJwwDQYJ +KoZIhvcNAQELBQADggEBAD2hkndVih6TWxoe/oOW0i2Bq7ScNO/n7/yHWL04HJmR +MaHv/Xjc8zLFLgHuHaRvC02ikWIJyQf5xJt0Oqu2GVbqXH9PBGKuEP2kCsRRyU27 +zTclAzfQhqmKBTYQ/3lJ3GhRQvXIdYTe+t4aq78TCawp1nSN+vdH/1geG6QjMn5N +1FU8tovDd4x8Ib/0dv8RJx+n9gytI8n/giIaDCEbfLLpe4EkV5e5UNpOnRgJjjuy +vtZutc81TQnzBtkS9XuulovDE0qI+jQrKkKu8xgGLhgH0zxnPkKtUg2I3Aq6zl1L +zYkEOUF8Y25J6WeY88Yfnc0iigI+Pnz5NK8R9GL7TYo= -----END CERTIFICATE----- diff --git a/notifications/notifications/src/test/resources/security/kirk-key.pem b/notifications/notifications/src/test/resources/security/kirk-key.pem index bacb22c2..fd1728cd 100644 --- a/notifications/notifications/src/test/resources/security/kirk-key.pem +++ b/notifications/notifications/src/test/resources/security/kirk-key.pem @@ -1,28 +1,28 @@ -----BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDCwgBOoO88uMM8 -dREJsk58Yt4Jn0zwQ2wUThbvy3ICDiEWhiAhUbg6dTggpS5vWWJto9bvaaqgMVoh -ElfYHdTDncX3UQNBEP8tqzHON6BFEFSGgJRGLd6f5dri6rK32nCotYS61CFXBFxf -WumXjSukjyrcTsdkR3C5QDo2oN7F883MOQqRENPzAtZi9s3jNX48u+/e3yvJzXsB -GS9Qmsye6C71enbIujM4CVwDT/7a5jHuaUp6OuNCFbdRPnu/wLYwOS2/yOtzAqk7 -/PFnPCe7YOa10ShnV/jx2sAHhp7ZQBJgFkkgnIERz9Ws74Au+EbptWnsWuB+LqRL -x5G02IzpAgMBAAECggEAEzwnMkeBbqqDgyRqFbO/PgMNvD7i0b/28V0dCtCPEVY6 -klzrg3RCERP5V9AN8VVkppYjPkCzZ2A4b0JpMUu7ncOmr7HCnoSCj2IfEyePSVg+ -4OHbbcBOAoDTHiI2myM/M9++8izNS34qGV4t6pfjaDyeQQ/5cBVWNBWnKjS34S5H -rJWpAcDgxYk5/ah2Xs2aULZlXDMxbSikjrv+n4JIYTKFQo8ydzL8HQDBRmXAFLjC -gNOSHf+5u1JdpY3uPIxK1ugVf8zPZ4/OEB23j56uu7c8+sZ+kZwfRWAQmMhFVG/y -OXxoT5mOruBsAw29m2Ijtxg252/YzSTxiDqFziB/eQKBgQDjeVAdi55GW/bvhuqn -xME/An8E3hI/FyaaITrMQJUBjiCUaStTEqUgQ6A7ZfY/VX6qafOX7sli1svihrXC -uelmKrdve/CFEEqzX9JWWRiPiQ0VZD+EQRsJvX85Tw2UGvVUh6dO3UGPS0BhplMD -jeVpyXgZ7Gy5we+DWjfwhYrCmwKBgQDbLmQhRy+IdVljObZmv3QtJ0cyxxZETWzU -MKmgBFvcRw+KvNwO+Iy0CHEbDu06Uj63kzI2bK3QdINaSrjgr8iftXIQpBmcgMF+ -a1l5HtHlCp6RWd55nWQOEvn36IGN3cAaQkXuh4UYM7QfEJaAbzJhyJ+wXA3jWqUd -8bDTIAZ0ywKBgFuZ44gyTAc7S2JDa0Up90O/ZpT4NFLRqMrSbNIJg7d/m2EIRNkM -HhCzCthAg/wXGo3XYq+hCdnSc4ICCzmiEfoBY6LyPvXmjJ5VDOeWs0xBvVIK74T7 -jr7KX2wdiHNGs9pZUidw89CXVhK8nptEzcheyA1wZowbK68yamph7HHXAoGBAK3x -7D9Iyl1mnDEWPT7f1Gh9UpDm1TIRrDvd/tBihTCVKK13YsFy2d+LD5Bk0TpGyUVR -STlOGMdloFUJFh4jA3pUOpkgUr8Uo/sbYN+x6Ov3+I3sH5aupRhSURVA7YhUIz/z -tqIt5R+m8Nzygi6dkQNvf+Qruk3jw0S3ahizwsvvAoGAL7do6dTLp832wFVxkEf4 -gg1M6DswfkgML5V/7GQ3MkIX/Hrmiu+qSuHhDGrp9inZdCDDYg5+uy1+2+RBMRZ3 -vDUUacvc4Fep05zp7NcjgU5y+/HWpuKVvLIlZAO1MBY4Xinqqii6RdxukIhxw7eT -C6TPL5KAcV1R/XAihDhI18Y= +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCVXDgEJQorgfXp +gpY0TgF55bD2xuzxN5Dc9rDfgWxrsOvOloMpd7k6FR71bKWjJi1KptSmM/cDElky +AWYKSfYWGiGxsQ+EQW+6kwCfEOHXQldn+0+JcWqP+osSPjtJfwRvRN5kRqP69MPo +7U0N2kdqenqMWjmG1chDGLRSOEGU5HIBiDxsZtOcvMaJ8b1eaW0lvS+6gFQ80AvB +GBkDDCOHHLtDXBylrZk2CQP8AzxNicIZ4B8G3CG3OHA8+nBtEtxZoIihrrkqlMt+ +b/5N8u8zB0Encew0kdrc4R/2wS//ahr6U+9Siq8T7WsUtGwKj3BJClg6OyDJRhlu +y2gFnxoPAgMBAAECggEAP5TOycDkx+megAWVoHV2fmgvgZXkBrlzQwUG/VZQi7V4 +ZGzBMBVltdqI38wc5MtbK3TCgHANnnKgor9iq02Z4wXDwytPIiti/ycV9CDRKvv0 +TnD2hllQFjN/IUh5n4thHWbRTxmdM7cfcNgX3aZGkYbLBVVhOMtn4VwyYu/Mxy8j +xClZT2xKOHkxqwmWPmdDTbAeZIbSv7RkIGfrKuQyUGUaWhrPslvYzFkYZ0umaDgQ +OAthZew5Bz3OfUGOMPLH61SVPuJZh9zN1hTWOvT65WFWfsPd2yStI+WD/5PU1Doo +1RyeHJO7s3ug8JPbtNJmaJwHe9nXBb/HXFdqb976yQKBgQDNYhpu+MYSYupaYqjs +9YFmHQNKpNZqgZ4ceRFZ6cMJoqpI5dpEMqToFH7tpor72Lturct2U9nc2WR0HeEs +/6tiptyMPTFEiMFb1opQlXF2ae7LeJllntDGN0Q6vxKnQV+7VMcXA0Y8F7tvGDy3 +qJu5lfvB1mNM2I6y/eMxjBuQhwKBgQC6K41DXMFro0UnoO879pOQYMydCErJRmjG +/tZSy3Wj4KA/QJsDSViwGfvdPuHZRaG9WtxdL6kn0w1exM9Rb0bBKl36lvi7o7xv +M+Lw9eyXMkww8/F5d7YYH77gIhGo+RITkKI3+5BxeBaUnrGvmHrpmpgRXWmINqr0 +0jsnN3u0OQKBgCf45vIgItSjQb8zonLz2SpZjTFy4XQ7I92gxnq8X0Q5z3B+o7tQ +K/4rNwTju/sGFHyXAJlX+nfcK4vZ4OBUJjP+C8CTjEotX4yTNbo3S6zjMyGQqDI5 +9aIOUY4pb+TzeUFJX7If5gR+DfGyQubvvtcg1K3GHu9u2l8FwLj87sRzAoGAflQF +RHuRiG+/AngTPnZAhc0Zq0kwLkpH2Rid6IrFZhGLy8AUL/O6aa0IGoaMDLpSWUJp +nBY2S57MSM11/MVslrEgGmYNnI4r1K25xlaqV6K6ztEJv6n69327MS4NG8L/gCU5 +3pEm38hkUi8pVYU7in7rx4TCkrq94OkzWJYurAkCgYATQCL/rJLQAlJIGulp8s6h +mQGwy8vIqMjAdHGLrCS35sVYBXG13knS52LJHvbVee39AbD5/LlWvjJGlQMzCLrw +F7oILW5kXxhb8S73GWcuMbuQMFVHFONbZAZgn+C9FW4l7XyRdkrbR1MRZ2km8YMs +/AHmo368d4PSNRMMzLHw8Q== -----END PRIVATE KEY----- diff --git a/notifications/notifications/src/test/resources/security/kirk.pem b/notifications/notifications/src/test/resources/security/kirk.pem index c32b21cd..716b4ec4 100644 --- a/notifications/notifications/src/test/resources/security/kirk.pem +++ b/notifications/notifications/src/test/resources/security/kirk.pem @@ -1,26 +1,27 @@ -----BEGIN CERTIFICATE----- -MIIEdzCCA1+gAwIBAgIGAWLrc1O4MA0GCSqGSIb3DQEBCwUAMIGPMRMwEQYKCZIm -iZPyLGQBGRYDY29tMRcwFQYKCZImiZPyLGQBGRYHZXhhbXBsZTEZMBcGA1UECgwQ -RXhhbXBsZSBDb20gSW5jLjEhMB8GA1UECwwYRXhhbXBsZSBDb20gSW5jLiBSb290 -IENBMSEwHwYDVQQDDBhFeGFtcGxlIENvbSBJbmMuIFJvb3QgQ0EwHhcNMTgwNDIy -MDM0MzQ3WhcNMjgwNDE5MDM0MzQ3WjBNMQswCQYDVQQGEwJkZTENMAsGA1UEBwwE -dGVzdDEPMA0GA1UECgwGY2xpZW50MQ8wDQYDVQQLDAZjbGllbnQxDTALBgNVBAMM -BGtpcmswggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDCwgBOoO88uMM8 -dREJsk58Yt4Jn0zwQ2wUThbvy3ICDiEWhiAhUbg6dTggpS5vWWJto9bvaaqgMVoh -ElfYHdTDncX3UQNBEP8tqzHON6BFEFSGgJRGLd6f5dri6rK32nCotYS61CFXBFxf -WumXjSukjyrcTsdkR3C5QDo2oN7F883MOQqRENPzAtZi9s3jNX48u+/e3yvJzXsB -GS9Qmsye6C71enbIujM4CVwDT/7a5jHuaUp6OuNCFbdRPnu/wLYwOS2/yOtzAqk7 -/PFnPCe7YOa10ShnV/jx2sAHhp7ZQBJgFkkgnIERz9Ws74Au+EbptWnsWuB+LqRL -x5G02IzpAgMBAAGjggEYMIIBFDCBvAYDVR0jBIG0MIGxgBSSNQzgDx4rRfZNOfN7 -X6LmEpdAc6GBlaSBkjCBjzETMBEGCgmSJomT8ixkARkWA2NvbTEXMBUGCgmSJomT -8ixkARkWB2V4YW1wbGUxGTAXBgNVBAoMEEV4YW1wbGUgQ29tIEluYy4xITAfBgNV -BAsMGEV4YW1wbGUgQ29tIEluYy4gUm9vdCBDQTEhMB8GA1UEAwwYRXhhbXBsZSBD -b20gSW5jLiBSb290IENBggEBMB0GA1UdDgQWBBRsdhuHn3MGDvZxOe22+1wliCJB -mDAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIF4DAWBgNVHSUBAf8EDDAKBggr -BgEFBQcDAjANBgkqhkiG9w0BAQsFAAOCAQEAkPrUTKKn+/6g0CjhTPBFeX8mKXhG -zw5z9Oq+xnwefZwxV82E/tgFsPcwXcJIBg0f43BaVSygPiV7bXqWhxASwn73i24z -lveIR4+z56bKIhP6c3twb8WWR9yDcLu2Iroin7dYEm3dfVUrhz/A90WHr6ddwmLL -3gcFF2kBu3S3xqM5OmN/tqRXFmo+EvwrdJRiTh4Fsf0tX1ZT07rrGvBFYktK7Kma -lqDl4UDCF1UWkiiFubc0Xw+DR6vNAa99E0oaphzvCmITU1wITNnYZTKzVzQ7vUCq -kLmXOFLTcxTQpptxSo5xDD3aTpzWGCvjExCKpXQtsITUOYtZc02AGjjPOQ== +MIIEmDCCA4CgAwIBAgIUZjrlDPP8azRDPZchA/XEsx0X2iYwDQYJKoZIhvcNAQEL +BQAwgY8xEzARBgoJkiaJk/IsZAEZFgNjb20xFzAVBgoJkiaJk/IsZAEZFgdleGFt +cGxlMRkwFwYDVQQKDBBFeGFtcGxlIENvbSBJbmMuMSEwHwYDVQQLDBhFeGFtcGxl +IENvbSBJbmMuIFJvb3QgQ0ExITAfBgNVBAMMGEV4YW1wbGUgQ29tIEluYy4gUm9v +dCBDQTAeFw0yMzA4MjkyMDA2MzdaFw0zMzA4MjYyMDA2MzdaME0xCzAJBgNVBAYT +AmRlMQ0wCwYDVQQHDAR0ZXN0MQ8wDQYDVQQKDAZjbGllbnQxDzANBgNVBAsMBmNs +aWVudDENMAsGA1UEAwwEa2lyazCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC +ggEBAJVcOAQlCiuB9emCljROAXnlsPbG7PE3kNz2sN+BbGuw686Wgyl3uToVHvVs +paMmLUqm1KYz9wMSWTIBZgpJ9hYaIbGxD4RBb7qTAJ8Q4ddCV2f7T4lxao/6ixI+ +O0l/BG9E3mRGo/r0w+jtTQ3aR2p6eoxaOYbVyEMYtFI4QZTkcgGIPGxm05y8xonx +vV5pbSW9L7qAVDzQC8EYGQMMI4ccu0NcHKWtmTYJA/wDPE2JwhngHwbcIbc4cDz6 +cG0S3FmgiKGuuSqUy35v/k3y7zMHQSdx7DSR2tzhH/bBL/9qGvpT71KKrxPtaxS0 +bAqPcEkKWDo7IMlGGW7LaAWfGg8CAwEAAaOCASswggEnMAwGA1UdEwEB/wQCMAAw +DgYDVR0PAQH/BAQDAgXgMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMCMIHPBgNVHSME +gccwgcSAFBeH36Ba62YSp9XQ+LoSRTy3KwCcoYGVpIGSMIGPMRMwEQYKCZImiZPy +LGQBGRYDY29tMRcwFQYKCZImiZPyLGQBGRYHZXhhbXBsZTEZMBcGA1UECgwQRXhh +bXBsZSBDb20gSW5jLjEhMB8GA1UECwwYRXhhbXBsZSBDb20gSW5jLiBSb290IENB +MSEwHwYDVQQDDBhFeGFtcGxlIENvbSBJbmMuIFJvb3QgQ0GCFHfkrz782p+T9k0G +xGeM4+BrehWKMB0GA1UdDgQWBBSjMS8tgguX/V7KSGLoGg7K6XMzIDANBgkqhkiG +9w0BAQsFAAOCAQEANMwD1JYlwAh82yG1gU3WSdh/tb6gqaSzZK7R6I0L7slaXN9m +y2ErUljpTyaHrdiBFmPhU/2Kj2r+fIUXtXdDXzizx/JdmueT0nG9hOixLqzfoC9p +fAhZxM62RgtyZoaczQN82k1/geMSwRpEndFe3OH7arkS/HSbIFxQhAIy229eWe5d +1bUzP59iu7f3r567I4ob8Vy7PP+Ov35p7Vv4oDHHwgsdRzX6pvL6mmwVrQ3BfVec +h9Dqprr+ukYmjho76g6k5cQuRaB6MxqldzUg+2E7IHQP8MCF+co51uZq2nl33mtp +RGr6JbdHXc96zsLTL3saJQ8AWEfu1gbTVrwyRA== -----END CERTIFICATE----- diff --git a/notifications/notifications/src/test/resources/security/root-ca.pem b/notifications/notifications/src/test/resources/security/root-ca.pem index 4015d866..5948a73b 100644 --- a/notifications/notifications/src/test/resources/security/root-ca.pem +++ b/notifications/notifications/src/test/resources/security/root-ca.pem @@ -1,24 +1,28 @@ -----BEGIN CERTIFICATE----- -MIID/jCCAuagAwIBAgIBATANBgkqhkiG9w0BAQsFADCBjzETMBEGCgmSJomT8ixk -ARkWA2NvbTEXMBUGCgmSJomT8ixkARkWB2V4YW1wbGUxGTAXBgNVBAoMEEV4YW1w -bGUgQ29tIEluYy4xITAfBgNVBAsMGEV4YW1wbGUgQ29tIEluYy4gUm9vdCBDQTEh -MB8GA1UEAwwYRXhhbXBsZSBDb20gSW5jLiBSb290IENBMB4XDTE4MDQyMjAzNDM0 -NloXDTI4MDQxOTAzNDM0NlowgY8xEzARBgoJkiaJk/IsZAEZFgNjb20xFzAVBgoJ -kiaJk/IsZAEZFgdleGFtcGxlMRkwFwYDVQQKDBBFeGFtcGxlIENvbSBJbmMuMSEw -HwYDVQQLDBhFeGFtcGxlIENvbSBJbmMuIFJvb3QgQ0ExITAfBgNVBAMMGEV4YW1w -bGUgQ29tIEluYy4gUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBAK/u+GARP5innhpXK0c0q7s1Su1VTEaIgmZr8VWI6S8amf5cU3ktV7WT9SuV -TsAm2i2A5P+Ctw7iZkfnHWlsC3HhPUcd6mvzGZ4moxnamM7r+a9otRp3owYoGStX -ylVTQusAjbq9do8CMV4hcBTepCd+0w0v4h6UlXU8xjhj1xeUIz4DKbRgf36q0rv4 -VIX46X72rMJSETKOSxuwLkov1ZOVbfSlPaygXIxqsHVlj1iMkYRbQmaTib6XWHKf -MibDaqDejOhukkCjzpptGZOPFQ8002UtTTNv1TiaKxkjMQJNwz6jfZ53ws3fh1I0 -RWT6WfM4oeFRFnyFRmc4uYTUgAkCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAf -BgNVHSMEGDAWgBSSNQzgDx4rRfZNOfN7X6LmEpdAczAdBgNVHQ4EFgQUkjUM4A8e -K0X2TTnze1+i5hKXQHMwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4IB -AQBoQHvwsR34hGO2m8qVR9nQ5Klo5HYPyd6ySKNcT36OZ4AQfaCGsk+SecTi35QF -RHL3g2qffED4tKR0RBNGQSgiLavmHGCh3YpDupKq2xhhEeS9oBmQzxanFwWFod4T -nnsG2cCejyR9WXoRzHisw0KJWeuNlwjUdJY0xnn16srm1zL/M/f0PvCyh9HU1mF1 -ivnOSqbDD2Z7JSGyckgKad1Omsg/rr5XYtCeyJeXUPcmpeX6erWJJNTUh6yWC/hY -G/dFC4xrJhfXwz6Z0ytUygJO32bJG4Np2iGAwvvgI9EfxzEv/KP+FGrJOvQJAq4/ -BU36ZAa80W/8TBnqZTkNnqZV +MIIExjCCA66gAwIBAgIUd+SvPvzan5P2TQbEZ4zj4Gt6FYowDQYJKoZIhvcNAQEL +BQAwgY8xEzARBgoJkiaJk/IsZAEZFgNjb20xFzAVBgoJkiaJk/IsZAEZFgdleGFt +cGxlMRkwFwYDVQQKDBBFeGFtcGxlIENvbSBJbmMuMSEwHwYDVQQLDBhFeGFtcGxl +IENvbSBJbmMuIFJvb3QgQ0ExITAfBgNVBAMMGEV4YW1wbGUgQ29tIEluYy4gUm9v +dCBDQTAeFw0yMzA4MjkwNDIwMDNaFw0yMzA5MjgwNDIwMDNaMIGPMRMwEQYKCZIm +iZPyLGQBGRYDY29tMRcwFQYKCZImiZPyLGQBGRYHZXhhbXBsZTEZMBcGA1UECgwQ +RXhhbXBsZSBDb20gSW5jLjEhMB8GA1UECwwYRXhhbXBsZSBDb20gSW5jLiBSb290 +IENBMSEwHwYDVQQDDBhFeGFtcGxlIENvbSBJbmMuIFJvb3QgQ0EwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDEPyN7J9VGPyJcQmCBl5TGwfSzvVdWwoQU +j9aEsdfFJ6pBCDQSsj8Lv4RqL0dZra7h7SpZLLX/YZcnjikrYC+rP5OwsI9xEE/4 +U98CsTBPhIMgqFK6SzNE5494BsAk4cL72dOOc8tX19oDS/PvBULbNkthQ0aAF1dg +vbrHvu7hq7LisB5ZRGHVE1k/AbCs2PaaKkn2jCw/b+U0Ml9qPuuEgz2mAqJDGYoA +WSR4YXrOcrmPuRqbws464YZbJW898/0Pn/U300ed+4YHiNYLLJp51AMkR4YEw969 +VRPbWIvLrd0PQBooC/eLrL6rvud/GpYhdQEUx8qcNCKd4bz3OaQ5AgMBAAGjggEW +MIIBEjAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQU +F4ffoFrrZhKn1dD4uhJFPLcrAJwwgc8GA1UdIwSBxzCBxIAUF4ffoFrrZhKn1dD4 +uhJFPLcrAJyhgZWkgZIwgY8xEzARBgoJkiaJk/IsZAEZFgNjb20xFzAVBgoJkiaJ +k/IsZAEZFgdleGFtcGxlMRkwFwYDVQQKDBBFeGFtcGxlIENvbSBJbmMuMSEwHwYD +VQQLDBhFeGFtcGxlIENvbSBJbmMuIFJvb3QgQ0ExITAfBgNVBAMMGEV4YW1wbGUg +Q29tIEluYy4gUm9vdCBDQYIUd+SvPvzan5P2TQbEZ4zj4Gt6FYowDQYJKoZIhvcN +AQELBQADggEBAIopqco/k9RSjouTeKP4z0EVUxdD4qnNh1GLSRqyAVe0aChyKF5f +qt1Bd1XCY8D16RgekkKGHDpJhGCpel+vtIoXPBxUaGQNYxmJCf5OzLMODlcrZk5i +jHIcv/FMeK02NBcz/WQ3mbWHVwXLhmwqa2zBsF4FmPCJAbFLchLhkAv1HJifHbnD +jQzlKyl5jxam/wtjWxSm0iyso0z2TgyzY+MESqjEqB1hZkCFzD1xtUOCxbXgtKae +dgfHVFuovr3fNLV3GvQk0s9okDwDUcqV7DSH61e5bUMfE84o3of8YA7+HUoPV5Du +8sTOKRf7ncGXdDRA8aofW268pTCuIu3+g/Y= -----END CERTIFICATE----- diff --git a/notifications/notifications/src/test/resources/security/sample.pem b/notifications/notifications/src/test/resources/security/sample.pem index fa785ca1..a1fc20a7 100644 --- a/notifications/notifications/src/test/resources/security/sample.pem +++ b/notifications/notifications/src/test/resources/security/sample.pem @@ -1,28 +1,25 @@ -----BEGIN CERTIFICATE----- -MIIEyTCCA7GgAwIBAgIGAWLrc1O2MA0GCSqGSIb3DQEBCwUAMIGPMRMwEQYKCZIm -iZPyLGQBGRYDY29tMRcwFQYKCZImiZPyLGQBGRYHZXhhbXBsZTEZMBcGA1UECgwQ -RXhhbXBsZSBDb20gSW5jLjEhMB8GA1UECwwYRXhhbXBsZSBDb20gSW5jLiBSb290 -IENBMSEwHwYDVQQDDBhFeGFtcGxlIENvbSBJbmMuIFJvb3QgQ0EwHhcNMTgwNDIy -MDM0MzQ3WhcNMjgwNDE5MDM0MzQ3WjBeMRIwEAYKCZImiZPyLGQBGRYCZGUxDTAL -BgNVBAcMBHRlc3QxDTALBgNVBAoMBG5vZGUxDTALBgNVBAsMBG5vZGUxGzAZBgNV -BAMMEm5vZGUtMC5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC -AQoCggEBAJa+f476vLB+AwK53biYByUwN+40D8jMIovGXm6wgT8+9Sbs899dDXgt -9CE1Beo65oP1+JUz4c7UHMrCY3ePiDt4cidHVzEQ2g0YoVrQWv0RedS/yx/DKhs8 -Pw1O715oftP53p/2ijD5DifFv1eKfkhFH+lwny/vMSNxellpl6NxJTiJVnQ9HYOL -gf2t971ITJHnAuuxUF48HcuNovW4rhtkXef8kaAN7cE3LU+A9T474ULNCKkEFPIl -ZAKN3iJNFdVsxrTU+CUBHzk73Do1cCkEvJZ0ZFjp0Z3y8wLY/gqWGfGVyA9l2CUq -eIZNf55PNPtGzOrvvONiui48vBKH1LsCAwEAAaOCAVkwggFVMIG8BgNVHSMEgbQw -gbGAFJI1DOAPHitF9k0583tfouYSl0BzoYGVpIGSMIGPMRMwEQYKCZImiZPyLGQB -GRYDY29tMRcwFQYKCZImiZPyLGQBGRYHZXhhbXBsZTEZMBcGA1UECgwQRXhhbXBs -ZSBDb20gSW5jLjEhMB8GA1UECwwYRXhhbXBsZSBDb20gSW5jLiBSb290IENBMSEw -HwYDVQQDDBhFeGFtcGxlIENvbSBJbmMuIFJvb3QgQ0GCAQEwHQYDVR0OBBYEFKyv -78ZmFjVKM9g7pMConYH7FVBHMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/BAQDAgXg -MCAGA1UdJQEB/wQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjA1BgNVHREELjAsiAUq -AwQFBYISbm9kZS0wLmV4YW1wbGUuY29tgglsb2NhbGhvc3SHBH8AAAEwDQYJKoZI -hvcNAQELBQADggEBAIOKuyXsFfGv1hI/Lkpd/73QNqjqJdxQclX57GOMWNbOM5H0 -5/9AOIZ5JQsWULNKN77aHjLRr4owq2jGbpc/Z6kAd+eiatkcpnbtbGrhKpOtoEZy -8KuslwkeixpzLDNISSbkeLpXz4xJI1ETMN/VG8ZZP1bjzlHziHHDu0JNZ6TnNzKr -XzCGMCohFfem8vnKNnKUneMQMvXd3rzUaAgvtf7Hc2LTBlf4fZzZF1EkwdSXhaMA -1lkfHiqOBxtgeDLxCHESZ2fqgVqsWX+t3qHQfivcPW6txtDyrFPRdJOGhiMGzT/t -e/9kkAtQRgpTb3skYdIOOUOV0WGQ60kJlFhAzIs= ------END CERTIFICATE----- \ No newline at end of file +MIIEPDCCAySgAwIBAgIUZjrlDPP8azRDPZchA/XEsx0X2iIwDQYJKoZIhvcNAQEL +BQAwgY8xEzARBgoJkiaJk/IsZAEZFgNjb20xFzAVBgoJkiaJk/IsZAEZFgdleGFt +cGxlMRkwFwYDVQQKDBBFeGFtcGxlIENvbSBJbmMuMSEwHwYDVQQLDBhFeGFtcGxl +IENvbSBJbmMuIFJvb3QgQ0ExITAfBgNVBAMMGEV4YW1wbGUgQ29tIEluYy4gUm9v +dCBDQTAeFw0yMzA4MjkwNDIzMTJaFw0zMzA4MjYwNDIzMTJaMFcxCzAJBgNVBAYT +AmRlMQ0wCwYDVQQHDAR0ZXN0MQ0wCwYDVQQKDARub2RlMQ0wCwYDVQQLDARub2Rl +MRswGQYDVQQDDBJub2RlLTAuZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUA +A4IBDwAwggEKAoIBAQCm93kXteDQHMAvbUPNPW5pyRHKDD42XGWSgq0k1D29C/Ud +yL21HLzTJa49ZU2ldIkSKs9JqbkHdyK0o8MO6L8dotLoYbxDWbJFW8bp1w6tDTU0 +HGkn47XVu3EwbfrTENg3jFu+Oem6a/501SzITzJWtS0cn2dIFOBimTVpT/4Zv5qr +XA6Cp4biOmoTYWhi/qQl8d0IaADiqoZ1MvZbZ6x76qTrRAbg+UWkpTEXoH1xTc8n +dibR7+HP6OTqCKvo1NhE8uP4pY+fWd6b6l+KLo3IKpfTbAIJXIO+M67FLtWKtttD +ao94B069skzKk6FPgW/OZh6PRCD0oxOavV+ld2SjAgMBAAGjgcYwgcMwRwYDVR0R +BEAwPogFKgMEBQWCEm5vZGUtMC5leGFtcGxlLmNvbYIJbG9jYWxob3N0hxAAAAAA +AAAAAAAAAAAAAAABhwR/AAABMAsGA1UdDwQEAwIF4DAdBgNVHSUEFjAUBggrBgEF +BQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU0/qDQaY10jIo +wCjLUpz/HfQXyt8wHwYDVR0jBBgwFoAUF4ffoFrrZhKn1dD4uhJFPLcrAJwwDQYJ +KoZIhvcNAQELBQADggEBAD2hkndVih6TWxoe/oOW0i2Bq7ScNO/n7/yHWL04HJmR +MaHv/Xjc8zLFLgHuHaRvC02ikWIJyQf5xJt0Oqu2GVbqXH9PBGKuEP2kCsRRyU27 +zTclAzfQhqmKBTYQ/3lJ3GhRQvXIdYTe+t4aq78TCawp1nSN+vdH/1geG6QjMn5N +1FU8tovDd4x8Ib/0dv8RJx+n9gytI8n/giIaDCEbfLLpe4EkV5e5UNpOnRgJjjuy +vtZutc81TQnzBtkS9XuulovDE0qI+jQrKkKu8xgGLhgH0zxnPkKtUg2I3Aq6zl1L +zYkEOUF8Y25J6WeY88Yfnc0iigI+Pnz5NK8R9GL7TYo= +-----END CERTIFICATE----- diff --git a/notifications/notifications/src/test/resources/security/test-kirk.jks b/notifications/notifications/src/test/resources/security/test-kirk.jks index 174dbda656f41b10341adb78ab91a46afaae8a1c..6dbc51e714784fa58a4209c75deab8b9ed1698ff 100644 GIT binary patch literal 4504 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 ROz*Khv5A{`^It3We*oUlR=)rM literal 3874 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 Date: Thu, 7 Sep 2023 13:23:12 +0800 Subject: [PATCH 05/28] Add 2.10.0 release notes (#755) * Add 2.10.0 release notes Signed-off-by: Hailong Cui * update release notes Signed-off-by: Hailong Cui * Update opensearch-notifications.release-notes-2.10.0.0.md Signed-off-by: Hailong Cui * fix wrong PR number Signed-off-by: Hailong Cui --------- Signed-off-by: Hailong Cui Signed-off-by: Aniruddh --- ...ch-notifications.release-notes-2.10.0.0.md | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 release-notes/opensearch-notifications.release-notes-2.10.0.0.md diff --git a/release-notes/opensearch-notifications.release-notes-2.10.0.0.md b/release-notes/opensearch-notifications.release-notes-2.10.0.0.md new file mode 100644 index 00000000..ac9a8067 --- /dev/null +++ b/release-notes/opensearch-notifications.release-notes-2.10.0.0.md @@ -0,0 +1,22 @@ +## Version 2.10.0.0 2023-09-25 + +Compatible with OpenSearch 2.10.0 + +### Features/Enhancements +* Support SNS FIFO queues([#716](https://github.com/opensearch-project/notifications/pull/716)) +* Supuport Microsoft teams([#676](https://github.com/opensearch-project/notifications/pull/676),[#746](https://github.com/opensearch-project/notifications/pull/746)) +* Support auto upgrade mapping logic([#699](https://github.com/opensearch-project/notifications/pull/699)) + +### Maintenance +* [AUTO] Increment version to 2.10.0-SNAPSHOT([#706](https://github.com/opensearch-project/notifications/pull/706)) + +### Infrastructure +* Fix core refactor: StreamIO from common to core.common([#707](https://github.com/opensearch-project/notifications/pull/707)) +* Fix core XcontentFactory refactor([#732](https://github.com/opensearch-project/notifications/pull/732)) +* Fix actions components after core([#739](https://github.com/opensearch-project/notifications/pull/739)) +* Add auto release workflow([#731](https://github.com/opensearch-project/notifications/pull/731)) +* Onboarding system and hidden index([#742](https://github.com/opensearch-project/notifications/pull/742)) +* Updates demo certs used in integ tests([#756](https://github.com/opensearch-project/notifications/pull/756)) + +### Documentation +* Add 2.10.0 release notes ([#755](https://github.com/opensearch-project/notifications/pull/755)) From 7dcca6e396d4c38b4bd660dfac21ea7ac848e0d6 Mon Sep 17 00:00:00 2001 From: Hailong Cui Date: Mon, 11 Sep 2023 12:05:12 +0800 Subject: [PATCH 06/28] bump bwc version to 2.11 (#763) Signed-off-by: Hailong Cui Signed-off-by: Aniruddh --- notifications/notifications/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notifications/notifications/build.gradle b/notifications/notifications/build.gradle index b29dcdf2..0024ef0c 100644 --- a/notifications/notifications/build.gradle +++ b/notifications/notifications/build.gradle @@ -265,7 +265,7 @@ testClusters.integTest { } // Always be minimumCompatibilityVersion of current opensearch version(3.0.0) -def bwcVersionShort = "2.10.0" +def bwcVersionShort = "2.11.0" def bwcVersion = bwcVersionShort + ".0" def bwcOpenSearchVesion= bwcVersionShort + "-SNAPSHOT" def bwcPluginVersion = bwcVersion + "-SNAPSHOT" From 93aa732aeb59fdb2dff55395013d916423c1b9cf Mon Sep 17 00:00:00 2001 From: Yuye Zhu Date: Fri, 6 Oct 2023 12:14:59 +0800 Subject: [PATCH 07/28] Add 2.11 release notes (#774) Signed-off-by: yuye-aws Signed-off-by: Aniruddh --- .../opensearch-notifications.release-notes-2.11.0.0.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 release-notes/opensearch-notifications.release-notes-2.11.0.0.md diff --git a/release-notes/opensearch-notifications.release-notes-2.11.0.0.md b/release-notes/opensearch-notifications.release-notes-2.11.0.0.md new file mode 100644 index 00000000..4f415424 --- /dev/null +++ b/release-notes/opensearch-notifications.release-notes-2.11.0.0.md @@ -0,0 +1,9 @@ +## Version 2.11.0.0 2023-10-18 + +Compatible with OpenSearch 2.11.0 + +### Maintenance +* Bump bwc version to 2.11([#763](https://github.com/opensearch-project/notifications/pull/763)) + +### Documentation +* Add 2.11.0 release notes ([#774](https://github.com/opensearch-project/notifications/issues/774)) From 2c3cef047cddaf340363e92a5228120a901b6523 Mon Sep 17 00:00:00 2001 From: gaobinlong Date: Wed, 11 Oct 2023 18:17:53 +0800 Subject: [PATCH 08/28] Fix integration test failure by allowing direct access to system index warning (#784) * Fix integration test failure by allowing direct access to system index warning Signed-off-by: gaobinlong * Fix bwc test failure of throwing direct access to system index when getting mapping Signed-off-by: gaobinlong --------- Signed-off-by: gaobinlong Signed-off-by: Aniruddh Srivastava Signed-off-by: Aniruddh --- .../integtest/PluginRestTestCase.kt | 36 +++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/PluginRestTestCase.kt b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/PluginRestTestCase.kt index cdfae6b0..56f0e342 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/PluginRestTestCase.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/PluginRestTestCase.kt @@ -372,14 +372,44 @@ abstract class PluginRestTestCase : OpenSearchRestTestCase() { } protected fun getCurrentMappingsSchemaVersion(): Int { - val indexName = ".opensearch-notifications-config" - val getMappingRequest = Request(RestRequest.Method.GET.name, "$indexName/_mappings") + val getMappingRequest = Request(RestRequest.Method.GET.name, "${NotificationConfigIndex.INDEX_NAME}/_mappings") + val requestOptions = RequestOptions.DEFAULT.toBuilder() + // Allow direct access to system index warning + requestOptions.setWarningsHandler { warnings: List -> + if (warnings.isEmpty()) { + return@setWarningsHandler false + } else if (warnings.size > 1) { + return@setWarningsHandler true + } else { + return@setWarningsHandler !warnings[0].startsWith("this request accesses system indices:") + } + } + getMappingRequest.setOptions(requestOptions) val response = executeRequest(getMappingRequest, RestStatus.OK.status, client()) - val mappingsObject = response.get(indexName).asJsonObject.get("mappings").asJsonObject + val mappingsObject = response.get(NotificationConfigIndex.INDEX_NAME).asJsonObject.get("mappings").asJsonObject return mappingsObject.get(NotificationConfigIndex._META)?.asJsonObject?.get(NotificationConfigIndex.SCHEMA_VERSION)?.asInt ?: NotificationConfigIndex.DEFAULT_SCHEMA_VERSION } + // only refresh the notification config index to avoid too many warnings + @Throws(IOException::class) + override fun refreshAllIndices() { + val refreshRequest = Request("POST", "${NotificationConfigIndex.INDEX_NAME}/_refresh") + val requestOptions = RequestOptions.DEFAULT.toBuilder() + // Allow direct access to system index warning + requestOptions.setWarningsHandler { warnings: List -> + if (warnings.isEmpty()) { + return@setWarningsHandler false + } else if (warnings.size > 1) { + return@setWarningsHandler true + } else { + return@setWarningsHandler !warnings[0].startsWith("this request accesses system indices:") + } + } + refreshRequest.setOptions(requestOptions) + client().performRequest(refreshRequest) + } + protected class ClusterSetting(val type: String, val name: String, var value: Any?) { init { this.value = if (value == null) "null" else "\"" + value + "\"" From e5452cd16f50c5832177f847776f95ed81d64d9b Mon Sep 17 00:00:00 2001 From: Aniruddh <63553175+Noir01@users.noreply.github.com> Date: Mon, 16 Oct 2023 04:34:05 -0400 Subject: [PATCH 09/28] Re-enable detekt Bumped version of `io.gitlab.arturbosch.detekt:detekt-gradle-plugin` to `1.23.0` Signed-off-by: Aniruddh <63553175+Noir01@users.noreply.github.com> Signed-off-by: Aniruddh Srivastava Signed-off-by: Aniruddh --- notifications/build.gradle | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/notifications/build.gradle b/notifications/build.gradle index 7c9b7741..899d50d4 100644 --- a/notifications/build.gradle +++ b/notifications/build.gradle @@ -38,16 +38,14 @@ buildscript { classpath "org.opensearch.gradle:build-tools:${opensearch_version}" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlin_version}" classpath "org.jetbrains.kotlin:kotlin-allopen:${kotlin_version}" -// TODO: enable detekt only when snakeyaml vulnerability is fixed -// classpath "io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.17.1" + classpath "io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.23.0" classpath "org.jacoco:org.jacoco.agent:0.8.7" } } apply plugin: 'base' apply plugin: 'jacoco' -// TODO: enable detekt only when snakeyaml vulnerability is fixed -//apply plugin: 'io.gitlab.arturbosch.detekt' +apply plugin: 'io.gitlab.arturbosch.detekt' apply from: 'build-tools/merged-coverage.gradle' allprojects { @@ -100,12 +98,11 @@ task ktlintFormat(type: JavaExec, group: "formatting") { jvmArgs "--add-opens=java.base/java.lang=ALL-UNNAMED" } -// TODO: enable detekt only when snakeyaml vulnerability is fixed -//detekt { -// config = files("detekt.yml") -// buildUponDefaultConfig = true -// parallel = true -//} +detekt { + config = files("detekt.yml") + buildUponDefaultConfig = true + parallel = true +} check.dependsOn ktlint From ff446bc8e41bfdc29b43375866727f2a7beac4f6 Mon Sep 17 00:00:00 2001 From: Hailong Cui Date: Mon, 16 Oct 2023 14:27:23 +0800 Subject: [PATCH 10/28] bump bwc version to 2.12 (#793) Signed-off-by: Hailong Cui Signed-off-by: Aniruddh Srivastava Signed-off-by: Aniruddh --- notifications/notifications/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notifications/notifications/build.gradle b/notifications/notifications/build.gradle index 0024ef0c..0db0b393 100644 --- a/notifications/notifications/build.gradle +++ b/notifications/notifications/build.gradle @@ -265,7 +265,7 @@ testClusters.integTest { } // Always be minimumCompatibilityVersion of current opensearch version(3.0.0) -def bwcVersionShort = "2.11.0" +def bwcVersionShort = "2.12.0" def bwcVersion = bwcVersionShort + ".0" def bwcOpenSearchVesion= bwcVersionShort + "-SNAPSHOT" def bwcPluginVersion = bwcVersion + "-SNAPSHOT" From ecac8aecf5f85fcd967eda2085b4066f3611b364 Mon Sep 17 00:00:00 2001 From: gaobinlong Date: Tue, 17 Oct 2023 11:34:49 +0800 Subject: [PATCH 11/28] Update dependency org.json:json to v20231013 (#795) Signed-off-by: gaobinlong Signed-off-by: Aniruddh Srivastava Signed-off-by: Aniruddh --- notifications/notifications/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notifications/notifications/build.gradle b/notifications/notifications/build.gradle index 0db0b393..14f686ce 100644 --- a/notifications/notifications/build.gradle +++ b/notifications/notifications/build.gradle @@ -100,7 +100,7 @@ dependencies { } // ${kotlin_version} does not work for coroutines implementation "${group}:common-utils:${common_utils_version}" // TODO: change compile to implementation when the _local/stats API is supported - compileOnly "org.json:json:20230227" + compileOnly "org.json:json:20231013" compileOnly "com.github.wnameless.json:json-flattener:0.13.0" // TODO: uncomment when the _local/stats API is supported // implementation "com.github.wnameless.json:json-base:2.0.0" From 445c1e790a6ac6aaaa5510f0f9f967ac413596c7 Mon Sep 17 00:00:00 2001 From: Hailong Cui Date: Thu, 19 Oct 2023 23:10:27 +0800 Subject: [PATCH 12/28] Impove security plugin enabling check (#792) Signed-off-by: Hailong Cui Signed-off-by: Aniruddh Srivastava Signed-off-by: Aniruddh --- .../workflows/security-notifications-test-workflow.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/security-notifications-test-workflow.yml b/.github/workflows/security-notifications-test-workflow.yml index 0d77cf7a..31352b76 100644 --- a/.github/workflows/security-notifications-test-workflow.yml +++ b/.github/workflows/security-notifications-test-workflow.yml @@ -79,10 +79,10 @@ jobs: - name: Run Notification Test for security enabled test cases if: env.imagePresent == 'true' run: | - cluster_running=`curl -XGET https://localhost:9200/_cat/plugins -u admin:admin --insecure` - echo $cluster_running - security=`curl -XGET https://localhost:9200/_cat/plugins -u admin:admin --insecure |grep opensearch-security|wc -l` - echo $security + container_id=`docker ps -q` + plugins=`docker exec $container_id /usr/share/opensearch/bin/opensearch-plugin list` + echo "plugins: $plugins" + security=`echo $plugins | grep opensearch-security | wc -l` if [ $security -gt 0 ] then echo "Security plugin is available" @@ -91,4 +91,4 @@ jobs: else echo "Security plugin is NOT available skipping this run as tests without security have already been run" exit 1 - fi \ No newline at end of file + fi From fd4872d545f43a5d6e006af4cfffb010a781c110 Mon Sep 17 00:00:00 2001 From: Hailong Cui Date: Fri, 20 Oct 2023 11:27:20 +0800 Subject: [PATCH 13/28] Add github workflow to auto bump bwc version (#799) * Adding bump bwc version github workflow Signed-off-by: Hailong Cui * revert app id Signed-off-by: Hailong Cui --------- Signed-off-by: Hailong Cui Signed-off-by: Aniruddh Srivastava Signed-off-by: Aniruddh --- .github/workflows/bump-bwc.yml | 66 ++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 .github/workflows/bump-bwc.yml diff --git a/.github/workflows/bump-bwc.yml b/.github/workflows/bump-bwc.yml new file mode 100644 index 00000000..dfdec028 --- /dev/null +++ b/.github/workflows/bump-bwc.yml @@ -0,0 +1,66 @@ +name: Bump bwc version + +on: + workflow_dispatch: + inputs: + tag: + type: string + required: true + push: + tags: + - '*.*.*.*' + +permissions: {} +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: GitHub App token + id: github_app_token + uses: tibdex/github-app-token@v1.5.0 + with: + app_id: ${{ secrets.APP_ID }} + private_key: ${{ secrets.APP_PRIVATE_KEY }} + installation_id: 22958780 + + - uses: actions/checkout@v4 + - name: Fetch Tag and Version Information + run: | + if [ -n ${{ inputs.tag }} ]; then + TAG=${{ inputs.tag }} + else + TAG=$(echo "${GITHUB_REF#refs/*/}") + fi + CURRENT_VERSION_ARRAY=($(echo "$TAG" | tr . '\n')) + CURRENT_VERSION=$(IFS=. ; echo "${CURRENT_VERSION_ARRAY[*]:0:3}") + CURRENT_VERSION_ARRAY[1]=$((CURRENT_VERSION_ARRAY[1]+1)) + NEXT_VERSION=$(IFS=. ; echo "${CURRENT_VERSION_ARRAY[*]:0:3}") + echo "TAG=$TAG" >> $GITHUB_ENV + echo "CURRENT_VERSION=$CURRENT_VERSION" >> $GITHUB_ENV + echo "NEXT_VERSION=$NEXT_VERSION" >> $GITHUB_ENV + + - uses: actions/checkout@v4 + with: + ref: main + token: ${{ steps.github_app_token.outputs.token }} + + - name: Bump bwc version for main branch + run: | + echo Bumping bwc version to $NEXT_VERSION + sed -i "s/def bwcVersionShort = \"$CURRENT_VERSION\"/def bwcVersionShort = \"$NEXT_VERSION\"/g" notifications/notifications/build.gradle + + - name: Create Pull Request + uses: peter-evans/create-pull-request@v5 + with: + token: ${{ steps.github_app_token.outputs.token }} + base: main + branch: 'create-pull-request/patch-main' + commit-message: Bump bwc version to ${{ env.NEXT_VERSION }} + signoff: true + delete-branch: true + labels: | + autocut + title: '[AUTO] [main] Bump bwc version to ${{ env.NEXT_VERSION }}.' + body: | + I've noticed that a new tag ${{ env.TAG }} was pushed, and bump bwc version to ${{ env.NEXT_VERSION }}. + From c00a7817b18c21bb23916b5770314858bbbe14ba Mon Sep 17 00:00:00 2001 From: Rachana Dani <36135368+rachana-dani@users.noreply.github.com> Date: Mon, 23 Oct 2023 08:35:30 +0530 Subject: [PATCH 14/28] Replace the TestMailServer to GreenMail server (#801) * Add 2.11 release notes (#774) Signed-off-by: yuye-aws Signed-off-by: rdani * Fix integration test failure by allowing direct access to system index warning (#784) * Fix integration test failure by allowing direct access to system index warning Signed-off-by: gaobinlong * Fix bwc test failure of throwing direct access to system index when getting mapping Signed-off-by: gaobinlong --------- Signed-off-by: gaobinlong Signed-off-by: rdani * Replace the TestMailServer to GreenMail server Signed-off-by: rdani * bump bwc version to 2.12 (#793) Signed-off-by: Hailong Cui Signed-off-by: rdani * Update dependency org.json:json to v20231013 (#795) Signed-off-by: gaobinlong Signed-off-by: rdani * Re-enable detekt (#796) Bumped version of `io.gitlab.arturbosch.detekt:detekt-gradle-plugin` to `1.23.0` Signed-off-by: Aniruddh <63553175+Noir01@users.noreply.github.com> Co-authored-by: Hailong Cui Signed-off-by: rdani * Add assertion for retrieval of notification Signed-off-by: rdani * Update to stable version Signed-off-by: rdani * Update to stable version Signed-off-by: rdani * Update to suggested version Signed-off-by: rdani --------- Signed-off-by: yuye-aws Signed-off-by: rdani Signed-off-by: gaobinlong Signed-off-by: Hailong Cui Signed-off-by: Aniruddh <63553175+Noir01@users.noreply.github.com> Co-authored-by: Yuye Zhu Co-authored-by: gaobinlong Co-authored-by: rdani Co-authored-by: Hailong Cui Co-authored-by: Aniruddh <63553175+Noir01@users.noreply.github.com> Signed-off-by: Aniruddh Srivastava Signed-off-by: Aniruddh --- notifications/core/build.gradle | 2 ++ .../notifications/core/smtp/SmtpEmailTests.kt | 27 +++++++++++-------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/notifications/core/build.gradle b/notifications/core/build.gradle index a00ccf60..1cef6633 100644 --- a/notifications/core/build.gradle +++ b/notifications/core/build.gradle @@ -161,6 +161,8 @@ dependencies { 'io.mockk:mockk-agent-jvm:1.11.0' ) testImplementation 'org.springframework.integration:spring-integration-mail:5.5.0' + // https://mvnrepository.com/artifact/com.icegreen/greenmail + testImplementation group: 'com.icegreen', name: 'greenmail', version: '1.6.14' testImplementation 'org.springframework.integration:spring-integration-test-support:5.5.0' testRuntimeOnly('org.junit.jupiter:junit-jupiter-engine:5.6.2') testImplementation "org.jetbrains.kotlin:kotlin-test:${kotlin_version}" diff --git a/notifications/core/src/test/kotlin/org/opensearch/notifications/core/smtp/SmtpEmailTests.kt b/notifications/core/src/test/kotlin/org/opensearch/notifications/core/smtp/SmtpEmailTests.kt index c3bd0e91..66f400c6 100644 --- a/notifications/core/src/test/kotlin/org/opensearch/notifications/core/smtp/SmtpEmailTests.kt +++ b/notifications/core/src/test/kotlin/org/opensearch/notifications/core/smtp/SmtpEmailTests.kt @@ -5,7 +5,10 @@ package org.opensearch.notifications.core.smtp -import org.junit.After +import com.icegreen.greenmail.util.GreenMail +import com.icegreen.greenmail.util.ServerSetupTest +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.opensearch.core.rest.RestStatus import org.opensearch.notifications.core.NotificationCoreImpl @@ -14,20 +17,21 @@ import org.opensearch.notifications.core.transport.SmtpDestinationTransport import org.opensearch.notifications.spi.model.MessageContent import org.opensearch.notifications.spi.model.destination.DestinationType import org.opensearch.notifications.spi.model.destination.SmtpDestination -import org.springframework.integration.test.mail.TestMailServer import kotlin.test.assertEquals class SmtpEmailTests { - internal companion object { - private const val smtpPort = 10255 // use non-standard port > 1024 to avoid permission issue - private val smtpServer = TestMailServer.smtp(smtpPort) + private lateinit var greenMail: GreenMail + + @BeforeEach + fun setUpServer() { + greenMail = GreenMail(ServerSetupTest.SMTP) + greenMail.start() } - @After + @AfterEach fun tearDownServer() { - smtpServer.stop() - smtpServer.resetServer() + greenMail.stop() } @Test @@ -35,7 +39,7 @@ class SmtpEmailTests { val smtpDestination = SmtpDestination( "testAccountName", "localhost", - smtpPort, + ServerSetupTest.SMTP.port, "none", "from@email.com", "test@localhost.com" @@ -53,6 +57,7 @@ class SmtpEmailTests { val response = NotificationCoreImpl.sendMessage(smtpDestination, message, "ref") assertEquals("Success", response.statusText) assertEquals(RestStatus.OK.status, response.statusCode) + assertEquals(1, greenMail.receivedMessages.size) // Indicates retrieval of notification. } @Test @@ -60,7 +65,7 @@ class SmtpEmailTests { val smtpDestination = SmtpDestination( "testAccountName", "invalidHost", - smtpPort, + ServerSetupTest.SMTP.port, "none", "from@email.com", "test@localhost.com" @@ -77,7 +82,7 @@ class SmtpEmailTests { DestinationTransportProvider.destinationTransportMap = mapOf(DestinationType.SMTP to SmtpDestinationTransport()) val response = NotificationCoreImpl.sendMessage(smtpDestination, message, "ref") assertEquals( - "sendEmail Error, status:Couldn't connect to host, port: invalidHost, $smtpPort; timeout -1", + "sendEmail Error, status:Couldn't connect to host, port: invalidHost, ${ServerSetupTest.SMTP.port}; timeout -1", response.statusText ) assertEquals(RestStatus.SERVICE_UNAVAILABLE.status, response.statusCode) From 9342dfa822e88961c128f4a5ebc48d67412425b6 Mon Sep 17 00:00:00 2001 From: Peter Zhu Date: Tue, 31 Oct 2023 23:01:33 -0400 Subject: [PATCH 15/28] Onboard prod jenkins docker image to github actions (#809) * Onboard prod jenkins docker image to github actions Signed-off-by: Peter Zhu * Add more Signed-off-by: Peter Zhu --------- Signed-off-by: Peter Zhu Signed-off-by: Aniruddh Srivastava Signed-off-by: Aniruddh --- .../notifications-test-and-build-workflow.yml | 78 ++++++++++++++++--- 1 file changed, 68 insertions(+), 10 deletions(-) diff --git a/.github/workflows/notifications-test-and-build-workflow.yml b/.github/workflows/notifications-test-and-build-workflow.yml index dd031a77..4f758317 100644 --- a/.github/workflows/notifications-test-and-build-workflow.yml +++ b/.github/workflows/notifications-test-and-build-workflow.yml @@ -8,7 +8,73 @@ name: Test and Build Notifications on: [push, pull_request] jobs: - build: + Get-CI-Image-Tag: + uses: opensearch-project/opensearch-build/.github/workflows/get-ci-image-tag.yml@main + with: + product: opensearch + + build-linux: + needs: Get-CI-Image-Tag + strategy: + # This setting says that all jobs should finish, even if one fails + fail-fast: false + matrix: + java: [11, 17] + + # Job name + name: Build Notifications with JDK ${{ matrix.java }} on linux + runs-on: ubuntu-latest + container: + # using the same image which is used by opensearch-build team to build the OpenSearch Distribution + # this image tag is subject to change as more dependencies and updates will arrive over time + image: ${{ needs.Get-CI-Image-Tag.outputs.ci-image-version-linux }} + # need to switch to root so that github actions can install runner binary on container without permission issues. + options: --user root + + steps: + - name: Set up JDK ${{ matrix.java }} + uses: actions/setup-java@v2 + with: + distribution: temurin # Temurin is a distribution of adoptium + java-version: ${{ matrix.java }} + + # notifications + - name: Checkout Notifications + uses: actions/checkout@v2 + + - name: Build with Gradle + run: | + chown -R 1000:1000 `pwd` + cd notifications + su `id -un 1000` -c "./gradlew build" + + - name: Upload coverage + uses: codecov/codecov-action@v1 + with: + flags: opensearch-notifications + directory: notifications/ + token: ${{ secrets.CODECOV_TOKEN }} + + - name: Create Artifact Path + run: | + mkdir -p notifications-build/{notifications,notifications-core} + cp -r ./notifications/notifications/build/distributions/*.zip notifications-build/notifications/ + cp -r ./notifications/core/build/distributions/*.zip notifications-build/notifications-core/ + shell: bash + + - name: Upload Artifacts for notifications plugin + uses: actions/upload-artifact@v1 + with: + name: notifications-plugin-${{ matrix.os }} + path: notifications-build/notifications + + - name: Upload Artifacts for notifications-core plugin + uses: actions/upload-artifact@v1 + with: + name: notifications-core-plugin-${{ matrix.os }} + path: notifications-build/notifications-core + + build-windows-macos: env: BUILD_ARGS: ${{ matrix.os_build_args }} WORKING_DIR: ${{ matrix.working_directory }}. @@ -17,7 +83,7 @@ jobs: fail-fast: false matrix: java: [11, 17] - os: [ ubuntu-latest, windows-latest, macos-latest ] + os: [ windows-latest, macos-latest ] include: - os: windows-latest os_build_args: -x integTest -x jacocoTestReport @@ -55,14 +121,6 @@ jobs: env: _JAVA_OPTIONS: ${{ matrix.os_java_options }} - - name: Upload coverage - if: ${{ matrix.os == 'ubuntu-latest' }} - uses: codecov/codecov-action@v1 - with: - flags: opensearch-notifications - directory: notifications/ - token: ${{ secrets.CODECOV_TOKEN }} - - name: Create Artifact Path run: | mkdir -p notifications-build/{notifications,notifications-core} From 0be0e400a5ba4567978aad17df14e1e683c202c1 Mon Sep 17 00:00:00 2001 From: Aniruddh <63553175+Noir01@users.noreply.github.com> Date: Thu, 2 Nov 2023 01:48:38 -0400 Subject: [PATCH 16/28] Added org.apache.logging.log4j:log4j-slf4j-impl to classpath (#791) * Added slf4j-jdk14.jar to classpath Adding binding for SLF4J that should fix StaticLoggerBinder being not loaded. Followed instructions from warning messages that appear. Signed-off-by: Noir <63553175+Noir01@users.noreply.github.com> * Undid 80fc198af89a44e90406c8de8245c94ab5a8f3d7 Removed slf4j-jdk14.jar from classpath Signed-off-by: Aniruddh <63553175+Noir01@users.noreply.github.com> * Added org.apache.logging.log4j:log4j-slf4j-impl to classpath Signed-off-by: Aniruddh <63553175+Noir01@users.noreply.github.com> --------- Signed-off-by: Noir <63553175+Noir01@users.noreply.github.com> Signed-off-by: Aniruddh <63553175+Noir01@users.noreply.github.com> Signed-off-by: Aniruddh Srivastava Signed-off-by: Aniruddh --- notifications/core/build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/notifications/core/build.gradle b/notifications/core/build.gradle index 1cef6633..f64402cf 100644 --- a/notifications/core/build.gradle +++ b/notifications/core/build.gradle @@ -144,6 +144,7 @@ dependencies { implementation "com.sun.mail:javax.mail:1.6.2" implementation "javax.activation:activation:1.1" implementation "org.slf4j:slf4j-api:${versions.slf4j}" //Needed for httpclient5 + implementation "org.apache.logging.log4j:log4j-slf4j-impl:${versions.log4j}" testImplementation( 'org.assertj:assertj-core:3.16.1', 'org.junit.jupiter:junit-jupiter-api:5.6.2', From ce888476c0599f41ff1bb4b01592b01f587618b1 Mon Sep 17 00:00:00 2001 From: Aniruddh Srivastava Date: Fri, 10 Nov 2023 00:28:59 -0500 Subject: [PATCH 17/28] Added Slack webhook URL validation regex Signed-off-by: Aniruddh Srivastava Signed-off-by: Aniruddh --- .../opensearch/notifications/index/ConfigIndexingActions.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/notifications/notifications/src/main/kotlin/org/opensearch/notifications/index/ConfigIndexingActions.kt b/notifications/notifications/src/main/kotlin/org/opensearch/notifications/index/ConfigIndexingActions.kt index 2ef5b93a..bf0a3293 100644 --- a/notifications/notifications/src/main/kotlin/org/opensearch/notifications/index/ConfigIndexingActions.kt +++ b/notifications/notifications/src/main/kotlin/org/opensearch/notifications/index/ConfigIndexingActions.kt @@ -56,7 +56,9 @@ object ConfigIndexingActions { @Suppress("UnusedPrivateMember") private fun validateSlackConfig(slack: Slack, user: User?) { - // TODO: URL validation with rules + require(slack.url.contains(Regex("https://hooks\\.slack\\.com/services"))) { + "Wrong Slack url. Should contain \"hooks.slack.com/services/\"" + } } @Suppress("UnusedPrivateMember") From f8a6c613ea4bbc4db3449f91410089b26533ba2e Mon Sep 17 00:00:00 2001 From: Aniruddh <63553175+noir01@users.noreply.github.com> Date: Fri, 10 Nov 2023 01:33:21 -0500 Subject: [PATCH 18/28] Replaced wrongly formatted dummy Slack URL with properly formatted dummy Slack URL Signed-off-by: Aniruddh Srivastava Signed-off-by: Aniruddh Srivastava Signed-off-by: Aniruddh --- .../integtest/config/ChimeNotificationConfigCrudIT.kt | 2 +- .../integtest/config/CreateNotificationConfigIT.kt | 2 +- .../integtest/config/SlackNotificationConfigCrudIT.kt | 6 +++--- .../integtest/config/WebhookNotificationConfigCrudIT.kt | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/ChimeNotificationConfigCrudIT.kt b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/ChimeNotificationConfigCrudIT.kt index 3707bb83..6b6d17e0 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/ChimeNotificationConfigCrudIT.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/ChimeNotificationConfigCrudIT.kt @@ -190,7 +190,7 @@ class ChimeNotificationConfigCrudIT : PluginRestTestCase() { "description":"this is a updated config description", "config_type":"slack", "is_enabled":"true", - "slack":{"url":"https://updated.domain.com/updated_slack_url#0987654321"} + "slack":{"url":"https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2"} } } """.trimIndent() diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/CreateNotificationConfigIT.kt b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/CreateNotificationConfigIT.kt index 64805e9d..3428c017 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/CreateNotificationConfigIT.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/CreateNotificationConfigIT.kt @@ -27,7 +27,7 @@ class CreateNotificationConfigIT : PluginRestTestCase() { fun `test Create slack notification config`() { // Create sample config request reference - val sampleSlack = Slack("https://domain.com/sample_slack_url#1234567890") + val sampleSlack = Slack("https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2") val referenceObject = NotificationConfig( "this is a sample config name", "this is a sample config description", diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/SlackNotificationConfigCrudIT.kt b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/SlackNotificationConfigCrudIT.kt index 86c64cf2..0b650c99 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/SlackNotificationConfigCrudIT.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/SlackNotificationConfigCrudIT.kt @@ -19,7 +19,7 @@ class SlackNotificationConfigCrudIT : PluginRestTestCase() { fun `test Create, Get, Update, Delete slack notification config using REST client`() { // Create sample config request reference - val sampleSlack = Slack("https://domain.com/sample_slack_url#1234567890") + val sampleSlack = Slack("https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2") val referenceObject = NotificationConfig( "this is a sample config name", "this is a sample config description", @@ -67,7 +67,7 @@ class SlackNotificationConfigCrudIT : PluginRestTestCase() { Thread.sleep(100) // Updated notification config object - val updatedSlack = Slack("https://updated.domain.com/updated_slack_url#0987654321") + val updatedSlack = Slack("https://hooks.slack.com/services/A654321/B7654321/L2K9J4I6H9G5F3E2D8C2B7A4") val updatedObject = NotificationConfig( "this is a updated config name", "this is a updated config description", @@ -126,7 +126,7 @@ class SlackNotificationConfigCrudIT : PluginRestTestCase() { fun `test Bad Request for multiple config data for Slack using REST Client`() { // Create sample config request reference - val sampleSlack = Slack("https://domain.com/sample_slack_url#1234567890") + val sampleSlack = Slack("https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2") val referenceObject = NotificationConfig( "this is a sample config name", "this is a sample config description", diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/WebhookNotificationConfigCrudIT.kt b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/WebhookNotificationConfigCrudIT.kt index 893a64fe..50076370 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/WebhookNotificationConfigCrudIT.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/WebhookNotificationConfigCrudIT.kt @@ -159,7 +159,7 @@ class WebhookNotificationConfigCrudIT : PluginRestTestCase() { "description":"${referenceObject.description}", "config_type":"webhook", "is_enabled":${referenceObject.isEnabled}, - "slack":{"url":"https://dummy.com"} + "slack":{"url":"https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2"} "webhook":{"url":"${(referenceObject.configData as Webhook).url}"} } } From de78a740d07162db660c35469ab0f2c04ebc277c Mon Sep 17 00:00:00 2001 From: Aniruddh Srivastava Date: Sat, 11 Nov 2023 03:13:21 -0500 Subject: [PATCH 19/28] Replaced more wrongly formatted dummy Slack URL with properly formatted dummy Slack URL Signed-off-by: Aniruddh Srivastava Signed-off-by: Aniruddh --- .../org/opensearch/integtest/IntegTestHelpers.kt | 2 +- .../opensearch/integtest/SecurityNotificationIT.kt | 12 ++++++------ .../config/ChimeNotificationConfigCrudIT.kt | 2 +- .../config/EmailNotificationConfigCrudIT.kt | 4 ++-- .../model/NotificationConfigDocTests.kt | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/IntegTestHelpers.kt b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/IntegTestHelpers.kt index fefc8a61..45bf01ac 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/IntegTestHelpers.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/IntegTestHelpers.kt @@ -116,7 +116,7 @@ fun getCreateNotificationRequestJsonString( .joinToString("") val configObjectString = when (configType) { ConfigType.SLACK -> """ - "slack":{"url":"https://slack.domain.com/sample_slack_url#$randomString"} + "slack":{"url":"https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2#$randomString"} """.trimIndent() ConfigType.CHIME -> """ "chime":{"url":"https://chime.domain.com/sample_chime_url#$randomString"} diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/SecurityNotificationIT.kt b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/SecurityNotificationIT.kt index e2d89769..ac35771b 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/SecurityNotificationIT.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/SecurityNotificationIT.kt @@ -54,7 +54,7 @@ class SecurityNotificationIT : PluginRestTestCase() { createUserWithCustomRole(user, password, NOTIFICATION_CREATE_CONFIG_ACCESS, "", ROLE_TO_PERMISSION_MAPPING[NOTIFICATION_CREATE_CONFIG_ACCESS]) // Create sample config request reference - val sampleSlack = Slack("https://domain.com/sample_slack_url#1234567890") + val sampleSlack = Slack("https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2") val referenceObject = NotificationConfig( "this is a sample config name", "this is a sample config description", @@ -97,7 +97,7 @@ class SecurityNotificationIT : PluginRestTestCase() { createUserWithCustomRole(user, password, NOTIFICATION_NO_ACCESS_ROLE, "", ROLE_TO_PERMISSION_MAPPING[NOTIFICATION_NO_ACCESS_ROLE]) // Create sample config request reference - val sampleSlack = Slack("https://domain.com/sample_slack_url#1234567890") + val sampleSlack = Slack("https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2") val referenceObject = NotificationConfig( "this is a sample config name", "this is a sample config description", @@ -133,7 +133,7 @@ class SecurityNotificationIT : PluginRestTestCase() { createUserWithCustomRole(user, password, NOTIFICATION_UPDATE_CONFIG_ACCESS, "", ROLE_TO_PERMISSION_MAPPING[NOTIFICATION_UPDATE_CONFIG_ACCESS]) // Create sample config request reference - val sampleSlack = Slack("https://domain.com/sample_slack_url#1234567890") + val sampleSlack = Slack("https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2") val referenceObject = NotificationConfig( "this is a sample config name", "this is a sample config description", @@ -210,7 +210,7 @@ class SecurityNotificationIT : PluginRestTestCase() { createUserWithCustomRole(user, password, NOTIFICATION_NO_ACCESS_ROLE, "", ROLE_TO_PERMISSION_MAPPING[NOTIFICATION_NO_ACCESS_ROLE]) // Create sample config request reference - val sampleSlack = Slack("https://domain.com/sample_slack_url#1234567890") + val sampleSlack = Slack("https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2") val referenceObject = NotificationConfig( "this is a sample config name", "this is a sample config description", @@ -246,7 +246,7 @@ class SecurityNotificationIT : PluginRestTestCase() { createUserWithCustomRole(user, password, NOTIFICATION_GET_CONFIG_ACCESS, "", ROLE_TO_PERMISSION_MAPPING[NOTIFICATION_GET_CONFIG_ACCESS]) // Create sample config request reference - val sampleSlack = Slack("https://domain.com/sample_slack_url#1234567890") + val sampleSlack = Slack("https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2") val referenceObject = NotificationConfig( "this is a sample config name", "this is a sample config description", @@ -302,7 +302,7 @@ class SecurityNotificationIT : PluginRestTestCase() { createUserWithCustomRole(user, password, NOTIFICATION_DELETE_CONFIG_ACCESS, "", ROLE_TO_PERMISSION_MAPPING[NOTIFICATION_DELETE_CONFIG_ACCESS]) // Create sample config request reference - val sampleSlack = Slack("https://domain.com/sample_slack_url#1234567890") + val sampleSlack = Slack("https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2") val referenceObject = NotificationConfig( "this is a sample config name", "this is a sample config description", diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/ChimeNotificationConfigCrudIT.kt b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/ChimeNotificationConfigCrudIT.kt index 6b6d17e0..bb41ea02 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/ChimeNotificationConfigCrudIT.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/ChimeNotificationConfigCrudIT.kt @@ -142,7 +142,7 @@ class ChimeNotificationConfigCrudIT : PluginRestTestCase() { "description":"${referenceObject.description}", "config_type":"chime", "is_enabled":${referenceObject.isEnabled}, - "slack":{"url":"https://dummy.com"} + "slack":{"url":"https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2"} "chime":{"url":"${(referenceObject.configData as Chime).url}"} } } diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/EmailNotificationConfigCrudIT.kt b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/EmailNotificationConfigCrudIT.kt index aed06e9f..fcb599a7 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/EmailNotificationConfigCrudIT.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/EmailNotificationConfigCrudIT.kt @@ -907,7 +907,7 @@ class EmailNotificationConfigCrudIT : PluginRestTestCase() { "description":"${smtpAccountConfig.description}", "config_type":"smtp_account", "is_enabled":${smtpAccountConfig.isEnabled}, - "slack": {"url": "https://dummy.com"}, + "slack": {"url": "https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2"}, "smtp_account":{ "host":"${sampleSmtpAccount.host}", "port":"${sampleSmtpAccount.port}", @@ -948,7 +948,7 @@ class EmailNotificationConfigCrudIT : PluginRestTestCase() { "description":"${emailConfig.description}", "config_type":"email", "is_enabled":${emailConfig.isEnabled}, - "slack":{"url": "https://dummy.com"}, + "slack":{"url": "https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2"}, "email":{ "email_account_id":"${sampleEmail.emailAccountID}", "default_recipients":[ diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/notifications/model/NotificationConfigDocTests.kt b/notifications/notifications/src/test/kotlin/org/opensearch/notifications/model/NotificationConfigDocTests.kt index 0f36945e..553499b0 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/notifications/model/NotificationConfigDocTests.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/notifications/model/NotificationConfigDocTests.kt @@ -25,7 +25,7 @@ internal class NotificationConfigDocTests { createdTimeMs, listOf("br1", "br2", "br3") ) - val sampleSlack = Slack("https://domain.com/sample_url#1234567890") + val sampleSlack = Slack("https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2") val config = NotificationConfig( "name", "description", From b4977cb96645add691831145023743b27c80b046 Mon Sep 17 00:00:00 2001 From: Aniruddh Srivastava Date: Sat, 11 Nov 2023 03:30:17 -0500 Subject: [PATCH 20/28] Replaced even more wrongly formatted dummy Slack URL with properly formatted dummy Slack URL Signed-off-by: Aniruddh Srivastava Signed-off-by: Aniruddh --- .../integtest/bwc/NotificationsBackwardsCompatibilityIT.kt | 2 +- .../notifications/model/NotificationConfigDocTests.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/bwc/NotificationsBackwardsCompatibilityIT.kt b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/bwc/NotificationsBackwardsCompatibilityIT.kt index 6e7eee5f..3ba6b86f 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/bwc/NotificationsBackwardsCompatibilityIT.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/bwc/NotificationsBackwardsCompatibilityIT.kt @@ -103,7 +103,7 @@ class NotificationsBackwardsCompatibilityIT : PluginRestTestCase() { "description": "This is a sample config description $configId", "config_type": "slack", "is_enabled": true, - "slack": { "url": "https://slack.domain.com/sample_slack_url#$configId" } + "slack": { "url": "https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2#$configId" } } } """.trimIndent() diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/notifications/model/NotificationConfigDocTests.kt b/notifications/notifications/src/test/kotlin/org/opensearch/notifications/model/NotificationConfigDocTests.kt index 553499b0..f36eebef 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/notifications/model/NotificationConfigDocTests.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/notifications/model/NotificationConfigDocTests.kt @@ -47,7 +47,7 @@ internal class NotificationConfigDocTests { createdTimeMs, listOf("br1", "br2", "br3") ) - val sampleSlack = Slack("https://domain.com/sample_url#1234567890") + val sampleSlack = Slack("https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2") val config = NotificationConfig( "name", "description", From f606953b2ac36a48b763c5e5fc44fd57a502800d Mon Sep 17 00:00:00 2001 From: Aniruddh Date: Wed, 15 Nov 2023 01:27:49 -0500 Subject: [PATCH 21/28] Replace path of mock Slack URL with `sample_slack_url` Signed-off-by: Aniruddh Signed-off-by: Aniruddh --- .../org/opensearch/integtest/IntegTestHelpers.kt | 2 +- .../opensearch/integtest/SecurityNotificationIT.kt | 12 ++++++------ .../bwc/NotificationsBackwardsCompatibilityIT.kt | 2 +- .../config/ChimeNotificationConfigCrudIT.kt | 4 ++-- .../integtest/config/CreateNotificationConfigIT.kt | 2 +- .../config/EmailNotificationConfigCrudIT.kt | 4 ++-- .../config/SlackNotificationConfigCrudIT.kt | 6 +++--- .../config/WebhookNotificationConfigCrudIT.kt | 2 +- .../model/NotificationConfigDocTests.kt | 4 ++-- 9 files changed, 19 insertions(+), 19 deletions(-) diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/IntegTestHelpers.kt b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/IntegTestHelpers.kt index 45bf01ac..da8e44ed 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/IntegTestHelpers.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/IntegTestHelpers.kt @@ -116,7 +116,7 @@ fun getCreateNotificationRequestJsonString( .joinToString("") val configObjectString = when (configType) { ConfigType.SLACK -> """ - "slack":{"url":"https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2#$randomString"} + "slack":{"url":"https://hooks.slack.com/services/sample_slack_url#$randomString"} """.trimIndent() ConfigType.CHIME -> """ "chime":{"url":"https://chime.domain.com/sample_chime_url#$randomString"} diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/SecurityNotificationIT.kt b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/SecurityNotificationIT.kt index ac35771b..fd185451 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/SecurityNotificationIT.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/SecurityNotificationIT.kt @@ -54,7 +54,7 @@ class SecurityNotificationIT : PluginRestTestCase() { createUserWithCustomRole(user, password, NOTIFICATION_CREATE_CONFIG_ACCESS, "", ROLE_TO_PERMISSION_MAPPING[NOTIFICATION_CREATE_CONFIG_ACCESS]) // Create sample config request reference - val sampleSlack = Slack("https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2") + val sampleSlack = Slack("https://hooks.slack.com/services/sample_slack_url") val referenceObject = NotificationConfig( "this is a sample config name", "this is a sample config description", @@ -97,7 +97,7 @@ class SecurityNotificationIT : PluginRestTestCase() { createUserWithCustomRole(user, password, NOTIFICATION_NO_ACCESS_ROLE, "", ROLE_TO_PERMISSION_MAPPING[NOTIFICATION_NO_ACCESS_ROLE]) // Create sample config request reference - val sampleSlack = Slack("https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2") + val sampleSlack = Slack("https://hooks.slack.com/services/sample_slack_url") val referenceObject = NotificationConfig( "this is a sample config name", "this is a sample config description", @@ -133,7 +133,7 @@ class SecurityNotificationIT : PluginRestTestCase() { createUserWithCustomRole(user, password, NOTIFICATION_UPDATE_CONFIG_ACCESS, "", ROLE_TO_PERMISSION_MAPPING[NOTIFICATION_UPDATE_CONFIG_ACCESS]) // Create sample config request reference - val sampleSlack = Slack("https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2") + val sampleSlack = Slack("https://hooks.slack.com/services/sample_slack_url") val referenceObject = NotificationConfig( "this is a sample config name", "this is a sample config description", @@ -210,7 +210,7 @@ class SecurityNotificationIT : PluginRestTestCase() { createUserWithCustomRole(user, password, NOTIFICATION_NO_ACCESS_ROLE, "", ROLE_TO_PERMISSION_MAPPING[NOTIFICATION_NO_ACCESS_ROLE]) // Create sample config request reference - val sampleSlack = Slack("https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2") + val sampleSlack = Slack("https://hooks.slack.com/services/sample_slack_url") val referenceObject = NotificationConfig( "this is a sample config name", "this is a sample config description", @@ -246,7 +246,7 @@ class SecurityNotificationIT : PluginRestTestCase() { createUserWithCustomRole(user, password, NOTIFICATION_GET_CONFIG_ACCESS, "", ROLE_TO_PERMISSION_MAPPING[NOTIFICATION_GET_CONFIG_ACCESS]) // Create sample config request reference - val sampleSlack = Slack("https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2") + val sampleSlack = Slack("https://hooks.slack.com/services/sample_slack_url") val referenceObject = NotificationConfig( "this is a sample config name", "this is a sample config description", @@ -302,7 +302,7 @@ class SecurityNotificationIT : PluginRestTestCase() { createUserWithCustomRole(user, password, NOTIFICATION_DELETE_CONFIG_ACCESS, "", ROLE_TO_PERMISSION_MAPPING[NOTIFICATION_DELETE_CONFIG_ACCESS]) // Create sample config request reference - val sampleSlack = Slack("https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2") + val sampleSlack = Slack("https://hooks.slack.com/services/sample_slack_url") val referenceObject = NotificationConfig( "this is a sample config name", "this is a sample config description", diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/bwc/NotificationsBackwardsCompatibilityIT.kt b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/bwc/NotificationsBackwardsCompatibilityIT.kt index 3ba6b86f..5ae57fb4 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/bwc/NotificationsBackwardsCompatibilityIT.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/bwc/NotificationsBackwardsCompatibilityIT.kt @@ -103,7 +103,7 @@ class NotificationsBackwardsCompatibilityIT : PluginRestTestCase() { "description": "This is a sample config description $configId", "config_type": "slack", "is_enabled": true, - "slack": { "url": "https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2#$configId" } + "slack": { "url": "https://hooks.slack.com/services/sample_slack_url#$configId" } } } """.trimIndent() diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/ChimeNotificationConfigCrudIT.kt b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/ChimeNotificationConfigCrudIT.kt index bb41ea02..744429ef 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/ChimeNotificationConfigCrudIT.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/ChimeNotificationConfigCrudIT.kt @@ -142,7 +142,7 @@ class ChimeNotificationConfigCrudIT : PluginRestTestCase() { "description":"${referenceObject.description}", "config_type":"chime", "is_enabled":${referenceObject.isEnabled}, - "slack":{"url":"https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2"} + "slack":{"url":"https://hooks.slack.com/services/sample_slack_url"} "chime":{"url":"${(referenceObject.configData as Chime).url}"} } } @@ -190,7 +190,7 @@ class ChimeNotificationConfigCrudIT : PluginRestTestCase() { "description":"this is a updated config description", "config_type":"slack", "is_enabled":"true", - "slack":{"url":"https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2"} + "slack":{"url":"https://hooks.slack.com/services/sample_slack_url"} } } """.trimIndent() diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/CreateNotificationConfigIT.kt b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/CreateNotificationConfigIT.kt index 3428c017..163388c7 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/CreateNotificationConfigIT.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/CreateNotificationConfigIT.kt @@ -27,7 +27,7 @@ class CreateNotificationConfigIT : PluginRestTestCase() { fun `test Create slack notification config`() { // Create sample config request reference - val sampleSlack = Slack("https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2") + val sampleSlack = Slack("https://hooks.slack.com/services/sample_slack_url") val referenceObject = NotificationConfig( "this is a sample config name", "this is a sample config description", diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/EmailNotificationConfigCrudIT.kt b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/EmailNotificationConfigCrudIT.kt index fcb599a7..c8b24b38 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/EmailNotificationConfigCrudIT.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/EmailNotificationConfigCrudIT.kt @@ -907,7 +907,7 @@ class EmailNotificationConfigCrudIT : PluginRestTestCase() { "description":"${smtpAccountConfig.description}", "config_type":"smtp_account", "is_enabled":${smtpAccountConfig.isEnabled}, - "slack": {"url": "https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2"}, + "slack": {"url": "https://hooks.slack.com/services/sample_slack_url"}, "smtp_account":{ "host":"${sampleSmtpAccount.host}", "port":"${sampleSmtpAccount.port}", @@ -948,7 +948,7 @@ class EmailNotificationConfigCrudIT : PluginRestTestCase() { "description":"${emailConfig.description}", "config_type":"email", "is_enabled":${emailConfig.isEnabled}, - "slack":{"url": "https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2"}, + "slack":{"url": "https://hooks.slack.com/services/sample_slack_url"}, "email":{ "email_account_id":"${sampleEmail.emailAccountID}", "default_recipients":[ diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/SlackNotificationConfigCrudIT.kt b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/SlackNotificationConfigCrudIT.kt index 0b650c99..c6aeea07 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/SlackNotificationConfigCrudIT.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/SlackNotificationConfigCrudIT.kt @@ -19,7 +19,7 @@ class SlackNotificationConfigCrudIT : PluginRestTestCase() { fun `test Create, Get, Update, Delete slack notification config using REST client`() { // Create sample config request reference - val sampleSlack = Slack("https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2") + val sampleSlack = Slack("https://hooks.slack.com/services/sample_slack_url") val referenceObject = NotificationConfig( "this is a sample config name", "this is a sample config description", @@ -67,7 +67,7 @@ class SlackNotificationConfigCrudIT : PluginRestTestCase() { Thread.sleep(100) // Updated notification config object - val updatedSlack = Slack("https://hooks.slack.com/services/A654321/B7654321/L2K9J4I6H9G5F3E2D8C2B7A4") + val updatedSlack = Slack("https://hooks.slack.com/services/updated_slack_url") val updatedObject = NotificationConfig( "this is a updated config name", "this is a updated config description", @@ -126,7 +126,7 @@ class SlackNotificationConfigCrudIT : PluginRestTestCase() { fun `test Bad Request for multiple config data for Slack using REST Client`() { // Create sample config request reference - val sampleSlack = Slack("https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2") + val sampleSlack = Slack("https://hooks.slack.com/services/sample_slack_url") val referenceObject = NotificationConfig( "this is a sample config name", "this is a sample config description", diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/WebhookNotificationConfigCrudIT.kt b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/WebhookNotificationConfigCrudIT.kt index 50076370..1977a040 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/WebhookNotificationConfigCrudIT.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/WebhookNotificationConfigCrudIT.kt @@ -159,7 +159,7 @@ class WebhookNotificationConfigCrudIT : PluginRestTestCase() { "description":"${referenceObject.description}", "config_type":"webhook", "is_enabled":${referenceObject.isEnabled}, - "slack":{"url":"https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2"} + "slack":{"url":"https://hooks.slack.com/services/sample_slack_url"} "webhook":{"url":"${(referenceObject.configData as Webhook).url}"} } } diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/notifications/model/NotificationConfigDocTests.kt b/notifications/notifications/src/test/kotlin/org/opensearch/notifications/model/NotificationConfigDocTests.kt index f36eebef..ab0d5129 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/notifications/model/NotificationConfigDocTests.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/notifications/model/NotificationConfigDocTests.kt @@ -25,7 +25,7 @@ internal class NotificationConfigDocTests { createdTimeMs, listOf("br1", "br2", "br3") ) - val sampleSlack = Slack("https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2") + val sampleSlack = Slack("https://hooks.slack.com/services/sample_slack_url") val config = NotificationConfig( "name", "description", @@ -47,7 +47,7 @@ internal class NotificationConfigDocTests { createdTimeMs, listOf("br1", "br2", "br3") ) - val sampleSlack = Slack("https://hooks.slack.com/services/A123456/B1234567/A1B2C3D4E5F6G7H8I9J0K1L2") + val sampleSlack = Slack("https://hooks.slack.com/services/sample_slack_url") val config = NotificationConfig( "name", "description", From bffe5d66a8bc5ad92f03f4ce1df14b317d3fa8af Mon Sep 17 00:00:00 2001 From: Aniruddh Date: Wed, 15 Nov 2023 01:28:51 -0500 Subject: [PATCH 22/28] Remove slackId from domainIds Signed-off-by: Aniruddh Signed-off-by: Aniruddh --- .../opensearch/integtest/config/QueryNotificationConfigIT.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/QueryNotificationConfigIT.kt b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/QueryNotificationConfigIT.kt index 47efbe32..6a8451ed 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/QueryNotificationConfigIT.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/QueryNotificationConfigIT.kt @@ -627,7 +627,7 @@ class QueryNotificationConfigIT : PluginRestTestCase() { val urlIds = setOf(slackId, chimeId, microsoftTeamsId, webhookId) val recipientIds = setOf(emailGroupId) val fromIds = setOf(emailGroupId, smtpAccountId) - val domainIds = setOf(slackId, chimeId, microsoftTeamsId, webhookId, smtpAccountId) + val domainIds = setOf(chimeId, microsoftTeamsId, webhookId, smtpAccountId) Thread.sleep(1000) // Get notification configs using query=slack @@ -702,7 +702,7 @@ class QueryNotificationConfigIT : PluginRestTestCase() { val urlIds = setOf(slackId, chimeId, microsoftTeamsId, webhookId) val recipientIds = setOf(emailGroupId) val fromIds = setOf(emailGroupId, smtpAccountId) - val domainIds = setOf(slackId, chimeId, microsoftTeamsId, webhookId, smtpAccountId) + val domainIds = setOf(chimeId, microsoftTeamsId, webhookId, smtpAccountId) Thread.sleep(1000) // Get notification configs using text_query=slack should not return any item From b56f436328c2deca1293caf2489f22ddf9a13d0c Mon Sep 17 00:00:00 2001 From: Aniruddh Date: Wed, 15 Nov 2023 01:37:03 -0500 Subject: [PATCH 23/28] Replace wrongly formatted dummy Slack URL with properly formatted dummy Slack URL Signed-off-by: Aniruddh Signed-off-by: Aniruddh --- .../notifications/model/NotificationConfigDocTests.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/notifications/model/NotificationConfigDocTests.kt b/notifications/notifications/src/test/kotlin/org/opensearch/notifications/model/NotificationConfigDocTests.kt index ab0d5129..24a8baa8 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/notifications/model/NotificationConfigDocTests.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/notifications/model/NotificationConfigDocTests.kt @@ -67,7 +67,7 @@ internal class NotificationConfigDocTests { "description":"description", "config_type":"slack", "is_enabled":true, - "slack":{"url":"https://domain.com/sample_url#1234567890"} + "slack":{"url":"https://hooks.slack.com/services/sample_slack_url"} }, "extra_field_1":["extra", "value"], "extra_field_2":{"extra":"value"}, From fe1189dbe3c785eaa75c5ba4a17f8a7203f62724 Mon Sep 17 00:00:00 2001 From: Aniruddh Date: Thu, 16 Nov 2023 01:23:07 -0500 Subject: [PATCH 24/28] Add tests for wrong Slack URLs Signed-off-by: Aniruddh --- .../config/SlackNotificationConfigCrudIT.kt | 43 ++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/SlackNotificationConfigCrudIT.kt b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/SlackNotificationConfigCrudIT.kt index c6aeea07..2b6910ea 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/SlackNotificationConfigCrudIT.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/SlackNotificationConfigCrudIT.kt @@ -6,11 +6,16 @@ package org.opensearch.integtest.config import org.junit.Assert +import org.opensearch.client.Request +import org.opensearch.client.RequestOptions +import org.opensearch.client.ResponseException import org.opensearch.commons.notifications.model.ConfigType -import org.opensearch.commons.notifications.model.NotificationConfig import org.opensearch.commons.notifications.model.Slack +import org.opensearch.commons.notifications.model.NotificationConfig import org.opensearch.core.rest.RestStatus import org.opensearch.integtest.PluginRestTestCase +import org.opensearch.integtest.getResponseBody +import org.opensearch.integtest.jsonify import org.opensearch.notifications.NotificationPlugin.Companion.PLUGIN_BASE_URI import org.opensearch.notifications.verifySingleConfigEquals import org.opensearch.rest.RestRequest @@ -155,4 +160,40 @@ class SlackNotificationConfigCrudIT : PluginRestTestCase() { RestStatus.BAD_REQUEST.status ) } + + fun `test create config with wrong Slack url and get error text`() { + val sampleSlack = Slack("https://webhook.slack.com/services/sample_slack_url") + val referenceObject = NotificationConfig( + "this is a sample config name", + "this is a sample config description", + ConfigType.SLACK, + isEnabled = true, + configData = sampleSlack + ) + val createRequestJsonString = """ + { + "config":{ + "name":"${referenceObject.name}", + "description":"${referenceObject.description}", + "config_type":"slack", + "is_enabled":${referenceObject.isEnabled}, + "slack":{"url":"${(referenceObject.configData as Slack).url}"} + } + } + """.trimIndent() + val response = try { + val request = Request(RestRequest.Method.POST.name, "$PLUGIN_BASE_URI/configs") + request.setJsonEntity(createRequestJsonString) + val restOptionsBuilder = RequestOptions.DEFAULT.toBuilder() + restOptionsBuilder.addHeader("Content-Type", "application/json") + request.setOptions(restOptionsBuilder) + client().performRequest(request) + fail("Expected wrong Slack URL.") + } catch (exception: ResponseException) { + Assert.assertEquals( + "Wrong Slack url. Should contain \"hooks.slack.com/services/\"", + jsonify(getResponseBody(exception.response))["error"].asJsonObject["reason"].asString + ) + } + } } From 8c17f39775c2c8dd25e4fdcae9865d99b2c39305 Mon Sep 17 00:00:00 2001 From: Aniruddh Date: Thu, 16 Nov 2023 02:19:12 -0500 Subject: [PATCH 25/28] Add validation tests for Slack URL Signed-off-by: Aniruddh --- .../index/ConfigIndexingActionsTests.kt | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/notifications/index/ConfigIndexingActionsTests.kt b/notifications/notifications/src/test/kotlin/org/opensearch/notifications/index/ConfigIndexingActionsTests.kt index d2c6b0ee..1731cbef 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/notifications/index/ConfigIndexingActionsTests.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/notifications/index/ConfigIndexingActionsTests.kt @@ -8,6 +8,7 @@ import org.junit.jupiter.api.BeforeAll import org.junit.jupiter.api.Test import org.opensearch.commons.authuser.User import org.opensearch.commons.notifications.model.MicrosoftTeams +import org.opensearch.commons.notifications.model.Slack import java.lang.reflect.Method import kotlin.test.assertFails @@ -28,8 +29,28 @@ class ConfigIndexingActionsTests { assertFails { validateMicrosoftTeamsConfig.invoke(ConfigIndexingActions, microsoftTeams, user) } } + @Test + fun `test validate slack`() { + val user = User() + var slack = Slack("https://hooks.slack.com/services/123456789/123456789/123456789") + validateSlackConfig.invoke(ConfigIndexingActions, slack, user) + slack = Slack("https://hooks.slack.com/services/samplesamplesamplesamplesamplesamplesamplesamplesample") + validateSlackConfig.invoke(ConfigIndexingActions, slack, user) + slack = Slack("http://hooks.slack.com/services/123456789/123456789/123456789/123456789") + assertFails { validateSlackConfig.invoke(ConfigIndexingActions, slack, user) } + slack = Slack("https://slack.com/services/123456789/123456789/123456789/123456789") + assertFails { validateSlackConfig.invoke(ConfigIndexingActions, slack, user) } + slack = Slack("https://hooks.slack.com/123456789/123456789/123456789/123456789/123456789") + assertFails { validateSlackConfig.invoke(ConfigIndexingActions, slack, user) } + slack = Slack("https://hook.slack.com/services/123456789/123456789/123456789/123456789/123456789") + assertFails { validateSlackConfig.invoke(ConfigIndexingActions, slack, user) } + slack = Slack("https://hooks.slack.com/") + assertFails { validateSlackConfig.invoke(ConfigIndexingActions, slack, user) } + } + companion object { private lateinit var validateMicrosoftTeamsConfig: Method + private lateinit var validateSlackConfig: Method @BeforeAll @JvmStatic @@ -38,8 +59,12 @@ class ConfigIndexingActionsTests { validateMicrosoftTeamsConfig = ConfigIndexingActions::class.java.getDeclaredMethod( "validateMicrosoftTeamsConfig", MicrosoftTeams::class.java, User::class.java ) + validateSlackConfig = ConfigIndexingActions::class.java.getDeclaredMethod( + "validateSlackConfig", Slack::class.java, User::class.java + ) validateMicrosoftTeamsConfig.isAccessible = true + validateSlackConfig.isAccessible = true } } } From 45823a6c9be2d7656f721f596d53250479e4241f Mon Sep 17 00:00:00 2001 From: Aniruddh Date: Thu, 16 Nov 2023 02:19:42 -0500 Subject: [PATCH 26/28] Format Signed-off-by: Aniruddh --- .../integtest/config/SlackNotificationConfigCrudIT.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/SlackNotificationConfigCrudIT.kt b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/SlackNotificationConfigCrudIT.kt index 2b6910ea..c2bdb823 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/SlackNotificationConfigCrudIT.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/SlackNotificationConfigCrudIT.kt @@ -10,8 +10,8 @@ import org.opensearch.client.Request import org.opensearch.client.RequestOptions import org.opensearch.client.ResponseException import org.opensearch.commons.notifications.model.ConfigType -import org.opensearch.commons.notifications.model.Slack import org.opensearch.commons.notifications.model.NotificationConfig +import org.opensearch.commons.notifications.model.Slack import org.opensearch.core.rest.RestStatus import org.opensearch.integtest.PluginRestTestCase import org.opensearch.integtest.getResponseBody From 84c17ed0dd95a2c3bc424017c03fd96aa4df811e Mon Sep 17 00:00:00 2001 From: Aniruddh Date: Thu, 16 Nov 2023 02:37:18 -0500 Subject: [PATCH 27/28] GovSlack apps can use the slack-gov.com domain Signed-off-by: Aniruddh --- .../org/opensearch/notifications/index/ConfigIndexingActions.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/notifications/notifications/src/main/kotlin/org/opensearch/notifications/index/ConfigIndexingActions.kt b/notifications/notifications/src/main/kotlin/org/opensearch/notifications/index/ConfigIndexingActions.kt index bf0a3293..5a228600 100644 --- a/notifications/notifications/src/main/kotlin/org/opensearch/notifications/index/ConfigIndexingActions.kt +++ b/notifications/notifications/src/main/kotlin/org/opensearch/notifications/index/ConfigIndexingActions.kt @@ -56,7 +56,7 @@ object ConfigIndexingActions { @Suppress("UnusedPrivateMember") private fun validateSlackConfig(slack: Slack, user: User?) { - require(slack.url.contains(Regex("https://hooks\\.slack\\.com/services"))) { + require(slack.url.contains(Regex("https://hooks\\.(?:gov-)?slack\\.com/services"))) { "Wrong Slack url. Should contain \"hooks.slack.com/services/\"" } } From aa3b636bfeb6c863a8df594924df50ca5bf1b7af Mon Sep 17 00:00:00 2001 From: Aniruddh Date: Thu, 16 Nov 2023 02:56:10 -0500 Subject: [PATCH 28/28] Add validation for gov-slack.com domain Signed-off-by: Aniruddh --- .../notifications/index/ConfigIndexingActions.kt | 2 +- .../config/SlackNotificationConfigCrudIT.kt | 2 +- .../index/ConfigIndexingActionsTests.kt | 14 ++++++++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/notifications/notifications/src/main/kotlin/org/opensearch/notifications/index/ConfigIndexingActions.kt b/notifications/notifications/src/main/kotlin/org/opensearch/notifications/index/ConfigIndexingActions.kt index 5a228600..01e76dfa 100644 --- a/notifications/notifications/src/main/kotlin/org/opensearch/notifications/index/ConfigIndexingActions.kt +++ b/notifications/notifications/src/main/kotlin/org/opensearch/notifications/index/ConfigIndexingActions.kt @@ -57,7 +57,7 @@ object ConfigIndexingActions { @Suppress("UnusedPrivateMember") private fun validateSlackConfig(slack: Slack, user: User?) { require(slack.url.contains(Regex("https://hooks\\.(?:gov-)?slack\\.com/services"))) { - "Wrong Slack url. Should contain \"hooks.slack.com/services/\"" + "Wrong Slack url. Should contain \"hooks.slack.com/services/\" or \"hooks.gov-slack.com/services/\"" } } diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/SlackNotificationConfigCrudIT.kt b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/SlackNotificationConfigCrudIT.kt index c2bdb823..5bbac40c 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/SlackNotificationConfigCrudIT.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/integtest/config/SlackNotificationConfigCrudIT.kt @@ -191,7 +191,7 @@ class SlackNotificationConfigCrudIT : PluginRestTestCase() { fail("Expected wrong Slack URL.") } catch (exception: ResponseException) { Assert.assertEquals( - "Wrong Slack url. Should contain \"hooks.slack.com/services/\"", + "Wrong Slack url. Should contain \"hooks.slack.com/services/\" or \"hooks.gov-slack.com/services/\"", jsonify(getResponseBody(exception.response))["error"].asJsonObject["reason"].asString ) } diff --git a/notifications/notifications/src/test/kotlin/org/opensearch/notifications/index/ConfigIndexingActionsTests.kt b/notifications/notifications/src/test/kotlin/org/opensearch/notifications/index/ConfigIndexingActionsTests.kt index 1731cbef..ddbe104e 100644 --- a/notifications/notifications/src/test/kotlin/org/opensearch/notifications/index/ConfigIndexingActionsTests.kt +++ b/notifications/notifications/src/test/kotlin/org/opensearch/notifications/index/ConfigIndexingActionsTests.kt @@ -34,18 +34,32 @@ class ConfigIndexingActionsTests { val user = User() var slack = Slack("https://hooks.slack.com/services/123456789/123456789/123456789") validateSlackConfig.invoke(ConfigIndexingActions, slack, user) + slack = Slack("https://hooks.gov-slack.com/services/123456789/123456789/123456789") + validateSlackConfig.invoke(ConfigIndexingActions, slack, user) slack = Slack("https://hooks.slack.com/services/samplesamplesamplesamplesamplesamplesamplesamplesample") validateSlackConfig.invoke(ConfigIndexingActions, slack, user) + slack = Slack("https://hooks.gov-slack.com/services/samplesamplesamplesamplesamplesamplesamplesamplesample") + validateSlackConfig.invoke(ConfigIndexingActions, slack, user) slack = Slack("http://hooks.slack.com/services/123456789/123456789/123456789/123456789") assertFails { validateSlackConfig.invoke(ConfigIndexingActions, slack, user) } + slack = Slack("http://hooks.gov-slack.com/services/123456789/123456789/123456789/123456789") + assertFails { validateSlackConfig.invoke(ConfigIndexingActions, slack, user) } slack = Slack("https://slack.com/services/123456789/123456789/123456789/123456789") assertFails { validateSlackConfig.invoke(ConfigIndexingActions, slack, user) } + slack = Slack("https://gov-slack.com/services/123456789/123456789/123456789/123456789") + assertFails { validateSlackConfig.invoke(ConfigIndexingActions, slack, user) } slack = Slack("https://hooks.slack.com/123456789/123456789/123456789/123456789/123456789") assertFails { validateSlackConfig.invoke(ConfigIndexingActions, slack, user) } + slack = Slack("https://hooks.gov-slack.com/123456789/123456789/123456789/123456789/123456789") + assertFails { validateSlackConfig.invoke(ConfigIndexingActions, slack, user) } slack = Slack("https://hook.slack.com/services/123456789/123456789/123456789/123456789/123456789") assertFails { validateSlackConfig.invoke(ConfigIndexingActions, slack, user) } + slack = Slack("https://hook.gov-slack.com/services/123456789/123456789/123456789/123456789/123456789") + assertFails { validateSlackConfig.invoke(ConfigIndexingActions, slack, user) } slack = Slack("https://hooks.slack.com/") assertFails { validateSlackConfig.invoke(ConfigIndexingActions, slack, user) } + slack = Slack("https://hooks.gov-slack.com/") + assertFails { validateSlackConfig.invoke(ConfigIndexingActions, slack, user) } } companion object {