diff --git a/compute/src/main/java/org/zstack/compute/vm/VmSystemTags.java b/compute/src/main/java/org/zstack/compute/vm/VmSystemTags.java index efb4f5e0ff8..70ff1fe1652 100755 --- a/compute/src/main/java/org/zstack/compute/vm/VmSystemTags.java +++ b/compute/src/main/java/org/zstack/compute/vm/VmSystemTags.java @@ -251,7 +251,13 @@ public String desensitizeTag(SystemTag systemTag, String tag) { } Yaml yaml = new Yaml(); - Object obj = yaml.load(userdata); + Object obj; + try { + obj = yaml.load(userdata); + } catch (RuntimeException e) { + tokens.put(t, "*****"); + continue; + } if (!(obj instanceof LinkedHashMap)) { return tag; } diff --git a/test/src/test/java/org/zstack/test/userdata/TestUserdataTagOutputHandler.java b/test/src/test/java/org/zstack/test/userdata/TestUserdataTagOutputHandler.java new file mode 100644 index 00000000000..f6b73498972 --- /dev/null +++ b/test/src/test/java/org/zstack/test/userdata/TestUserdataTagOutputHandler.java @@ -0,0 +1,44 @@ +package org.zstack.test.userdata; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.zstack.compute.vm.VmSystemTags; + +import java.util.Base64; +import java.util.HashMap; +import java.util.Map; + +public class TestUserdataTagOutputHandler { + private final VmSystemTags.UserdataTagOutputHandler handler = new VmSystemTags.UserdataTagOutputHandler(); + + @Before + public void setUp() throws NoSuchFieldException { + VmSystemTags.USERDATA.annotation = VmSystemTags.class.getField("USERDATA").getAnnotation(org.zstack.tag.SensitiveTag.class); + } + + @Test + public void desensitizeMalformedCloudConfigMasksUserdata() { + String userdata = "#cloud-config\nchpasswd:\n list: |\nroot:word\nexpire: False\n"; + String maskedTag = handler.desensitizeTag(VmSystemTags.USERDATA, userdataTag(userdata)); + + Assert.assertEquals("*****", VmSystemTags.USERDATA.getTokenByTag(maskedTag, VmSystemTags.USERDATA_TOKEN)); + } + + @Test + public void desensitizeValidCloudConfigKeepsStructuredMask() { + String userdata = "#cloud-config\nchpasswd:\n list: |\n root:word\n expire: False\n"; + String maskedTag = handler.desensitizeTag(VmSystemTags.USERDATA, userdataTag(userdata)); + String maskedUserdata = new String(Base64.getDecoder().decode( + VmSystemTags.USERDATA.getTokenByTag(maskedTag, VmSystemTags.USERDATA_TOKEN).getBytes())); + + Assert.assertTrue(maskedUserdata.contains("*****:*****")); + Assert.assertFalse(maskedUserdata.contains("root:word")); + } + + private String userdataTag(String userdata) { + Map tokens = new HashMap<>(); + tokens.put(VmSystemTags.USERDATA_TOKEN, new String(Base64.getEncoder().encode(userdata.getBytes()))); + return VmSystemTags.USERDATA.instantiateTag(tokens); + } +}