From 238cf8b434107e82c86d9d4d4c3b51d8cb00872f Mon Sep 17 00:00:00 2001 From: Julian Antonielli Date: Fri, 7 Oct 2022 14:44:11 +0100 Subject: [PATCH] Fix @sensitive handling in Display implementations on error shapes (#1802) * Use `Sensitive` wrapper in Debug impl for structures * Fix using the wrong import path for `Sensitive` * Use redactMemberIfNecessary * Fix display implementation on errors to respect @sensitive trait * Don't use Sensitive type just yet * Add entry in changelog * Improve redaction of sensitive error message * Use correct flags in changelog * Run ktlint --- CHANGELOG.next.toml | 8 +++++++- .../smithy/generators/StructureGenerator.kt | 3 ++- .../smithy/generators/error/ErrorGenerator.kt | 12 ++++++++++-- .../smithy/rust/codegen/core/util/Smithy.kt | 19 ++++++++++++------- 4 files changed, 31 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.next.toml b/CHANGELOG.next.toml index 02caa3a350..ae179af55e 100644 --- a/CHANGELOG.next.toml +++ b/CHANGELOG.next.toml @@ -36,6 +36,12 @@ references = ["smithy-rs#1803"] meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "server"} author = "LukeMathWalker" +[[smithy-rs]] +message = "Sensitive fields in errors now respect @sensitive trait and are properly redacted." +references = ["smithy-rs#1802"] +meta = { "breaking" = false, "tada" = false, "bug" = true, "target" = "all" } +author = "jjant" + [[smithy-rs]] message = "Pokémon Service example code now runs clippy during build." references = ["smithy-rs#1727"] @@ -117,7 +123,7 @@ author = "jdisanti" [[smithy-rs]] message = "Paginators now stop on encountering a duplicate token by default rather than panic. This behavior can be customized by toggling the `stop_on_duplicate_token` property on the paginator before calling `send`." references = ["aws-sdk-rust#620", "smithy-rs#1748"] -meta = { "breaking" = false, "tada" = false, "bug" = true, "target" = "client"} +meta = { "breaking" = false, "tada" = false, "bug" = true, "target" = "client" } author = "jdisanti" [[aws-sdk-rust]] diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/StructureGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/StructureGenerator.kt index 5bf6e0a6b8..f216f236d4 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/StructureGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/StructureGenerator.kt @@ -63,7 +63,7 @@ open class StructureGenerator( fun render(forWhom: CodegenTarget = CodegenTarget.CLIENT) { renderStructure() errorTrait?.also { errorTrait -> - ErrorGenerator(symbolProvider, writer, shape, errorTrait).render(forWhom) + ErrorGenerator(model, symbolProvider, writer, shape, errorTrait).render(forWhom) } } @@ -109,6 +109,7 @@ open class StructureGenerator( members.forEach { member -> val memberName = symbolProvider.toMemberName(member) val fieldValue = member.redactIfNecessary(model, "self.$memberName") + rust( "formatter.field(${memberName.dq()}, &$fieldValue);", ) diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/ErrorGenerator.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/ErrorGenerator.kt index 8f9382b5ac..07f9315b85 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/ErrorGenerator.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/smithy/generators/error/ErrorGenerator.kt @@ -5,6 +5,7 @@ package software.amazon.smithy.rust.codegen.core.smithy.generators.error +import software.amazon.smithy.model.Model import software.amazon.smithy.model.shapes.StructureShape import software.amazon.smithy.model.traits.ErrorTrait import software.amazon.smithy.model.traits.RetryableTrait @@ -19,10 +20,12 @@ import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType import software.amazon.smithy.rust.codegen.core.smithy.RuntimeType.Companion.StdError import software.amazon.smithy.rust.codegen.core.smithy.RustSymbolProvider import software.amazon.smithy.rust.codegen.core.smithy.isOptional +import software.amazon.smithy.rust.codegen.core.util.REDACTION import software.amazon.smithy.rust.codegen.core.util.dq import software.amazon.smithy.rust.codegen.core.util.errorMessageMember import software.amazon.smithy.rust.codegen.core.util.getTrait import software.amazon.smithy.rust.codegen.core.util.letIf +import software.amazon.smithy.rust.codegen.core.util.shouldRedact sealed class ErrorKind { abstract fun writable(runtimeConfig: RuntimeConfig): Writable @@ -60,6 +63,7 @@ fun StructureShape.modeledRetryKind(errorTrait: ErrorTrait): ErrorKind? { } class ErrorGenerator( + private val model: Model, private val symbolProvider: RustSymbolProvider, private val writer: RustWriter, private val shape: StructureShape, @@ -118,8 +122,12 @@ class ErrorGenerator( } write("write!(f, ${errorDesc.dq()})?;") messageShape?.let { - ifSet(it, symbolProvider.toSymbol(it), "&self.message") { field -> - write("""write!(f, ": {}", $field)?;""") + if (it.shouldRedact(model)) { + write("""write!(f, ": {}", $REDACTION)?;""") + } else { + ifSet(it, symbolProvider.toSymbol(it), "&self.message") { field -> + write("""write!(f, ": {}", $field)?;""") + } } } write("Ok(())") diff --git a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/util/Smithy.kt b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/util/Smithy.kt index 448107af0c..291dd30e31 100644 --- a/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/util/Smithy.kt +++ b/codegen-core/src/main/kotlin/software/amazon/smithy/rust/codegen/core/util/Smithy.kt @@ -84,14 +84,19 @@ fun ServiceShape.hasEventStreamOperations(model: Model): Boolean = operations.an model.expectShape(id, OperationShape::class.java).isEventStream(model) } -fun Shape.redactIfNecessary(model: Model, safeToPrint: String): String = +fun Shape.shouldRedact(model: Model): Boolean = when (this) { - is MemberShape -> model.expectShape(this.target).redactIfNecessary(model, safeToPrint) - else -> if (this.hasTrait()) { - "*** Sensitive Data Redacted ***".dq() - } else { - safeToPrint - } + is MemberShape -> model.expectShape(this.target).shouldRedact(model) + else -> this.hasTrait() + } + +const val REDACTION = "\"*** Sensitive Data Redacted ***\"" + +fun Shape.redactIfNecessary(model: Model, safeToPrint: String): String = + if (this.shouldRedact(model)) { + REDACTION + } else { + safeToPrint } /*