Skip to content

Commit

Permalink
[MGDCTRS-1279] Add splunk to system-x
Browse files Browse the repository at this point in the history
- Move scc creation into OpenShiftClient
  • Loading branch information
mkralik3 authored and avano committed Oct 27, 2022
1 parent fe0d0d2 commit d4c3bcf
Show file tree
Hide file tree
Showing 14 changed files with 15,127 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
import io.fabric8.kubernetes.api.model.Secret;
import io.fabric8.kubernetes.api.model.SecretBuilder;
import io.fabric8.kubernetes.client.Config;
import io.fabric8.openshift.api.model.SecurityContextConstraints;
import io.fabric8.openshift.api.model.SecurityContextConstraintsBuilder;
import io.fabric8.openshift.api.model.operatorhub.v1.OperatorGroupBuilder;
import io.fabric8.openshift.api.model.operatorhub.v1alpha1.InstallPlan;
import io.fabric8.openshift.api.model.operatorhub.v1alpha1.Subscription;
Expand Down Expand Up @@ -400,4 +402,41 @@ public String getIntegrationContainer(Pod pod) {
}
return container;
}

public SecurityContextConstraints createSecurityContext(String sccName, String copyFromScc, String... defaultCapabilities) {
SecurityContextConstraints scc = OpenshiftClient.get().securityContextConstraints().withName(sccName).get();
if (scc == null) {
SecurityContextConstraints existingScc = OpenshiftClient.get().securityContextConstraints().withName(copyFromScc).get();
scc = OpenshiftClient.get().securityContextConstraints().create(
new SecurityContextConstraintsBuilder(existingScc)
.withNewMetadata() // new metadata to override the existing annotations
.withName(sccName)
.endMetadata()
.addToDefaultAddCapabilities(defaultCapabilities)
.build());
}
return scc;
}

public void addUsersToSecurityContext(SecurityContextConstraints scc, String... users) {
for (String user : users) {
if (!scc.getUsers().contains(user)) {
scc.getUsers().add(user);
}
}
OpenshiftClient.get().securityContextConstraints().withName(scc.getMetadata().getName()).patch(scc);
}

public void addGroupsToSecurityContext(SecurityContextConstraints scc, String... groups) {
for (String group : groups) {
if (!scc.getGroups().contains(group)) {
scc.getGroups().add(group);
}
}
OpenshiftClient.get().securityContextConstraints().withName(scc.getMetadata().getName()).patch(scc);
}

