Improved sanitize function.

This commit is contained in:
Erik C. Thauvin 2021-10-25 17:27:55 -07:00
parent 0d144d4b10
commit 95823db1d9
6 changed files with 43 additions and 31 deletions

View file

@ -42,7 +42,7 @@ import java.io.IOException
import java.net.URL import java.net.URL
/** /**
* Reads a RSS feed. * Reads an RSS feed.
*/ */
class FeedReader( class FeedReader(
// Bot // Bot

View file

@ -66,7 +66,7 @@ class TellMessage internal constructor(
var id: String = queued.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) var id: String = queued.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))
/** /**
* Returns {@code true) if a notification was send. * Returns {@code true) if a notification was sent.
*/ */
var isNotified = false var isNotified = false
@ -82,7 +82,7 @@ class TellMessage internal constructor(
} }
/** /**
* Return the message creating date. * Returns the message creating date.
*/ */
var receptionDate: LocalDateTime = LocalDateTime.MIN var receptionDate: LocalDateTime = LocalDateTime.MIN

View file

@ -34,23 +34,29 @@ package net.thauvin.erik.mobibot
import net.thauvin.erik.mobibot.Utils.obfuscate import net.thauvin.erik.mobibot.Utils.obfuscate
import net.thauvin.erik.mobibot.Utils.replaceEach import net.thauvin.erik.mobibot.Utils.replaceEach
import net.thauvin.erik.mobibot.modules.ModuleException
object Sanitize { object Sanitize {
/** /**
* Return the sanitized exception message (e.g. remove API keys, etc.) * Returns a sanitized exception to avoid displaying api keys, etc. in CI logs.
*/ */
fun sanitizedMessage(e: Throwable, vararg sanitize: String): String { fun sanitizeException(e: ModuleException, vararg sanitize: String): ModuleException {
val obfuscate = sanitize.map { it.obfuscate() }.toTypedArray() var sanitizedException = e
with(e) { val search = sanitize.filter { it.isNotBlank() }.toTypedArray()
return when { if (search.isNotEmpty()) {
cause?.message != null -> { val obfuscate = search.map { it.obfuscate() }.toTypedArray()
cause!!.javaClass.name + ": " + cause!!.message!!.replaceEach(sanitize, obfuscate) with(e) {
if (cause?.message != null) {
sanitizedException = ModuleException(
debugMessage,
cause!!.javaClass.name + ": " + cause!!.message!!.replaceEach(search, obfuscate),
this
)
} else if (message != null) {
sanitizedException = ModuleException(debugMessage, message!!.replaceEach(search, obfuscate), this)
} }
message != null -> {
message!!.javaClass.name + ": " + message!!.replaceEach(sanitize, obfuscate)
}
else -> ""
} }
} }
return sanitizedException
} }
} }

View file

