Skip to content

Commit

Permalink
Add some settings to specify a remote Openshift cluster URL
Browse files Browse the repository at this point in the history
  • Loading branch information
barkbay committed Oct 9, 2018
1 parent 2e1e117 commit fc96d27
Show file tree
Hide file tree
Showing 10 changed files with 160 additions and 7 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ The following additional parameters can be set in set in `elasticsearch.yml`:
|*_openshift.acl.expire_in_millis_*| The delay in milliseconds before generated ACLs are removed from|
|*_openshift.config.project_index_prefix_*| The string value that project/namespace indices use as their prefix (default: ``) for example, with the common data model, if the namespace is `test`, the index name will be `project.test.$uuid.YYYY.MM.DD`. In this case, use `"project"` as the prefix - do not include the trailing `.`.|
|*_openshift.kibana.index.mode_*| The setting that determines the kibana index is used by users. Valid values are one of the following: <ul><li>**unique** (Default) - Each user gets a unique index for kibana visualizations (e.g. .kibana.USER_UUID)</ul></li><ul><li>**ops_shared** - Users who are in an ops role will share an index (e.g. kibana) while non ops users will have a unique index (e.g. .kibana.USER_UUID)</ul></li>|
|*openshift.master*| If Openshift users must be authenticated to a remote cluster, this parameter must contain its URL (default: `https://kubernetes.default.svc`).|
|*openshift.trust.certificates*| Trust remote Openshift certificate (default: `true`)|
|*openshift.ca.path*| Absolute file path to the certificate that has to be used to authenticate remote Openshift cluster (default: `empty`)|

