diff --git a/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt b/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt index 74fcc600..9c1f0573 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/NotificationConstants.kt @@ -69,4 +69,5 @@ object NotificationConstants { const val PLUGIN_FEATURES_TAG = "plugin_features" const val DEFAULT_MAX_ITEMS = 1000 + const val ENCRYPTION_PREFIX = "enc:" } diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/Chime.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/Chime.kt index ee1c5aa8..0e0c80ee 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/Chime.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/Chime.kt @@ -4,6 +4,7 @@ */ package org.opensearch.commons.notifications.model +import org.opensearch.commons.notifications.NotificationConstants.ENCRYPTION_PREFIX import org.opensearch.commons.notifications.NotificationConstants.URL_TAG import org.opensearch.commons.utils.logger import org.opensearch.commons.utils.validateUrl @@ -26,7 +27,9 @@ data class Chime( init { require(!Strings.isNullOrEmpty(url)) { "URL is null or empty" } - validateUrl(url) + if (!url.startsWith(ENCRYPTION_PREFIX)) { + validateUrl(url) + } } companion object { diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/MicrosoftTeams.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/MicrosoftTeams.kt index 48e32f15..2391d463 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/MicrosoftTeams.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/MicrosoftTeams.kt @@ -4,6 +4,7 @@ */ package org.opensearch.commons.notifications.model +import org.opensearch.commons.notifications.NotificationConstants.ENCRYPTION_PREFIX import org.opensearch.commons.notifications.NotificationConstants.URL_TAG import org.opensearch.commons.utils.logger import org.opensearch.commons.utils.validateUrl @@ -26,7 +27,9 @@ data class MicrosoftTeams( init { require(!Strings.isNullOrEmpty(url)) { "URL is null or empty" } - validateUrl(url) + if (!url.startsWith(ENCRYPTION_PREFIX)) { + validateUrl(url) + } } companion object { diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/Slack.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/Slack.kt index b4433b95..b63e2f07 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/Slack.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/Slack.kt @@ -4,6 +4,7 @@ */ package org.opensearch.commons.notifications.model +import org.opensearch.commons.notifications.NotificationConstants.ENCRYPTION_PREFIX import org.opensearch.commons.notifications.NotificationConstants.URL_TAG import org.opensearch.commons.utils.logger import org.opensearch.commons.utils.validateUrl @@ -26,7 +27,9 @@ data class Slack( init { require(!Strings.isNullOrEmpty(url)) { "URL is null or empty" } - validateUrl(url) + if (!url.startsWith(ENCRYPTION_PREFIX)) { + validateUrl(url) + } } companion object { diff --git a/src/main/kotlin/org/opensearch/commons/notifications/model/Webhook.kt b/src/main/kotlin/org/opensearch/commons/notifications/model/Webhook.kt index e48f29f4..83f0b37f 100644 --- a/src/main/kotlin/org/opensearch/commons/notifications/model/Webhook.kt +++ b/src/main/kotlin/org/opensearch/commons/notifications/model/Webhook.kt @@ -4,6 +4,7 @@ */ package org.opensearch.commons.notifications.model +import org.opensearch.commons.notifications.NotificationConstants.ENCRYPTION_PREFIX import org.opensearch.commons.notifications.NotificationConstants.HEADER_PARAMS_TAG import org.opensearch.commons.notifications.NotificationConstants.METHOD_TAG import org.opensearch.commons.notifications.NotificationConstants.URL_TAG @@ -32,7 +33,9 @@ data class Webhook( init { require(!Strings.isNullOrEmpty(url)) { "URL is null or empty" } - validateUrl(url) + if (!url.startsWith(ENCRYPTION_PREFIX)) { + validateUrl(url) + } } companion object { diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/ChimeTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/ChimeTests.kt index 22cf4146..0f7179b4 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/ChimeTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/ChimeTests.kt @@ -76,6 +76,28 @@ internal class ChimeTests { } } + @Test + fun `Chime should skip url validation when url starts with enc prefix`() { + val encryptedUrl = "enc:this-is-not-a-real-url" + val chime = Chime(encryptedUrl) + assertEquals(encryptedUrl, chime.url) + } + + @Test + fun `Chime with enc prefix should serialize and deserialize transport object`() { + val sampleChime = Chime("enc:some-encrypted-value") + val recreatedObject = recreateObject(sampleChime) { Chime(it) } + assertEquals(sampleChime, recreatedObject) + } + + @Test + fun `Chime with enc prefix should serialize and deserialize using json object`() { + val sampleChime = Chime("enc:some-encrypted-value") + val jsonString = getJsonString(sampleChime) + val recreatedObject = createObjectFromJsonString(jsonString) { Chime.parse(it) } + assertEquals(sampleChime, recreatedObject) + } + @Test fun `Chime should safely ignore extra field in json object`() { val sampleChime = Chime("https://domain.com/sample_url#1234567890") diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/MicrosoftTeamsTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/MicrosoftTeamsTests.kt index 910a5f8e..001bffb2 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/MicrosoftTeamsTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/MicrosoftTeamsTests.kt @@ -76,6 +76,28 @@ internal class MicrosoftTeamsTests { } } + @Test + fun `Microsoft Teams should skip url validation when url starts with enc prefix`() { + val encryptedUrl = "enc:this-is-not-a-real-url" + val microsoftTeams = MicrosoftTeams(encryptedUrl) + assertEquals(encryptedUrl, microsoftTeams.url) + } + + @Test + fun `Microsoft Teams with enc prefix should serialize and deserialize transport object`() { + val sampleMicrosoftTeams = MicrosoftTeams("enc:some-encrypted-value") + val recreatedObject = recreateObject(sampleMicrosoftTeams) { MicrosoftTeams(it) } + assertEquals(sampleMicrosoftTeams, recreatedObject) + } + + @Test + fun `Microsoft Teams with enc prefix should serialize and deserialize using json object`() { + val sampleMicrosoftTeams = MicrosoftTeams("enc:some-encrypted-value") + val jsonString = getJsonString(sampleMicrosoftTeams) + val recreatedObject = createObjectFromJsonString(jsonString) { MicrosoftTeams.parse(it) } + assertEquals(sampleMicrosoftTeams, recreatedObject) + } + @Test fun `Microsoft Teams should safely ignore extra field in json object`() { val sampleMicrosoftTeams = MicrosoftTeams("https://domain.com/sample_url#1234567890") diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/SlackTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/SlackTests.kt index e66de5a5..db36b6af 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/SlackTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/SlackTests.kt @@ -76,6 +76,28 @@ internal class SlackTests { } } + @Test + fun `Slack should skip url validation when url starts with enc prefix`() { + val encryptedUrl = "enc:this-is-not-a-real-url" + val slack = Slack(encryptedUrl) + assertEquals(encryptedUrl, slack.url) + } + + @Test + fun `Slack with enc prefix should serialize and deserialize transport object`() { + val sampleSlack = Slack("enc:some-encrypted-value") + val recreatedObject = recreateObject(sampleSlack) { Slack(it) } + assertEquals(sampleSlack, recreatedObject) + } + + @Test + fun `Slack with enc prefix should serialize and deserialize using json object`() { + val sampleSlack = Slack("enc:some-encrypted-value") + val jsonString = getJsonString(sampleSlack) + val recreatedObject = createObjectFromJsonString(jsonString) { Slack.parse(it) } + assertEquals(sampleSlack, recreatedObject) + } + @Test fun `Slack should safely ignore extra field in json object`() { val sampleSlack = Slack("https://domain.com/sample_url#1234567890") diff --git a/src/test/kotlin/org/opensearch/commons/notifications/model/WebhookTests.kt b/src/test/kotlin/org/opensearch/commons/notifications/model/WebhookTests.kt index 455f7ca4..ac39e26d 100644 --- a/src/test/kotlin/org/opensearch/commons/notifications/model/WebhookTests.kt +++ b/src/test/kotlin/org/opensearch/commons/notifications/model/WebhookTests.kt @@ -92,6 +92,28 @@ internal class WebhookTests { } } + @Test + fun `Webhook should skip url validation when url starts with enc prefix`() { + val encryptedUrl = "enc:this-is-not-a-real-url" + val webhook = Webhook(encryptedUrl) + assertEquals(encryptedUrl, webhook.url) + } + + @Test + fun `Webhook with enc prefix should serialize and deserialize transport object`() { + val sampleWebhook = Webhook("enc:some-encrypted-value") + val recreatedObject = recreateObject(sampleWebhook) { Webhook(it) } + assertEquals(sampleWebhook, recreatedObject) + } + + @Test + fun `Webhook with enc prefix should serialize and deserialize using json object`() { + val sampleWebhook = Webhook("enc:some-encrypted-value") + val jsonString = getJsonString(sampleWebhook) + val recreatedObject = createObjectFromJsonString(jsonString) { Webhook.parse(it) } + assertEquals(sampleWebhook, recreatedObject) + } + @Test fun `Webhook should safely ignore extra field in json object`() { val sampleWebhook = Webhook("https://domain.com/sample_url#1234567890")