From f8e931b66fa957241042773fb780b561bca8332d Mon Sep 17 00:00:00 2001 From: Benjamin Clauss Date: Wed, 30 Oct 2024 17:34:23 +0100 Subject: [PATCH] Add IdentityManager and create agentId based on PID and hostname --- .../internal/identity/IdentityManager.java | 76 +++++++++++++++++++ .../internal/identity/model/IdentityInfo.java | 4 + .../agent/notification/model/AgentInfo.java | 26 +++---- .../identity/IdentityManagerTest.java | 64 ++++++++++++++++ .../notification/model/AgentInfoTest.java | 2 + 5 files changed, 159 insertions(+), 13 deletions(-) create mode 100644 inspectit-gepard-agent/src/main/java/rocks/inspectit/gepard/agent/internal/identity/IdentityManager.java create mode 100644 inspectit-gepard-agent/src/main/java/rocks/inspectit/gepard/agent/internal/identity/model/IdentityInfo.java create mode 100644 inspectit-gepard-agent/src/test/java/rocks/inspectit/gepard/agent/internal/identity/IdentityManagerTest.java diff --git a/inspectit-gepard-agent/src/main/java/rocks/inspectit/gepard/agent/internal/identity/IdentityManager.java b/inspectit-gepard-agent/src/main/java/rocks/inspectit/gepard/agent/internal/identity/IdentityManager.java new file mode 100644 index 0000000..9c2a323 --- /dev/null +++ b/inspectit-gepard-agent/src/main/java/rocks/inspectit/gepard/agent/internal/identity/IdentityManager.java @@ -0,0 +1,76 @@ +/* (C) 2024 */ +package rocks.inspectit.gepard.agent.internal.identity; + +import java.lang.management.ManagementFactory; +import java.lang.management.RuntimeMXBean; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import rocks.inspectit.gepard.agent.internal.identity.model.IdentityInfo; + +public class IdentityManager { + + private static final Logger log = LoggerFactory.getLogger(IdentityManager.class); + + private final IdentityInfo identityInfo; + + private IdentityManager() { + RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean(); + long pid = runtime.getPid(); + String localHostName = getLocalHostname(); + this.identityInfo = new IdentityInfo(pid, localHostName, hash(pid + localHostName)); + } + + public static IdentityManager getInstance() { + return new IdentityManager(); + } + + public IdentityInfo getIdentityInfo() { + return this.identityInfo; + } + + /** + * Determines the current hostname. + * + * @return the hostname or if the operation is not allowed by the security check, the textual + * representation of the IP address. The default value is "0.0.0.0". + */ + private String getLocalHostname() { + String localHostName = "0.0.0.0"; + try { + localHostName = InetAddress.getLocalHost().getHostName(); + } catch (UnknownHostException e) { + log.info("Could not determine hostname", e); + } + return localHostName; + } + + /** + * Hashes the given input with SHA3-256. + * + * @param input the String to be hashed. + * @return the SHA3-256 hashed String + */ + private static String hash(String input) { + MessageDigest messageDigest; + try { + messageDigest = MessageDigest.getInstance("SHA3-256"); + } catch (NoSuchAlgorithmException e) { + throw new UnsupportedOperationException("SHA3-256 not supported", e); + } + byte[] bytes = messageDigest.digest(input.getBytes(StandardCharsets.UTF_8)); + StringBuilder hexString = new StringBuilder(2 * bytes.length); + for (byte b : bytes) { + String hex = Integer.toHexString(0xff & b); + if (hex.length() == 1) { + hexString.append('0'); + } + hexString.append(hex); + } + return hexString.toString(); + } +} diff --git a/inspectit-gepard-agent/src/main/java/rocks/inspectit/gepard/agent/internal/identity/model/IdentityInfo.java b/inspectit-gepard-agent/src/main/java/rocks/inspectit/gepard/agent/internal/identity/model/IdentityInfo.java new file mode 100644 index 0000000..ea61103 --- /dev/null +++ b/inspectit-gepard-agent/src/main/java/rocks/inspectit/gepard/agent/internal/identity/model/IdentityInfo.java @@ -0,0 +1,4 @@ +/* (C) 2024 */ +package rocks.inspectit.gepard.agent.internal.identity.model; + +public record IdentityInfo(long pid, String hostname, String agentId) {} diff --git a/inspectit-gepard-agent/src/main/java/rocks/inspectit/gepard/agent/notification/model/AgentInfo.java b/inspectit-gepard-agent/src/main/java/rocks/inspectit/gepard/agent/notification/model/AgentInfo.java index 986639e..fa2ba00 100644 --- a/inspectit-gepard-agent/src/main/java/rocks/inspectit/gepard/agent/notification/model/AgentInfo.java +++ b/inspectit-gepard-agent/src/main/java/rocks/inspectit/gepard/agent/notification/model/AgentInfo.java @@ -11,6 +11,8 @@ import java.lang.management.RuntimeMXBean; import java.util.Map; import java.util.Objects; +import rocks.inspectit.gepard.agent.internal.identity.IdentityManager; +import rocks.inspectit.gepard.agent.internal.identity.model.IdentityInfo; import rocks.inspectit.gepard.agent.internal.properties.PropertiesResolver; /** Meta-information about the current agent */ @@ -33,16 +35,25 @@ public class AgentInfo { private final long pid; + private final String hostname; + + private final String agentId; + private final Map attributes; private AgentInfo() { + IdentityManager identityManager = IdentityManager.getInstance(); + IdentityInfo identityInfo = identityManager.getIdentityInfo(); + RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean(); + this.serviceName = getServiceNameFromSdk(); this.gepardVersion = "0.0.1"; this.otelVersion = AgentVersion.VERSION; this.javaVersion = System.getProperty("java.version"); - RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean(); this.startTime = runtime.getStartTime(); - this.pid = runtime.getPid(); + this.pid = identityInfo.pid(); + this.hostname = identityInfo.hostname(); + this.agentId = identityInfo.agentId(); this.attributes = PropertiesResolver.getAttributes(); } @@ -67,15 +78,4 @@ private String getServiceNameFromSdk() { ? "inspectit-gepard-agent" : configuredServiceName; } - - /** - * @return the service name of the agent. - */ - public String getServiceName() { - return serviceName; - } - - public long getPid() { - return pid; - } } diff --git a/inspectit-gepard-agent/src/test/java/rocks/inspectit/gepard/agent/internal/identity/IdentityManagerTest.java b/inspectit-gepard-agent/src/test/java/rocks/inspectit/gepard/agent/internal/identity/IdentityManagerTest.java new file mode 100644 index 0000000..583ddb5 --- /dev/null +++ b/inspectit-gepard-agent/src/test/java/rocks/inspectit/gepard/agent/internal/identity/IdentityManagerTest.java @@ -0,0 +1,64 @@ +/* (C) 2024 */ +package rocks.inspectit.gepard.agent.internal.identity; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.lang.management.ManagementFactory; +import java.lang.management.RuntimeMXBean; +import java.net.InetAddress; +import java.net.UnknownHostException; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; +import rocks.inspectit.gepard.agent.internal.identity.model.IdentityInfo; + +@ExtendWith(MockitoExtension.class) +class IdentityManagerTest { + + @Test + void testCreateIdentityManagerSuccessfully() { + InetAddress mockInetAddress = mock(InetAddress.class); + when(mockInetAddress.getHostName()).thenReturn("mockedHostName"); + + RuntimeMXBean mockRuntimeMXBean = mock(RuntimeMXBean.class); + when(mockRuntimeMXBean.getPid()).thenReturn(12345L); + + try (MockedStatic mockedStatic = Mockito.mockStatic(InetAddress.class); + MockedStatic managementFactoryMockedStatic = + Mockito.mockStatic(ManagementFactory.class)) { + mockedStatic.when(InetAddress::getLocalHost).thenReturn(mockInetAddress); + managementFactoryMockedStatic + .when(ManagementFactory::getRuntimeMXBean) + .thenReturn(mockRuntimeMXBean); + + IdentityManager identityManager = IdentityManager.getInstance(); + IdentityInfo identityInfo = identityManager.getIdentityInfo(); + + assertNotNull(identityInfo); + assertEquals("mockedHostName", identityInfo.hostname()); + assertEquals(12345L, identityInfo.pid()); + assertEquals( + "ef138ea8d422d1df09c3f94b675a99bb475cdae966d067f58a0887ab54ab35e0", + identityInfo.agentId()); + } + } + + @Test + void testCreateIdentityManagerWithUnknownHostException() { + try (MockedStatic mockedStatic = Mockito.mockStatic(InetAddress.class)) { + mockedStatic + .when(InetAddress::getLocalHost) + .thenThrow(new UnknownHostException("Mocked Exception")); + + IdentityManager identityManager = IdentityManager.getInstance(); + IdentityInfo identityInfo = identityManager.getIdentityInfo(); + + assertNotNull(identityInfo); + assertEquals("0.0.0.0", identityInfo.hostname()); + } + } +} diff --git a/inspectit-gepard-agent/src/test/java/rocks/inspectit/gepard/agent/notification/model/AgentInfoTest.java b/inspectit-gepard-agent/src/test/java/rocks/inspectit/gepard/agent/notification/model/AgentInfoTest.java index cadcb4a..f3993cc 100644 --- a/inspectit-gepard-agent/src/test/java/rocks/inspectit/gepard/agent/notification/model/AgentInfoTest.java +++ b/inspectit-gepard-agent/src/test/java/rocks/inspectit/gepard/agent/notification/model/AgentInfoTest.java @@ -24,6 +24,8 @@ void agentInformationContainsProperties() throws JsonProcessingException { assertTrue(info.contains("javaVersion")); assertTrue(info.contains("startTime")); assertTrue(info.contains("pid")); + assertTrue(info.contains("hostname")); + assertTrue(info.contains("agentId")); assertTrue(info.contains("attributes")); } }