*Note*: The `io.fabric8.elasticsearch.kibana.mapping.*` properties are required and must be defined for the plugin to function. A sample file
may be found in the `samples` folder.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ public interface ConfigurationSettings extends KibanaIndexMode{
static final String OPENSHIFT_ACL_ROLE_STRATEGY = "openshift.acl.role_strategy";
static final String DEFAULT_ACL_ROLE_STRATEGY = "user";

static final String OPENSHIFT_MASTER = "openshift.master";
static final String OPENSHIFT_CA_PATH = "openshift.ca.path";
static final String OPENSHIFT_TRUST_CERT = "openshift.trust.certificates";

/**
* List of index patterns to create for operations users
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public Collection<Object> createComponents(Client client, ClusterService cluster
final PluginSettings pluginSettings = new PluginSettings(settings);
final IndexMappingLoader indexMappingLoader = new IndexMappingLoader(settings);
final PluginClient pluginClient = new PluginClient(client, threadPool.getThreadContext());
final OpenshiftAPIService apiService = new OpenshiftAPIService();
final OpenshiftAPIService apiService = new OpenshiftAPIService(pluginSettings);
final RequestUtils requestUtils = new RequestUtils(pluginSettings, apiService);
final OpenshiftRequestContextFactory contextFactory = new OpenshiftRequestContextFactory(settings, requestUtils,
apiService);
Expand Down Expand Up @@ -216,6 +216,9 @@ public List<Setting<?>> getSettings() {
settings.add(Setting.boolSetting("openshift.operations.allow_cluster_reader", false, Property.NodeScope));
settings.add(Setting.simpleString("openshift.kibana.index.mode", Property.NodeScope));
settings.add(Setting.simpleString(OPENSHIFT_ACL_ROLE_STRATEGY, Property.NodeScope));
settings.add(Setting.simpleString(OPENSHIFT_MASTER, Property.NodeScope));
settings.add(Setting.simpleString(OPENSHIFT_CA_PATH, Property.NodeScope));
settings.add(Setting.simpleString(OPENSHIFT_TRUST_CERT, Property.NodeScope));
return settings;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.apache.logging.log4j.Logger;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.ElasticsearchSecurityException;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
Expand All @@ -48,6 +49,13 @@ public class OpenshiftAPIService {
private static final String CONTENT_TYPE = "Content-Type";
private static final String APPLICATION_JSON = "application/json";
private static final Logger LOGGER = Loggers.getLogger(OpenshiftAPIService.class);

private final PluginSettings settings;

@Inject
public OpenshiftAPIService(PluginSettings settings) {
this.settings = settings;
}

public String userName(final String token) {
Response response = null;
Expand Down Expand Up @@ -141,8 +149,21 @@ public boolean localSubjectAccessReview(final String token,
return false;
}

private DefaultOpenShiftClient buildClient(final String token) {
DefaultOpenShiftClient buildClient(final String token) {
Config config = new ConfigBuilder().withOauthToken(token).build();

if (settings.getMasterUrl() != null) {
config.setMasterUrl(settings.getMasterUrl());
}
if (settings.isTrustCerts() != null) {
config.setTrustCerts(settings.isTrustCerts());
}
if (settings.getOpenshiftCaPath() != null) {
config.setCaCertFile(settings.getOpenshiftCaPath());
}
LOGGER.debug("Target cluster is {}, trust cert is {}, ca path is {}",
config.getMasterUrl(), config.isTrustCerts(), config.getCaCertFile());

return new DefaultOpenShiftClient(config);
}
}
24 changes: 24 additions & 0 deletions src/main/java/io/fabric8/elasticsearch/plugin/PluginSettings.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ public class PluginSettings implements ConfigurationSettings {
private final Set<String> opsIndexPatterns;
private final long expireInMillis;
private final Settings settings;
private final String masterUrl;
private final Boolean isTrustCerts;
private final String openshiftCaPath;

public PluginSettings(final Settings settings) {
this.settings = settings;
Expand All @@ -64,6 +67,15 @@ public PluginSettings(final Settings settings) {
this.opsIndexPatterns = new HashSet<String>(Arrays.asList(settings.getAsArray(OPENSHIFT_KIBANA_OPS_INDEX_PATTERNS, DEFAULT_KIBANA_OPS_INDEX_PATTERNS)));
this.expireInMillis = settings.getAsLong(OPENSHIFT_ACL_EXPIRE_IN_MILLIS, new Long(1000 * 60));

this.masterUrl = settings.get(OPENSHIFT_MASTER);
this.openshiftCaPath = settings.get(OPENSHIFT_CA_PATH);
// Do not overwrite default K8S behavior
if (settings.get(OPENSHIFT_TRUST_CERT) != null) {
this.isTrustCerts = settings.getAsBoolean(OPENSHIFT_TRUST_CERT, true);
} else {
this.isTrustCerts = null;
}

LOGGER.info("Using kibanaIndexMode: '{}'", this.kibanaIndexMode);
LOGGER.debug("searchGuardIndex: {}", this.searchGuardIndex);
LOGGER.debug("roleStrategy: {}", this.roleStrategy);
Expand Down Expand Up @@ -113,4 +125,16 @@ public void setKibanaIndexMode(String kibanaIndexMode) {
public Set<String> getKibanaOpsIndexPatterns() {
return opsIndexPatterns;
}

public String getMasterUrl() {
return masterUrl;
}

public String getOpenshiftCaPath() {
return openshiftCaPath;
}

public Boolean isTrustCerts() {
return isTrustCerts;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public String getBearerToken(RestRequest request) {
}
return StringUtils.defaultIfEmpty(token, "");
}

public boolean isClientCertAuth(final ThreadContext threadContext) {
return threadContext != null && StringUtils.isNotEmpty(threadContext.getTransient("_sg_ssl_transport_principal"));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
import java.util.HashSet;
import java.util.Set;

import org.elasticsearch.common.settings.Settings;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
Expand All @@ -35,11 +37,15 @@ public class OpenshiftAPIServiceTest {

@Rule
public OpenShiftServer apiServer = new OpenShiftServer();
private OpenshiftAPIService service = new OpenshiftAPIService();

private final PluginSettings pluginSettings = new PluginSettings(Settings.EMPTY);
private final OpenshiftAPIService service = new OpenshiftAPIService(pluginSettings);



@Before
public void setup() {
final String basedir = System.getProperty("project.basedir");
final String basedir = System.getProperty("basedir");
final String password = "changeit";
final String keyStore = basedir + "/src/it/resources/keystore.jks";
final String masterUrl = apiServer.getMockServer().url("/").toString();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package io.fabric8.elasticsearch.plugin;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.io.File;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

import com.google.common.io.Files;

import io.fabric8.kubernetes.client.Config;
import io.fabric8.kubernetes.client.ConfigBuilder;
import io.fabric8.openshift.client.NamespacedOpenShiftClient;

public class OpenshiftClientFactoryTest {

private final String cert =
"-----BEGIN CERTIFICATE-----\n"
+ "MIIC0DCCAbigAwIBAgIBATANBgkqhkiG9w0BAQsFADAZMRcwFQYDVQQDEw5sb2dn\n"
+ "aW5nLXNpZ25lcjAeFw0xNzEwMTQxMTMwMDFaFw0yNzEwMTIxMTMwMDJaMBkxFzAV\n"
+ "BgNVBAMTDmxvZ2dpbmctc2lnbmVyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB\n"
+ "CgKCAQEAwjq3zygMEywx0PD/qGO2IwZxN18DwJbWB71JH+ldbLQHMJ3fvIy4wpJV\n"
+ "FlJDPAejQ6hFnsoArVZInxcIcVfTiLgX15CXfCcrWUXXxfY2WWc6qDbQKje/+VZX\n"
+ "/nr8c5DvbiDQxTDjXNO7WDGxqCaJIKg72VIqE4ac4AYNEwHeW3rd5cLEh/wfAu3n\n"
+ "/iGFQ0v75ZG8ef2QQE364/d5GHMrXcWXUrXxuqRO/wdEjuXkP3SY/8sUZHCdugt8\n"
+ "QygSXLp5mHaMc+Ie70/gl7u8wAxJGOvkjYVEgZPUTbemjEYhr9QwMuPvXxalWNc8\n"
+ "kWIsOXnnyKG+RWDo7FE7kZtXpYfBcwIDAQABoyMwITAOBgNVHQ8BAf8EBAMCAqQw\n"
+ "DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAf+1IaNvSYQ1BNQVa\n"
+ "hODEru6x+Ytg5HUyykT4tmxvvlqLS03ez37zKi2tDQBI/Sl4l46mu9H7GS98viO7\n"
+ "Cj9Vn7km70GH6vDvCjY3iMKYK+rXzp1D2az0wmdmYymfrP8WC4X0q+KMZKPSVb9g\n"
+ "9/0kAKPtH7YRzTiaSMlWhxNFQxM+zrHvw/Vp16PXZwq+FCbtv6zemQKo4JBHN2LM\n"
+ "dIfgLqEMBkpvo1TeD3HOB4LyJJ6nnG4bUWsOnYYSZw1L70rHX9Vu5xq7xap2eL9g\n"
+ "Uk4XsS8F+8hOE3zaHbqKbxRSqxnNqBI+UM+nQc1i3Qh2CXy8jgdVTjxWstDN/IHN\n"
+ "Y6RrKw== \n"
+ "-----END CERTIFICATE-----";

// We need a temporary folder because K8S plugin check if CA file exists in constructor
@Rule
public TemporaryFolder certFolder = new TemporaryFolder();

@Test
public void testWhenRemoteCAIsNotNull() throws Exception {

File tempCaFile = certFolder.newFile("ca.crt");
Files.write(cert.getBytes(), tempCaFile);

final Config config = (new ConfigBuilder()).build();
final PluginSettings pluginSettings = mock(PluginSettings.class);
when(pluginSettings.getOpenshiftCaPath()).thenReturn(tempCaFile.getAbsolutePath());
when(pluginSettings.getMasterUrl()).thenReturn("https://foo.bar");
when(pluginSettings.isTrustCerts()).thenReturn(false);

OpenshiftAPIService openshiftAPIService = new OpenshiftAPIService(pluginSettings);
final NamespacedOpenShiftClient openShiftClient = openshiftAPIService.buildClient("foo");
final Config k8sConfig = openShiftClient.getConfiguration();

assertEquals("Exp. the CA file path to be loaded by K8S plugin", tempCaFile.getAbsolutePath(), k8sConfig.getCaCertFile());
assertEquals("Exp. the master url to be correctly set in the K8S plugin", "https://foo.bar/", k8sConfig.getMasterUrl());
assertFalse("Exp. the trust cert boolean to be correctly set in the K8S plugin", k8sConfig.isTrustCerts());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyString;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
package io.fabric8.elasticsearch.plugin;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

import org.elasticsearch.common.settings.Settings;
import org.junit.Test;
Expand All @@ -37,4 +40,25 @@ public void testKibanaIndexModeDefault() {
assertEquals("Exp. the plugin default to make kibana index mode unique", "unique", plugin.getKibanaIndexMode());
}

@Test
public void testRemoteOpenshiftWithDefaultConfiguration() {
PluginSettings plugin = new PluginSettings(Settings.builder().build());
assertNull("Exp. remote Openshift URL is null by default to not override default K8S plugin behaviour", plugin.getMasterUrl());
assertNull("Exp. Openshift certificate authority is null by default to not override default K8S plugin behaviour", plugin.getOpenshiftCaPath());
assertNull("Exp. default trust cert is null to not override default K8S plugin behaviour", plugin.isTrustCerts());
}

@Test
public void testRemoteOpenshift() {
final String expectedRemoteOpenshiftUrl = "https://foo.bar:8443";
final String expectedOpenshiftCaPath = "/etc/elasticsearch/secret/openshift-ca";
final String source = "openshift.master: " + expectedRemoteOpenshiftUrl + "\n"
+ "openshift.ca.path: " + expectedOpenshiftCaPath + "\n"
+ "openshift.trust.certificates: false";
PluginSettings plugin = new PluginSettings(Settings.builder().loadFromSource(source).build());
assertEquals("Exp. the correct remote Openshift URL", expectedRemoteOpenshiftUrl, plugin.getMasterUrl());
assertEquals("Exp. the correct Openshift certificate authority", expectedOpenshiftCaPath, plugin.getOpenshiftCaPath());
assertFalse("Exp. the correct non default trust cert value from configuration", plugin.isTrustCerts());
}

}

0 comments on commit fc96d27

Please sign in to comment.