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
This commit is contained in:
Julian Antonielli 2022-10-07 14:44:11 +01:00 committed by GitHub
parent e78da5598a
commit 238cf8b434
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 31 additions and 11 deletions

View File

@ -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]]

View File

@ -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);",
)

View File

@ -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(())")

View File

@ -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<SensitiveTrait>()) {
"*** Sensitive Data Redacted ***".dq()
} else {
safeToPrint
}
is MemberShape -> model.expectShape(this.target).shouldRedact(model)
else -> this.hasTrait<SensitiveTrait>()
}
const val REDACTION = "\"*** Sensitive Data Redacted ***\""
fun Shape.redactIfNecessary(model: Model, safeToPrint: String): String =
if (this.shouldRedact(model)) {
REDACTION
} else {
safeToPrint
}
/*