mirror of https://github.com/apache/druid.git
adding a properties endpoint in status resource (#5276)
* adding a properties endpoint in status resource * checkstyle fixes * more checkstyle corrections * correcting the resource filter for properties endpoint * adding feature of hiding sensitive properties * checkstyle changes * review changes for adding default hidden properties and using jackson for arrays value * making review changes
This commit is contained in:
parent
deeda0dff2
commit
305ecc2a78
|
@ -121,3 +121,8 @@ druid.emitter.logging.logLevel=info
|
|||
# ommiting this will lead to index double as float at the storage layer
|
||||
|
||||
druid.indexing.doubleStorage=double
|
||||
|
||||
#
|
||||
# Security
|
||||
#
|
||||
druid.server.hiddenProperties=["druid.s3.accessKey","druid.s3.secretKey","druid.metadata.storage.connector.password"]
|
||||
|
|
|
@ -20,8 +20,11 @@
|
|||
package io.druid.client;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*/
|
||||
|
@ -37,6 +40,10 @@ public class DruidServerConfig
|
|||
@JsonProperty
|
||||
private int priority = DruidServer.DEFAULT_PRIORITY;
|
||||
|
||||
@JsonProperty
|
||||
@NotNull
|
||||
private Set<String> hiddenProperties = Sets.newHashSet("druid.s3.accessKey", "druid.s3.secretKey", "druid.metadata.storage.connector.password");
|
||||
|
||||
public long getMaxSize()
|
||||
{
|
||||
return maxSize;
|
||||
|
@ -51,4 +58,9 @@ public class DruidServerConfig
|
|||
{
|
||||
return priority;
|
||||
}
|
||||
|
||||
public Set<String> getHiddenProperties()
|
||||
{
|
||||
return hiddenProperties;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,12 +21,16 @@ package io.druid.server;
|
|||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.sun.jersey.spi.container.ResourceFilters;
|
||||
import io.druid.client.DruidServerConfig;
|
||||
import io.druid.initialization.DruidModule;
|
||||
import io.druid.initialization.Initialization;
|
||||
import io.druid.java.util.common.StringUtils;
|
||||
import io.druid.server.http.security.ConfigResourceFilter;
|
||||
import io.druid.server.http.security.StateResourceFilter;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
|
@ -34,12 +38,38 @@ import javax.ws.rs.core.MediaType;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*/
|
||||
@Path("/status")
|
||||
public class StatusResource
|
||||
{
|
||||
|
||||
private final Properties properties;
|
||||
|
||||
private final DruidServerConfig druidServerConfig;
|
||||
|
||||
@Inject
|
||||
public StatusResource(Properties properties, DruidServerConfig druidServerConfig)
|
||||
{
|
||||
this.properties = properties;
|
||||
this.druidServerConfig = druidServerConfig;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/properties")
|
||||
@ResourceFilters(ConfigResourceFilter.class)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Map<String, String> getProperties()
|
||||
{
|
||||
Map<String, String> allProperties = Maps.fromProperties(properties);
|
||||
Set<String> hidderProperties = druidServerConfig.getHiddenProperties();
|
||||
return Maps.filterEntries(allProperties, (entry) -> !hidderProperties.contains(entry.getKey()));
|
||||
}
|
||||
|
||||
@GET
|
||||
@ResourceFilters(StateResourceFilter.class)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
|
|
|
@ -74,6 +74,7 @@ public class ConfigResourceFilter extends AbstractResourceFilter
|
|||
{
|
||||
return requestPath.startsWith("druid/worker/v1") ||
|
||||
requestPath.startsWith("druid/indexer/v1") ||
|
||||
requestPath.startsWith("status/properties") ||
|
||||
requestPath.startsWith("druid/coordinator/v1/config");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,10 +33,6 @@ import com.google.inject.Provides;
|
|||
import com.google.inject.Scopes;
|
||||
import com.google.inject.Singleton;
|
||||
import com.google.inject.multibindings.Multibinder;
|
||||
import io.druid.java.util.emitter.service.ServiceEmitter;
|
||||
import io.druid.java.util.emitter.service.ServiceMetricEvent;
|
||||
import io.druid.java.util.metrics.AbstractMonitor;
|
||||
import io.druid.java.util.metrics.MonitorUtils;
|
||||
import com.sun.jersey.api.core.DefaultResourceConfig;
|
||||
import com.sun.jersey.api.core.ResourceConfig;
|
||||
import com.sun.jersey.guice.JerseyServletModule;
|
||||
|
@ -53,6 +49,10 @@ import io.druid.java.util.common.ISE;
|
|||
import io.druid.java.util.common.RE;
|
||||
import io.druid.java.util.common.lifecycle.Lifecycle;
|
||||
import io.druid.java.util.common.logger.Logger;
|
||||
import io.druid.java.util.emitter.service.ServiceEmitter;
|
||||
import io.druid.java.util.emitter.service.ServiceMetricEvent;
|
||||
import io.druid.java.util.metrics.AbstractMonitor;
|
||||
import io.druid.java.util.metrics.MonitorUtils;
|
||||
import io.druid.server.DruidNode;
|
||||
import io.druid.server.StatusResource;
|
||||
import io.druid.server.initialization.ServerConfig;
|
||||
|
|
|
@ -19,14 +19,22 @@
|
|||
|
||||
package io.druid.server;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
import io.druid.guice.PropertiesModule;
|
||||
import io.druid.initialization.DruidModule;
|
||||
import io.druid.initialization.InitializationTest;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static io.druid.server.StatusResource.ModuleVersion;
|
||||
|
||||
|
@ -55,5 +63,16 @@ public class StatusResourceTest
|
|||
Assert.assertTrue("Status resource should contain module " + moduleName, contains);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPropertiesWithRestrictedConfigs()
|
||||
{
|
||||
Injector injector = Guice.createInjector(Collections.singletonList(new PropertiesModule(Collections.singletonList(
|
||||
"status.resource.test.runtime.properties"))));
|
||||
Map<String, String> returnedProperties = injector.getInstance(StatusResource.class).getProperties();
|
||||
Set<String> hiddenProperties = Sets.newHashSet();
|
||||
Splitter.on(",").split(returnedProperties.get("druid.server.hiddenProperties")).forEach(hiddenProperties::add);
|
||||
hiddenProperties.forEach((property) -> Assert.assertNull(returnedProperties.get(property)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
druid.server.hiddenProperties=["druid.s3.accessKey","druid.s3.secretKey","druid.metadata.storage.connector.password"]
|
||||
druid.storage.type=s3
|
||||
druid.storage.bucket=your-bucket
|
||||
druid.storage.baseKey=druid/segments
|
||||
druid.s3.accessKey=s3accesskey
|
||||
druid.s3.secretKey=s3secretkey
|
||||
|
||||
druid.metadata.storage.type=mysql
|
||||
druid.metadata.storage.connector.connectURI=jdbc:mysql://db.example.com:3306/druid
|
||||
druid.metadata.storage.connector.user=druiduser
|
||||
druid.metadata.storage.connector.password=password123
|
Loading…
Reference in New Issue