Unverified Commit 0ab54937 authored by 82marbag's avatar 82marbag Committed by GitHub
Browse files

Redact sensitive structs in debug (#2155)



* Redact sensitive structs in debug

Signed-off-by: default avatarDaniele Ahmed <ahmeddan@amazon.de>
parent 76ee00eb
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -92,7 +92,7 @@ fun ServiceShape.hasEventStreamOperations(model: Model): Boolean = operations.an

fun Shape.shouldRedact(model: Model): Boolean =
    when (this) {
        is MemberShape -> model.expectShape(this.target).shouldRedact(model)
        is MemberShape -> model.expectShape(this.target).shouldRedact(model) || model.expectShape(this.container).shouldRedact(model)
        else -> this.hasTrait<SensitiveTrait>()
    }

+22 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ internal class BuilderGeneratorTest {
    private val inner = StructureGeneratorTest.inner
    private val struct = StructureGeneratorTest.struct
    private val credentials = StructureGeneratorTest.credentials
    private val secretStructure = StructureGeneratorTest.secretStructure

    @Test
    fun `generate builders`() {
@@ -118,4 +119,25 @@ internal class BuilderGeneratorTest {
            """,
        )
    }

    @Test
    fun `builder for a sensitive struct should implement the debug trait as such`() {
        val provider = testSymbolProvider(model)
        val writer = RustWriter.forModule("model")
        val structGenerator = StructureGenerator(model, provider, writer, secretStructure)
        val builderGenerator = BuilderGenerator(model, provider, secretStructure)
        structGenerator.render()
        builderGenerator.render(writer)
        writer.implBlock(secretStructure, provider) {
            builderGenerator.renderConvenienceMethod(this)
        }
        writer.compileAndTest(
            """
            use super::*;
            let builder = SecretStructure::builder()
                .secret_field("secret");
            assert_eq!(format!("{:?}", builder), "Builder { secret_field: \"*** Sensitive Data Redacted ***\" }");
            """,
        )
    }
}
+57 −1
Original line number Diff line number Diff line
@@ -69,11 +69,23 @@ class StructureGeneratorTest {
            structure StructWithDoc {
                doc: Document
            }

            @sensitive
            structure SecretStructure {
                secretField: String
            }

            structure StructWithInnerSecretStructure {
                public: String,
                private: SecretStructure,
            }
            """.asSmithyModel()
        val struct = model.lookup<StructureShape>("com.test#MyStruct")
        val structWithDoc = model.lookup<StructureShape>("com.test#StructWithDoc")
        val inner = model.lookup<StructureShape>("com.test#Inner")
        val credentials = model.lookup<StructureShape>("com.test#Credentials")
        val secretStructure = model.lookup<StructureShape>("com.test#SecretStructure")
        val structWithInnerSecretStructure = model.lookup<StructureShape>("com.test#StructWithInnerSecretStructure")
        val error = model.lookup<StructureShape>("com.test#MyError")
    }

@@ -143,7 +155,7 @@ class StructureGeneratorTest {
    }

    @Test
    fun `generate a custom debug implementation when the sensitive trait is present`() {
    fun `generate a custom debug implementation when the sensitive trait is applied to some members`() {
        val provider = testSymbolProvider(model)
        val writer = RustWriter.forModule("lib")
        val generator = StructureGenerator(model, provider, writer, credentials)
@@ -162,6 +174,50 @@ class StructureGeneratorTest {
        writer.compileAndTest()
    }

    @Test
    fun `generate a custom debug implementation when the sensitive trait is applied to the struct`() {
        val provider = testSymbolProvider(model)
        val writer = RustWriter.forModule("lib")
        val generator = StructureGenerator(model, provider, writer, secretStructure)
        generator.render()
        writer.unitTest(
            "sensitive_structure_redacted",
            """
            let secret_structure = SecretStructure {
                secret_field: Some("secret".to_owned()),
            };
            assert_eq!(format!("{:?}", secret_structure), "SecretStructure { secret_field: \"*** Sensitive Data Redacted ***\" }");
            """,
        )
        writer.compileAndTest()
    }

    @Test
    fun `generate a custom debug implementation when the sensitive trait is applied to an inner struct`() {
        val provider = testSymbolProvider(model)
        val project = TestWorkspace.testProject(provider)
        project.useShapeWriter(inner) {
            val secretGenerator = StructureGenerator(model, provider, this, secretStructure)
            val generator = StructureGenerator(model, provider, this, structWithInnerSecretStructure)
            secretGenerator.render()
            generator.render()
            unitTest(
                "sensitive_inner_structure_redacted",
                """
                let secret_structure = SecretStructure {
                    secret_field: Some("secret".to_owned()),
                };
                let struct_with_inner_secret_structure = StructWithInnerSecretStructure {
                    public: Some("Public".to_owned()),
                    private: Some(secret_structure),
                };
                assert_eq!(format!("{:?}", struct_with_inner_secret_structure), "StructWithInnerSecretStructure { public: Some(\"Public\"), private: \"*** Sensitive Data Redacted ***\" }");
                """,
            )
        }
        project.compileAndTest()
    }

    @Test
    fun `attach docs to everything`() {
        val model = """