Skip to content

Commit

Permalink
Add ConfigResource
Browse files Browse the repository at this point in the history
Closes #31
  • Loading branch information
chrisrohr committed Dec 7, 2020
1 parent 1aacf0f commit 32b80bd
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package org.kiwiproject.dropwizard.util.resource;

import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
import static org.kiwiproject.json.KiwiJacksonSerializers.buildPropertyMaskingSafeSerializerModule;

import com.codahale.metrics.annotation.ExceptionMetered;
import com.codahale.metrics.annotation.Timed;
import io.dropwizard.Configuration;
import lombok.extern.slf4j.Slf4j;
import org.kiwiproject.json.JsonHelper;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;
import java.util.List;

/**
* JAX-RS resource that enables the retrieval of the current runtime configuration of the service.
* <p>
* A list of regex patterns can be given in order to mask secrets in the configuration.
*/
@Slf4j
@Path("app/config")
public class ConfigResource<T extends Configuration> {

// Intentionally creating a separate JsonHelper to allow customizations
private final JsonHelper jsonHelper;
private final T config;

public ConfigResource(T config, List<String> hiddenRegex) {
this.config = config;
this.jsonHelper = JsonHelper.newDropwizardJsonHelper();

jsonHelper.getObjectMapper().registerModule(buildPropertyMaskingSafeSerializerModule(hiddenRegex));
}

@GET
@Timed
@ExceptionMetered
@Produces(APPLICATION_JSON)
public Response getCurrentConfiguration() {
var json = jsonHelper.toJson(config);
return Response.ok(json).build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package org.kiwiproject.dropwizard.util.resource;

import static org.assertj.core.api.Assertions.assertThat;

import io.dropwizard.Application;
import io.dropwizard.Configuration;
import io.dropwizard.setup.Environment;
import io.dropwizard.testing.junit5.DropwizardAppExtension;
import io.dropwizard.testing.junit5.DropwizardExtensionsSupport;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;

import javax.ws.rs.core.GenericType;
import java.util.List;
import java.util.Map;

@DisplayName("ConfigResource")
@ExtendWith(DropwizardExtensionsSupport.class)
class ConfigResourceTest {

@Getter
@Setter
@AllArgsConstructor
static class TestConfig extends Configuration {
private String someNeededProperty;
private String someHiddenPassword;
}

public static class TestApp extends Application<TestConfig> {

public TestApp() {}

@Override
public void run(TestConfig config, Environment environment) {
environment.jersey().register(new ConfigResource<>(config, List.of(".*Password")));
}
}

private static final TestConfig CONFIG = new TestConfig("foo", "secret");
private static final DropwizardAppExtension<TestConfig> APP = new DropwizardAppExtension<>(TestApp.class, CONFIG);

@Test
void shouldReturnConfigAndMaskSecrets() {
var response = APP.client().target("http://localhost:" + APP.getLocalPort() + "/app/config")
.request()
.get();

var configData = response.readEntity(new GenericType<Map<String, Object>>(){});

assertThat(configData)
.containsEntry("someNeededProperty", "foo")
.containsEntry("someHiddenPassword", "********");
}
}

0 comments on commit 32b80bd

Please sign in to comment.