diff --git a/echo-telemetry/src/main/java/com/netflix/spinnaker/echo/telemetry/TelemetryEventListener.java b/echo-telemetry/src/main/java/com/netflix/spinnaker/echo/telemetry/TelemetryEventListener.java index 1819fa12e..0fd09a47f 100644 --- a/echo-telemetry/src/main/java/com/netflix/spinnaker/echo/telemetry/TelemetryEventListener.java +++ b/echo-telemetry/src/main/java/com/netflix/spinnaker/echo/telemetry/TelemetryEventListener.java @@ -105,7 +105,6 @@ public void processEvent(Event event) { log.debug("Application ID must be non-null and not empty"); return; } - String hashedApplicationId = hash(applicationId); Holder.Content content = objectMapper.convertValue(event.getContent(), Holder.Content.class); Holder.Execution execution = content.getExecution(); @@ -143,11 +142,17 @@ public void processEvent(Event event) { } Execution executionProto = executionBuilder.build(); + // We want to ensure it's really hard to guess the application name. Using the instance ID (a + // ULID) provides a good level of randomness as a salt, and is not easily guessable. + String instanceId = telemetryConfigProps.getInstanceId(); + String hashedInstanceId = hash(instanceId); + String hashedApplicationId = hash(applicationId, instanceId); + Application application = Application.newBuilder().setId(hashedApplicationId).build(); SpinnakerInstance spinnakerInstance = SpinnakerInstance.newBuilder() - .setId(telemetryConfigProps.getInstanceId()) + .setId(hashedInstanceId) .setVersion(telemetryConfigProps.getSpinnakerVersion()) .build(); @@ -197,7 +202,11 @@ private Optional toStage(Holder.Stage stage) { } private String hash(String clearText) { - return Hashing.sha256().hashString(clearText, StandardCharsets.UTF_8).toString(); + return hash(clearText, ""); + } + + private String hash(String clearText, String salt) { + return Hashing.sha256().hashString(clearText + salt, StandardCharsets.UTF_8).toString(); } private static EnumValueDescriptor parseEnum(EnumDescriptor ed, String value) { diff --git a/echo-telemetry/src/test/groovy/com/netflix/spinnaker/echo/telemetry/TelemetryEventListenerSpec.groovy b/echo-telemetry/src/test/groovy/com/netflix/spinnaker/echo/telemetry/TelemetryEventListenerSpec.groovy index 10b6861ff..945bab8f9 100644 --- a/echo-telemetry/src/test/groovy/com/netflix/spinnaker/echo/telemetry/TelemetryEventListenerSpec.groovy +++ b/echo-telemetry/src/test/groovy/com/netflix/spinnaker/echo/telemetry/TelemetryEventListenerSpec.groovy @@ -21,10 +21,11 @@ class TelemetryEventListenerSpec extends Specification { def circuitBreaker = registry.circuitBreaker(TelemetryEventListener.TELEMETRY_REGISTRY_NAME) def instanceId = "test-instance" + def instanceHash = "b6a8ed497aba799fb0033fcb3588de65e198a0d9b731c5481499251177074a8f" def spinnakerVersion = "1.2.3" def applicationName = "someApp" - def applicationHash = "e40464bf6d04933c6011c29974eb328777669813a76583e5d547941427df686f" + def applicationHash = "f0291bf122b40a43cb2129378272f205200dff0445af506346b1dc47127e258d" def executionId = "execution_id" def executionHash = "6d6de5b8d67c11fff6d817ea3e1190bc63857de0329d253b21aef6e5c6bbebf9" @@ -143,7 +144,7 @@ class TelemetryEventListenerSpec extends Specification { SpinnakerInstance s = e.spinnakerInstance assert s != null - assert s.id == instanceId + assert s.id == instanceHash assert s.version == spinnakerVersion Application a = e.getApplication()