@ -32,7 +32,7 @@
package net.thauvin.erik.mobibot.modules package net.thauvin.erik.mobibot.modules
import net.thauvin.erik.mobibot.LocalProperties import net.thauvin.erik.mobibot.LocalProperties
import net.thauvin.erik.mobibot.Sanitize.sanitizedMessage import net.thauvin.erik.mobibot.Sanitize.sanitizeException
import net.thauvin.erik.mobibot.modules.GoogleSearch.Companion.searchGoogle import net.thauvin.erik.mobibot.modules.GoogleSearch.Companion.searchGoogle
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatThrownBy import org.assertj.core.api.Assertions.assertThatThrownBy
@ -64,8 +64,8 @@ class GoogleSearchTest : LocalProperties() {
.describedAs("no query").isInstanceOf(ModuleException::class.java).hasNoCause() .describedAs("no query").isInstanceOf(ModuleException::class.java).hasNoCause()
} catch (e: ModuleException) { } catch (e: ModuleException) {
// Avoid displaying api keys in CI logs // Avoid displaying api keys in CI logs
if ("true" == System.getenv("CI") && (apiKey.isNotBlank() || cseKey.isNotBlank())) { if ("true" == System.getenv("CI")) {
throw ModuleException(e.debugMessage, sanitizedMessage(e, apiKey, cseKey), e) throw sanitizeException(e, apiKey, cseKey)
} else { } else {
throw e throw e
} }

View file

@ -1,7 +1,7 @@
/* /*
* ModuleExceptionTest.java * ModuleExceptionTest.kt
* *
* Copyright (c) 2004-2019, Erik C. Thauvin (erik@thauvin.net) * Copyright (c) 2004-2021, Erik C. Thauvin (erik@thauvin.net)
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -31,7 +31,7 @@
*/ */
package net.thauvin.erik.mobibot.modules package net.thauvin.erik.mobibot.modules
import net.thauvin.erik.mobibot.Sanitize.sanitizedMessage import net.thauvin.erik.mobibot.Sanitize.sanitizeException
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.testng.annotations.DataProvider import org.testng.annotations.DataProvider
import org.testng.annotations.Test import org.testng.annotations.Test
@ -63,25 +63,31 @@ class ModuleExceptionTest {
@Test(dataProvider = "dp") @Test(dataProvider = "dp")
fun testGetMessage(e: ModuleException) { fun testGetMessage(e: ModuleException) {
assertThat(e.message).describedAs("get message").isEqualTo(message) assertThat(e).describedAs("get message").hasMessage(message)
} }
@Test @Test
fun testSanitizeMessage() { fun testSanitizeMessage() {
val apiKey = "1234567890" val apiKey = "1234567890"
var e = ModuleException(debugMessage, message, IOException("URL http://foo.com?apiKey=$apiKey&userID=me")) var e = ModuleException(debugMessage, message, IOException("URL http://foo.com?apiKey=$apiKey&userID=me"))
assertThat(sanitizedMessage(e, apiKey)).describedAs("sanitized url") assertThat(sanitizeException(e, apiKey, "", "me")).describedAs("sanitized url")
.contains("xxxxxxxxxx").doesNotContain(apiKey) .hasMessageContainingAll("xxxxxxxxxx", "userID=xx").hasMessageNotContainingAny(apiKey, "me")
e = ModuleException(debugMessage, message, null) e = ModuleException(debugMessage, message, null)
assertThat(sanitizedMessage(e, apiKey)).describedAs("no cause").contains(message) assertThat(sanitizeException(e, apiKey)).describedAs("no cause").hasMessage(message)
e = ModuleException(debugMessage, message, IOException())
assertThat(sanitizeException(e, apiKey)).describedAs("no cause message").hasMessage(message)
e = ModuleException(apiKey)
assertThat(sanitizeException(e, apiKey)).describedAs("api key in message").hasMessageNotContaining(apiKey)
val msg: String? = null val msg: String? = null
e = ModuleException(debugMessage, msg, IOException(msg)) e = ModuleException(debugMessage, msg, IOException(msg))
assertThat(sanitizedMessage(e, apiKey)).describedAs("no message").isEqualTo("") assertThat(sanitizeException(e, apiKey).message).describedAs("null message").isNull()
e = ModuleException(msg, msg, IOException("foo is $apiKey"))
e = ModuleException(msg, msg, IOException(apiKey)) assertThat(sanitizeException(e, " ", apiKey, "foo").message).describedAs("key in cause")
assertThat(sanitizedMessage(e, apiKey)).describedAs("null message").doesNotContain(apiKey) .doesNotContain(apiKey).endsWith("xxx is xxxxxxxxxx")
} }
} }

View file

@ -32,7 +32,7 @@
package net.thauvin.erik.mobibot.modules package net.thauvin.erik.mobibot.modules
import net.thauvin.erik.mobibot.LocalProperties import net.thauvin.erik.mobibot.LocalProperties
import net.thauvin.erik.mobibot.Sanitize.sanitizedMessage import net.thauvin.erik.mobibot.Sanitize.sanitizeException
import net.thauvin.erik.mobibot.modules.StockQuote.Companion.getQuote import net.thauvin.erik.mobibot.modules.StockQuote.Companion.getQuote
import org.assertj.core.api.Assertions.assertThat import org.assertj.core.api.Assertions.assertThat
import org.assertj.core.api.Assertions.assertThatThrownBy import org.assertj.core.api.Assertions.assertThatThrownBy
@ -64,8 +64,8 @@ class StockQuoteTest : LocalProperties() {
.isInstanceOf(ModuleException::class.java).hasNoCause() .isInstanceOf(ModuleException::class.java).hasNoCause()
} catch (e: ModuleException) { } catch (e: ModuleException) {
// Avoid displaying api keys in CI logs // Avoid displaying api keys in CI logs
if ("true" == System.getenv("CI") && apiKey.isNotBlank()) { if ("true" == System.getenv("CI")) {
throw ModuleException(e.debugMessage, sanitizedMessage(e, apiKey), e) throw sanitizeException(e, apiKey)
} else { } else {
throw e throw e
} }