public String getServiceAccountRef(String serviceAccountName) {
return "system:serviceaccount:" + OpenshiftConfiguration.openshiftNamespace() + ":" + serviceAccountName;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder;
import io.fabric8.kubernetes.client.LocalPortForward;
import io.fabric8.openshift.api.model.SecurityContextConstraints;
import io.fabric8.openshift.api.model.SecurityContextConstraintsBuilder;

public class OpenshiftDB implements OpenshiftDeployable, WithName {

Expand All @@ -32,19 +31,10 @@ public OpenshiftDB(SQL sqlService, int port) {

@Override
public void create() {
SecurityContextConstraints scc = OpenshiftClient.get().securityContextConstraints().withName(SCC_NAME).get();
if (scc == null) {
SecurityContextConstraints restricted = OpenshiftClient.get().securityContextConstraints().withName("restricted").get();
scc = OpenshiftClient.get().securityContextConstraints().create(
new SecurityContextConstraintsBuilder(restricted)
.withNewMetadata() // new metadata to override the existing annotations
.withName(SCC_NAME)
.endMetadata()
.build());
}
final String group = "system:serviceaccounts:" + OpenshiftConfiguration.openshiftNamespace();
scc.getGroups().add(group);
OpenshiftClient.get().securityContextConstraints().withName(SCC_NAME).patch(scc);
OpenshiftClient.get().addGroupsToSecurityContext(
OpenshiftClient.get().createSecurityContext(SCC_NAME, "restricted"),
"system:serviceaccounts:" + OpenshiftConfiguration.openshiftNamespace());

//@formatter:off
OpenshiftClient.get().apps().deployments().createOrReplace(

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,24 +67,9 @@ public void create() {
.build()
);

SecurityContextConstraints scc = OpenshiftClient.get().securityContextConstraints().withName(SCC_NAME).get();
if (scc == null) {
// if our scc does not exist, copy it from the anyuid and add SYS_CHROOT
SecurityContextConstraints anyuid = OpenshiftClient.get().securityContextConstraints().withName("anyuid").get();
scc = OpenshiftClient.get().securityContextConstraints().create(
new SecurityContextConstraintsBuilder(anyuid)
.withNewMetadata() // new metadata to override the existing annotations
.withName(SCC_NAME)
.endMetadata()
.addToDefaultAddCapabilities("SYS_CHROOT")
.build());
}

final String user = "system:serviceaccount:" + OpenshiftConfiguration.openshiftNamespace() + ":" + serviceAccountName;
if (!scc.getUsers().contains(user)) {
scc.getUsers().add(user);
OpenshiftClient.get().securityContextConstraints().withName(SCC_NAME).patch(scc);
}
OpenshiftClient.get().addUsersToSecurityContext(
OpenshiftClient.get().createSecurityContext(SCC_NAME, "anyuid", "SYS_CHROOT"),
OpenshiftClient.get().getServiceAccountRef(serviceAccountName));

OpenshiftClient.get().apps().deployments().createOrReplace(
new DeploymentBuilder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@
import io.fabric8.openshift.api.model.RoutePortBuilder;
import io.fabric8.openshift.api.model.RouteTargetReferenceBuilder;
import io.fabric8.openshift.api.model.SecurityContextConstraints;
import io.fabric8.openshift.api.model.SecurityContextConstraintsBuilder;

@AutoService(MailServer.class)
public class OpenshiftMailServer extends MailServer implements ReusableOpenshiftDeployable, WithName, WithInClusterHostname, WithExternalHostname {
Expand All @@ -61,24 +60,9 @@ public void create() {
.build()
);

SecurityContextConstraints scc = OpenshiftClient.get().securityContextConstraints().withName(SCC_NAME).get();
if (scc == null) {
// if our scc does not exist, copy it from the anyuid and add SYS_CHROOT
SecurityContextConstraints anyuid = OpenshiftClient.get().securityContextConstraints().withName("anyuid").get();
scc = OpenshiftClient.get().securityContextConstraints().create(
new SecurityContextConstraintsBuilder(anyuid)
.withNewMetadata() // new metadata to override the existing annotations
.withName(SCC_NAME)
.endMetadata()
.addToDefaultAddCapabilities("SYS_CHROOT")
.build());
}

final String user = "system:serviceaccount:" + OpenshiftConfiguration.openshiftNamespace() + ":" + serviceAccountName;
if (!scc.getUsers().contains(user)) {
scc.getUsers().add(user);
OpenshiftClient.get().securityContextConstraints().withName(SCC_NAME).patch(scc);
}
OpenshiftClient.get().addUsersToSecurityContext(
OpenshiftClient.get().createSecurityContext(SCC_NAME, "anyuid", "SYS_CHROOT"),
OpenshiftClient.get().getServiceAccountRef(serviceAccountName));

List<ContainerPort> ports = new LinkedList<>();
services.forEach((name, port) -> {
Expand Down
1 change: 1 addition & 0 deletions system-x/services/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
<module>lra-coordinator</module>
<module>mllp</module>
<module>webhook</module>
<module>splunk</module>
</modules>

<dependencies>
Expand Down
39 changes: 39 additions & 0 deletions system-x/services/splunk/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>software.tnb</groupId>
<artifactId>system-x-services</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>

<artifactId>system-x-splunk</artifactId>
<version>1.0-SNAPSHOT</version>
<name>TNB :: System-X :: Services :: Splunk</name>

<properties>
<splunk.client.version>1.9.1</splunk.client.version>
</properties>

<repositories>
<repository>
<id>splunk-artifactory</id>
<name>Splunk Releases</name>
<url>https://splunk.jfrog.io/splunk/ext-releases-local</url>
</repository>
</repositories>

<dependencies>
<dependency>
<groupId>com.splunk</groupId>
<artifactId>splunk</artifactId>
<version>${splunk.client.version}</version>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package software.tnb.splunk.account;

import software.tnb.common.account.Account;

public class SplunkAccount implements Account {

private String username = "admin";

private String password;

public String username() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String password() {
return password;
}

public void setPassword(String password) {
this.password = password;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package software.tnb.splunk.service;

import software.tnb.common.deployment.WithExternalHostname;
import software.tnb.common.service.Service;
import software.tnb.splunk.account.SplunkAccount;
import software.tnb.splunk.validation.SplunkValidation;

import com.splunk.ServiceArgs;

public abstract class Splunk implements Service, WithExternalHostname {

protected SplunkAccount account;
private com.splunk.Service client;
private SplunkValidation validation;

public abstract int apiPort();

public abstract SplunkAccount account();

public abstract String apiSchema();

/**
* Due to self sign certificate, the client is not able to communicate via localhost and port-forward.
* OCP external route with `reencrypt` is used. (Cluster needs to have valid certificate!)
*/
protected com.splunk.Service client() {
if (client == null) {
ServiceArgs loginArgs = new ServiceArgs();
loginArgs.setUsername(account().username());
loginArgs.setPassword(account().password());
loginArgs.setHost(externalHostname());
loginArgs.setPort(apiPort());
loginArgs.setScheme(apiSchema());
client = com.splunk.Service.connect(loginArgs);
}
return client;
}

public SplunkValidation validation() {
if (validation == null) {
validation = new SplunkValidation(client());
}
return validation;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package software.tnb.splunk.service.local;

import software.tnb.common.account.AccountFactory;
import software.tnb.common.deployment.Deployable;
import software.tnb.common.deployment.WithDockerImage;
import software.tnb.splunk.account.SplunkAccount;
import software.tnb.splunk.service.Splunk;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.auto.service.AutoService;

import java.util.Map;

@AutoService(Splunk.class)
public class LocalSplunk extends Splunk implements Deployable, WithDockerImage {

private static final Logger LOG = LoggerFactory.getLogger(LocalSplunk.class);

private SplunkContainer container;

private final int containerApiPort = 8089;
private static final String PASSWORD = "password";

@Override
public void deploy() {
LOG.info("Starting Splunk container");
container = new SplunkContainer(image(), containerApiPort, containerEnvironment());
container.start();
LOG.info("Splunk container started");
}

@Override
public void undeploy() {
if (container != null) {
LOG.info("Stopping Splunk container");
container.stop();
}
}

@Override
public void openResources() {
// nothing to do
}

@Override
public void closeResources() {
// nothing to do
}

@Override
public String defaultImage() {
return "quay.io/fuse_qe/splunk:9.0";
}

@Override
public SplunkAccount account() {
if (account == null) {
account = AccountFactory.create(SplunkAccount.class);
account.setPassword(PASSWORD);
}
return account;
}

// SSL is disabled for local deployment because the app has self-signed certificate and Splunk client throws
// "SunCertPathBuilderException: unable to find valid certification path to requested target" exception
@Override
public String apiSchema() {
return "http";
}

public Map<String, String> containerEnvironment() {
return Map.of(
"SPLUNK_START_ARGS", "--accept-license",
"SPLUNKD_SSL_ENABLE", "false",
"SPLUNK_PASSWORD", PASSWORD
);
}

@Override
public String externalHostname() {
return "localhost";
}

@Override
public int apiPort() {
return container.getMappedPort(containerApiPort);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package software.tnb.splunk.service.local;

import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.wait.strategy.Wait;

import java.util.Map;

/**
* 8000 port = UI
*/
public class SplunkContainer extends GenericContainer<SplunkContainer> {
public SplunkContainer(String image, int containerApiPort, Map<String, String> env) {
super(image);
this.withEnv(env);
this.withExposedPorts(containerApiPort, 8000);
this.waitingFor(Wait.forLogMessage(".*Ansible playbook complete, will begin streaming.*", 1));
}
}
Loading

0 comments on commit d4c3bcf

Please sign in to comment.