Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: include agent info into polling #29

Merged
merged 7 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ public AgentBuilder extend(AgentBuilder agentBuilder, ConfigProperties config) {

// Notify configuration server about this agent
NotificationManager notificationManager = NotificationManager.create();
notificationManager.sendStartNotification();
// Set up shutdown notification to configuration server
notificationManager.setUpShutdownNotification();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
package rocks.inspectit.gepard.agent.configuration.http;

import java.io.IOException;
import java.util.Objects;
import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
import org.apache.hc.core5.concurrent.FutureCallback;
import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.ProtocolException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import rocks.inspectit.gepard.agent.internal.configuration.observer.ConfigurationReceivedSubject;
Expand All @@ -16,12 +19,10 @@ public class HttpConfigurationCallback implements FutureCallback<SimpleHttpRespo

@Override
public void completed(SimpleHttpResponse result) {
log.info(
"Fetched configuration from configuration server and received status code {}",
result.getCode());

logStatus(result);
// Publish Event
if (result.getCode() == 200) {
if (result.getCode() == 200 || result.getCode() == 201) {
String body = result.getBodyText();

try {
Expand All @@ -45,4 +46,28 @@ public void failed(Exception ex) {
public void cancelled() {
log.info("Cancelled configuration fetch");
}

private void logStatus(SimpleHttpResponse response) {
int statusCode = response.getCode();
log.info("Received status code {}", statusCode);

if (statusCode == 404) {
log.error("Configuration not found on configuration server");
} else if (statusCode == 200) {
try {
Header registrationHeader = response.getHeader("x-gepard-service-registered");
if (Objects.isNull(registrationHeader)) {
log.error("Configuration server did not return registration header!");
} else if (registrationHeader.getValue().equals("true")) {
log.info("Connection to configuration server was successfully established.");
} else {
log.debug("Connection to configuration server reused.");
}
} catch (ProtocolException e) {
log.error(
"Error reading response header. There might be an issue with the config-server!", e);
}
log.info("Configuration fetched successfully");
}
}
binarycoded marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Map;
import org.apache.hc.client5.http.async.methods.SimpleHttpRequest;
import org.apache.hc.client5.http.async.methods.SimpleRequestBuilder;
import org.apache.hc.core5.net.URIBuilder;
import rocks.inspectit.gepard.agent.internal.identity.model.AgentInfo;
import rocks.inspectit.gepard.commons.model.agent.Agent;

/**
* This factory should create different HTTP requests for the configuration server to fetch
Expand All @@ -23,8 +26,32 @@ private HttpConfigurationFactory() {}
*/
public static SimpleHttpRequest createConfigurationRequest(String baseUrl)
throws URISyntaxException {
URI uri = new URIBuilder(baseUrl + "/agent-configuration").build();

return SimpleRequestBuilder.get(uri).build();
AgentInfo agentInfo = AgentInfo.INFO;

URI uri = new URIBuilder(baseUrl + "/agent-configuration/" + agentInfo.getAgentId()).build();

SimpleRequestBuilder requestBuilder = SimpleRequestBuilder.get(uri);

return buildRequestWithHeaders(requestBuilder, agentInfo.getAgent()).build();
}

private static SimpleRequestBuilder buildRequestWithHeaders(
SimpleRequestBuilder requestBuilder, Agent agent) {
Map<String, String> headers =
Map.of(
"x-gepard-service-Name", agent.getServiceName(),
"x-gepard-vm-id", agent.getVmId(),
"x-gepard-gepard-version", agent.getGepardVersion(),
"x-gepard-otel-version", agent.getOtelVersion(),
"x-gepard-java-version", agent.getJavaVersion(),
"x-gepard-start-time", agent.getStartTime().toString());
binarycoded marked this conversation as resolved.
Show resolved Hide resolved

headers.forEach(requestBuilder::addHeader);
agent
.getAttributes()
.forEach((key, value) -> requestBuilder.addHeader("X-Gepard-Attribute-" + key, value));
binarycoded marked this conversation as resolved.
Show resolved Hide resolved

return requestBuilder;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;
import java.util.Objects;
import rocks.inspectit.gepard.agent.internal.identity.model.IdentityInfo;

Expand Down Expand Up @@ -38,13 +40,16 @@ public IdentityInfo getIdentityInfo() {
* @return the SHA3-256 hashed <code>String</code>
*/
private static String hash(String input) {
String salt = generateSalt();
String saltedInput = salt + 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));
byte[] bytes = messageDigest.digest(saltedInput.getBytes(StandardCharsets.UTF_8));
StringBuilder hexString = new StringBuilder(2 * bytes.length);
for (byte b : bytes) {
String hex = Integer.toHexString(0xff & b);
Expand All @@ -55,4 +60,12 @@ private static String hash(String input) {
}
return hexString.toString();
}

/** Generates a secure random 128bit string/salt */
private static String generateSalt() {
byte[] salt = new byte[16];
SecureRandom secureRandom = new SecureRandom();
secureRandom.nextBytes(salt);
return Base64.getEncoder().encodeToString(salt);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,10 @@ public class NotificationManager {

private final String serverBaseUrl;

private final StartNotifier startNotifier;

private final ShutdownNotifier shutdownNotifier;

private NotificationManager(String serverBaseUrl) {
this.serverBaseUrl = serverBaseUrl;
this.startNotifier = new StartNotifier();
this.shutdownNotifier = new ShutdownNotifier();
}

Expand All @@ -35,22 +32,6 @@ public static NotificationManager create() {
return new NotificationManager(url);
}

/**
* Sends a message to the configuration server, to notify it about this agent starting, if a
* configuration server url was provided.
*
* @return true, if the notification was executed successfully
*/
public boolean sendStartNotification() {
boolean successful = false;
if (serverBaseUrl.isEmpty()) log.info("No configuration server url was provided");
else {
log.info("Sending start notification to configuration server with url: {}", serverBaseUrl);
successful = startNotifier.sendNotification(serverBaseUrl);
}
return successful;
}

/**
* Sets up a shutdown notification to the configuration server, if a configuration server url was
* provided.
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,16 @@
import org.mockserver.model.HttpError;
import rocks.inspectit.gepard.agent.MockServerTestBase;
import rocks.inspectit.gepard.agent.configuration.persistence.ConfigurationPersistence;
import rocks.inspectit.gepard.agent.internal.identity.model.AgentInfo;

class HttpConfigurationPollerTest extends MockServerTestBase {

private static HttpConfigurationPoller poller;

private static ConfigurationPersistence persistence;

private static String AGENT_ID = AgentInfo.INFO.getAgentId();

@BeforeEach
void beforeEach() {
persistence = mock(ConfigurationPersistence.class);
Expand All @@ -33,7 +36,7 @@ void afterEach() {
@Test
void runDoesntLoadLocalConfigurationWhenPollingIsSuccessful() {
mockServer
.when(request().withMethod("GET").withPath("/api/v1/agent-configuration"))
.when(request().withMethod("GET").withPath("/api/v1/agent-configuration/" + AGENT_ID))
.respond(response().withStatusCode(200));
poller.run();
verify(persistence, never()).loadLocalConfiguration();
Expand All @@ -52,7 +55,7 @@ void runLoadsLocalConfigurationOnlyOnceWhenConnectionFailed() {
@Test
void configurationRequestIsSentSuccessfully() {
mockServer
.when(request().withMethod("GET").withPath("/api/v1/agent-configuration"))
.when(request().withMethod("GET").withPath("/api/v1/agent-configuration/" + AGENT_ID))
.respond(response().withStatusCode(200));

boolean successful = poller.pollConfiguration();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
import java.io.IOException;
import org.apache.commons.io.FileUtils;
import org.mockserver.client.MockServerClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testcontainers.containers.MockServerContainer;
import org.testcontainers.containers.Network;
import org.testcontainers.utility.DockerImageName;
Expand All @@ -22,8 +20,6 @@
*/
public class ConfigurationServerMock {

private static final Logger logger = LoggerFactory.getLogger(ConfigurationServerMock.class);

private MockServerContainer server;
private MockServerClient serverClient;

Expand Down Expand Up @@ -56,7 +52,7 @@ public void configServerSetup(String config_path) throws IOException {
String body = FileUtils.readFileToString(file, "UTF-8");

serverClient
.when(request().withMethod("GET").withPath("/api/v1/agent-configuration"))
.when(request().withMethod("GET").withPath("/api/v1/agent-configuration/.*"))
.respond(response().withStatusCode(200).withBody(body));

serverClient
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,22 @@

import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.lang.reflect.Field;
import org.junit.jupiter.api.BeforeEach;
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 {

@BeforeEach
public void setup() throws NoSuchFieldException, IllegalAccessException {
Field instance = IdentityManager.class.getDeclaredField("instance");
instance.setAccessible(true);
instance.set(null, null);
}

@Test
void testCreateIdentityManagerSuccessfully() {
RuntimeMXBean mockRuntimeMXBean = mock(RuntimeMXBean.class);
Expand All @@ -33,9 +39,7 @@ void testCreateIdentityManagerSuccessfully() {

assertNotNull(identityInfo);
assertEquals("12345@mockedHostName", identityInfo.vmId());
assertEquals(
"d29aca592fc2071bcef6577d649071d4d54a8ae6cd5c0be0e51f28af2867f207",
identityInfo.agentId());
assertNotNull(identityInfo.agentId());
}
}
}
Loading
Loading