-
Notifications
You must be signed in to change notification settings - Fork 41
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
✨ Adds cert-manager operator system-x
- Loading branch information
Showing
8 changed files
with
379 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
<?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"> | ||
<parent> | ||
<artifactId>system-x-services</artifactId> | ||
<groupId>software.tnb</groupId> | ||
<version>1.0-SNAPSHOT</version> | ||
</parent> | ||
<properties> | ||
<velocity.version>2.4.1</velocity.version> | ||
</properties> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<artifactId>system-x-cert-manager</artifactId> | ||
<version>1.0-SNAPSHOT</version> | ||
<name>TNB :: System-X :: Services :: Cert Manager</name> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>org.apache.velocity</groupId> | ||
<artifactId>velocity-engine-core</artifactId> | ||
<version>${velocity.version}</version> | ||
<exclusions> | ||
<exclusion> | ||
<groupId>org.apache.commons</groupId> | ||
<artifactId>commons-lang3</artifactId> | ||
</exclusion> | ||
<exclusion> | ||
<groupId>org.slf4j</groupId> | ||
<artifactId>slf4j-api</artifactId> | ||
</exclusion> | ||
</exclusions> | ||
</dependency> | ||
</dependencies> | ||
|
||
</project> |
124 changes: 124 additions & 0 deletions
124
...nager/src/main/java/software/tnb/certmanager/resource/opesnhift/OpenshiftCertManager.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
package software.tnb.certmanager.resource.opesnhift; | ||
|
||
import software.tnb.certmanager.service.CertManager; | ||
import software.tnb.common.deployment.ReusableOpenshiftDeployable; | ||
import software.tnb.common.deployment.WithCustomResource; | ||
import software.tnb.common.deployment.WithOperatorHub; | ||
import software.tnb.common.openshift.OpenshiftClient; | ||
import software.tnb.common.utils.WaitUtils; | ||
|
||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
|
||
import com.google.auto.service.AutoService; | ||
|
||
import java.util.Map; | ||
import java.util.function.BooleanSupplier; | ||
import java.util.function.Predicate; | ||
|
||
import cz.xtf.core.openshift.helpers.ResourceParsers; | ||
import io.fabric8.kubernetes.api.model.GenericKubernetesResource; | ||
import io.fabric8.kubernetes.api.model.Pod; | ||
|
||
@AutoService(CertManager.class) | ||
public class OpenshiftCertManager extends CertManager implements ReusableOpenshiftDeployable, WithOperatorHub, WithCustomResource { | ||
|
||
private static final Logger LOG = LoggerFactory.getLogger(OpenshiftCertManager.class); | ||
|
||
@Override | ||
public void undeploy() { | ||
OpenshiftClient.get().genericKubernetesResources(apiVersion(), kind()).delete(); | ||
WaitUtils.waitFor(() -> servicePod() == null, "Waiting until the pod is removed"); | ||
deleteSubscription(() -> OpenshiftClient.get().getLabeledPods("name", "cert-manager-operator").isEmpty()); | ||
} | ||
|
||
/** | ||
* Open all resources needed after the service is deployed - initialize clients and stuff. | ||
*/ | ||
@Override | ||
public void openResources() { | ||
} | ||
|
||
/** | ||
* Close all resources used after before the service is undeployed. | ||
*/ | ||
@Override | ||
public void closeResources() { | ||
//do nothing | ||
} | ||
|
||
@Override | ||
public void create() { | ||
LOG.debug("Creating Cert Manager instance"); | ||
// Create subscription | ||
createSubscription(); | ||
|
||
WaitUtils.waitFor(() -> !OpenshiftClient.get() | ||
.pods().inNamespace(targetNamespace()) | ||
.withLabel("name", "cert-manager-operator").list().getItems().isEmpty() | ||
, "Wait for the operator has been installed"); | ||
|
||
} | ||
|
||
@Override | ||
public boolean isReady() { | ||
return ResourceParsers.isPodReady(OpenshiftClient.get() | ||
.pods().inNamespace(targetNamespace()) | ||
.withLabel("name", "cert-manager-operator").list().getItems().get(0)); | ||
} | ||
|
||
@Override | ||
public boolean isDeployed() { | ||
return isReady(); | ||
} | ||
|
||
@Override | ||
public Predicate<Pod> podSelector() { | ||
return p -> OpenshiftClient.get().hasLabels(p, Map.of("name", "cert-manager-operator")); | ||
} | ||
|
||
@Override | ||
public void cleanup() { | ||
//do nothing | ||
} | ||
|
||
@Override | ||
public String operatorChannel() { | ||
return "stable-v1"; | ||
} | ||
|
||
@Override | ||
public String operatorName() { | ||
return "openshift-cert-manager-operator"; | ||
} | ||
|
||
@Override | ||
public String kind() { | ||
return "CertManager"; | ||
} | ||
|
||
@Override | ||
public String apiVersion() { | ||
return "operator.openshift.io/v1alpha1"; | ||
} | ||
|
||
@Override | ||
public GenericKubernetesResource customResource() { | ||
return null; | ||
} | ||
|
||
@Override | ||
public String targetNamespace() { | ||
return "cert-manager-operator"; | ||
} | ||
|
||
@Override | ||
public String subscriptionName() { | ||
return "openshift-cert-manager-operator"; | ||
} | ||
|
||
@Override | ||
public void deleteSubscription(BooleanSupplier waitCondition) { | ||
//want to keep the operator | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
...m-x/services/cert-manager/src/main/java/software/tnb/certmanager/service/CertManager.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package software.tnb.certmanager.service; | ||
|
||
import software.tnb.certmanager.validation.CertManagerValidation; | ||
import software.tnb.common.account.NoAccount; | ||
import software.tnb.common.client.NoClient; | ||
import software.tnb.common.service.Service; | ||
|
||
import java.util.Optional; | ||
|
||
public abstract class CertManager extends Service<NoAccount, NoClient, CertManagerValidation> { | ||
|
||
@Override | ||
public CertManagerValidation validation() { | ||
validation = Optional.ofNullable(validation) | ||
.orElseGet(CertManagerValidation::new); | ||
return validation; | ||
} | ||
} |
156 changes: 156 additions & 0 deletions
156
...cert-manager/src/main/java/software/tnb/certmanager/validation/CertManagerValidation.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
package software.tnb.certmanager.validation; | ||
|
||
import software.tnb.common.openshift.OpenshiftClient; | ||
import software.tnb.common.validation.Validation; | ||
|
||
import org.apache.velocity.Template; | ||
import org.apache.velocity.VelocityContext; | ||
import org.apache.velocity.app.VelocityEngine; | ||
import org.apache.velocity.runtime.RuntimeConstants; | ||
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader; | ||
import org.yaml.snakeyaml.Yaml; | ||
|
||
import java.io.StringWriter; | ||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
||
import io.fabric8.kubernetes.api.model.GenericKubernetesResourceBuilder; | ||
import io.fabric8.kubernetes.api.model.ServiceAccount; | ||
import io.fabric8.kubernetes.api.model.ServiceAccountBuilder; | ||
import io.fabric8.kubernetes.api.model.rbac.PolicyRule; | ||
import io.fabric8.kubernetes.api.model.rbac.Role; | ||
import io.fabric8.kubernetes.api.model.rbac.RoleBinding; | ||
import io.fabric8.kubernetes.api.model.rbac.RoleBindingBuilder; | ||
import io.fabric8.kubernetes.api.model.rbac.RoleBuilder; | ||
import io.fabric8.kubernetes.api.model.rbac.RoleRef; | ||
import io.fabric8.kubernetes.api.model.rbac.Subject; | ||
import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext; | ||
|
||
public class CertManagerValidation implements Validation { | ||
|
||
private static final CustomResourceDefinitionContext ISSUER_CTX = new CustomResourceDefinitionContext | ||
.Builder() | ||
.withGroup("cert-manager.io") | ||
.withKind("Issuer") | ||
.withName("issuers.cert-manager.io") | ||
.withPlural("issuers") | ||
.withScope("Namespaced") | ||
.withVersion("v1") | ||
.build(); | ||
|
||
private static final CustomResourceDefinitionContext CERTIFICATE_CTX = new CustomResourceDefinitionContext | ||
.Builder() | ||
.withGroup("cert-manager.io") | ||
.withKind("Certificate") | ||
.withName("certificates.cert-manager.io") | ||
.withPlural("certificates") | ||
.withScope("Namespaced") | ||
.withVersion("v1") | ||
.build(); | ||
|
||
/** | ||
* Creates self-signed issuer in the current namespace | ||
*/ | ||
public void createSelfSignedIssuer() { | ||
OpenshiftClient.get().genericKubernetesResources(ISSUER_CTX) | ||
.inNamespace(OpenshiftClient.get().getNamespace()) | ||
.resource(new GenericKubernetesResourceBuilder() | ||
.withKind(ISSUER_CTX.getKind()) | ||
.withNewMetadata() | ||
.withName("selfsigned-issuer") | ||
.endMetadata() | ||
.withAdditionalProperties(Map.of("spec", Map.of( | ||
"selfSigned", Map.of() | ||
))) | ||
.build() | ||
).create(); | ||
} | ||
|
||
/** | ||
* Creates self-signed certificate in the current namespace, it requires createSelfSignedIssuer to be called | ||
* @param name String, the name of the certificate CR | ||
* @param secretName String, the name of the secret that will contain the certificates | ||
* @param commonName String, the common name assigned to the certificate | ||
* @param usages List, the list of the usages according | ||
* to <a href="https://cert-manager.io/docs/reference/api-docs/#cert-manager.io/v1.KeyUsage">KeyUsage</a> | ||
* @param dnsNames List, the list of the associated names | ||
* @param passwordSecretName String, the name of the secret, containing the key `password` to use as password | ||
*/ | ||
public void createSelfSignedCertificate(String name, String secretName, String commonName, List<String> usages | ||
, List<String> dnsNames, String passwordSecretName) { | ||
VelocityEngine engine = new VelocityEngine(); | ||
engine.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath"); | ||
engine.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName()); | ||
engine.init(); | ||
Template template = engine.getTemplate("cert-manager/certificate-template.vm"); | ||
VelocityContext context = new VelocityContext(); | ||
context.put("name", name); | ||
context.put("secretName", secretName); | ||
context.put("commonName", commonName); | ||
context.put("namespace", OpenshiftClient.get().getNamespace()); | ||
context.put("usagesList", usages); | ||
context.put("dnsNameList", dnsNames); | ||
context.put("passwordSecretRef", passwordSecretName); | ||
StringWriter writer = new StringWriter(); | ||
template.merge(context, writer); | ||
Map<String, Object> spec = new Yaml().load(writer.toString()); | ||
|
||
OpenshiftClient.get().genericKubernetesResources(CERTIFICATE_CTX) | ||
.inNamespace(OpenshiftClient.get().getNamespace()) | ||
.resource(new GenericKubernetesResourceBuilder() | ||
.withKind(CERTIFICATE_CTX.getKind()) | ||
.withNewMetadata() | ||
.withName(name) | ||
.endMetadata() | ||
.withAdditionalProperties(spec) | ||
.build() | ||
).create(); | ||
} | ||
|
||
/** | ||
* Creates a service account enabled to read secrets in the current namespace. | ||
* A new service account, role and role binding will be created | ||
* @param serviceAccount String, the name of the service account | ||
*/ | ||
public void createSecretViewer(String serviceAccount) { | ||
final String roleName = "secret-viewer"; | ||
final String roleBingingName = "sa-secret-viewer"; | ||
|
||
ServiceAccount sa = new ServiceAccountBuilder() | ||
.withNewMetadata().withName(serviceAccount).endMetadata() | ||
.withAutomountServiceAccountToken(false) | ||
.build(); | ||
OpenshiftClient.get().serviceAccounts().inNamespace(OpenshiftClient.get().getNamespace()).resource(sa).create(); | ||
|
||
List<PolicyRule> policyRuleList = new ArrayList<>(); | ||
PolicyRule endpoints = new PolicyRule(); | ||
endpoints.setApiGroups(List.of("")); | ||
endpoints.setResources(List.of("secrets")); | ||
endpoints.setVerbs(Arrays.asList("get", "list", "watch")); | ||
policyRuleList.add(endpoints); | ||
Role roleCreated = new RoleBuilder() | ||
.withNewMetadata().withName(roleName).withNamespace(OpenshiftClient.get().getNamespace()).endMetadata() | ||
.addAllToRules(policyRuleList) | ||
.build(); | ||
OpenshiftClient.get().rbac().roles().resource(roleCreated).create(); | ||
|
||
List<Subject> subjects = new ArrayList<>(); | ||
Subject subject = new Subject(); | ||
subject.setKind("ServiceAccount"); | ||
subject.setName(sa.getMetadata().getName()); | ||
subject.setNamespace(OpenshiftClient.get().getNamespace()); | ||
subjects.add(subject); | ||
RoleRef roleRef = new RoleRef(); | ||
roleRef.setApiGroup("rbac.authorization.k8s.io"); | ||
roleRef.setKind("Role"); | ||
roleRef.setName(roleCreated.getMetadata().getName()); | ||
RoleBinding roleBindingCreated = new RoleBindingBuilder() | ||
.withNewMetadata().withName(roleBingingName).withNamespace(OpenshiftClient.get().getNamespace()).endMetadata() | ||
.withRoleRef(roleRef) | ||
.addAllToSubjects(subjects) | ||
.build(); | ||
OpenshiftClient.get().rbac().roleBindings().resource(roleBindingCreated).create(); | ||
} | ||
} |
34 changes: 34 additions & 0 deletions
34
system-x/services/cert-manager/src/main/resources/cert-manager/certificate-template.vm
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
spec: | ||
secretName: $secretName | ||
duration: 2160h | ||
renewBefore: 360h | ||
subject: | ||
organizations: | ||
- $namespace | ||
|
||
commonName: $commonName | ||
isCA: false | ||
privateKey: | ||
algorithm: RSA | ||
encoding: PKCS1 | ||
size: 2048 | ||
usages: | ||
#foreach($usage in $usagesList) | ||
- $usage | ||
#end | ||
|
||
dnsNames: | ||
#foreach($dnsName in $dnsNameList) | ||
- $dnsName | ||
#end | ||
issuerRef: | ||
name: selfsigned-issuer | ||
kind: Issuer | ||
group: cert-manager.io | ||
|
||
keystores: | ||
jks: | ||
create: true | ||
passwordSecretRef: | ||
name: $passwordSecretRef | ||
key: password |
Oops, something went wrong.