diff --git a/pom.xml b/pom.xml
index 1434c68..026f6a3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -74,19 +74,15 @@
io.quarkus
quarkus-smallrye-openapi
-
info.picocli
picocli
4.7.4
+
+ io.quarkus
+ quarkus-vertx
+
io.quarkus
quarkus-junit5
diff --git a/src/main/java/com/redhat/pctsec/model/RequestType.java b/src/main/java/com/redhat/pctsec/model/RequestType.java
new file mode 100644
index 0000000..a589a78
--- /dev/null
+++ b/src/main/java/com/redhat/pctsec/model/RequestType.java
@@ -0,0 +1,3 @@
+package com.redhat.pctsec.model;
+
+public enum RequestType {BREW, PNC, GIT}
diff --git a/src/main/java/com/redhat/pctsec/model/ScanRequest.java b/src/main/java/com/redhat/pctsec/model/ScanRequest.java
index 16533db..04da19a 100644
--- a/src/main/java/com/redhat/pctsec/model/ScanRequest.java
+++ b/src/main/java/com/redhat/pctsec/model/ScanRequest.java
@@ -12,14 +12,11 @@ import jakarta.persistence.*;
import java.util.HashMap;
import java.util.UUID;
-enum RequestType{BREW, PNC, GIT}
@ApplicationScoped
@Entity
public class ScanRequest {
- @Transient
- @Inject
- EventBus bus;
+
@Id
@GeneratedValue
@@ -27,8 +24,23 @@ public class ScanRequest {
private String metadata;
private String oshScanOptions;
+ public EventBus getBus() {
+ return bus;
+ }
+
+ public void setBus(EventBus bus) {
+ this.bus = bus;
+ }
+
+ @Transient
+ @Inject
+ EventBus bus;
+
+ public RequestType getType() {
+ return type;
+ }
- RequestType type;
+ private RequestType type;
@OneToOne
@JoinColumn(name = "brew_build_id", referencedColumnName = "id")
@@ -65,8 +77,10 @@ public class ScanRequest {
{
this.git = new Git(repo, ref);
}
- public void executeScan(){
- //Drop self on event bus for tekton handler
+ public ScanTask executeScan(){
+ ScanTask st = new ScanTask(this);
+ st.execute();
+ return st;
}
}
diff --git a/src/main/java/com/redhat/pctsec/model/ScanRequests.java b/src/main/java/com/redhat/pctsec/model/ScanRequests.java
index df8ad3e..4d52f3d 100644
--- a/src/main/java/com/redhat/pctsec/model/ScanRequests.java
+++ b/src/main/java/com/redhat/pctsec/model/ScanRequests.java
@@ -2,9 +2,11 @@ package com.redhat.pctsec.model;
import com.redhat.pctsec.model.api.request.pssaas;
import com.redhat.pctsec.model.api.request.scanChain;
+import io.vertx.mutiny.core.eventbus.EventBus;
import jakarta.enterprise.context.ApplicationScoped;
import java.util.*;
+import java.util.stream.Collectors;
import jakarta.persistence.*;
@@ -71,10 +73,14 @@ public class ScanRequests {
}
//Create tekton pipeline/taskrun
- public void execute(){
+ public List execute(EventBus eventBus){
+ scanRequests.stream().forEach(s -> s.setBus(eventBus));
+ return scanRequests.stream().map(s -> s.executeScan()).collect(Collectors.toList());
+ /*
for(ScanRequest s : scanRequests){
s.executeScan();
}
+ */
}
public Set getScanRequests() {
diff --git a/src/main/java/com/redhat/pctsec/model/ScanResult.java b/src/main/java/com/redhat/pctsec/model/ScanResult.java
new file mode 100644
index 0000000..64c56ba
--- /dev/null
+++ b/src/main/java/com/redhat/pctsec/model/ScanResult.java
@@ -0,0 +1,19 @@
+package com.redhat.pctsec.model;
+
+import java.net.URI;
+import java.net.URL;
+
+public class ScanResult {
+
+ public URL covScanTask;
+
+
+ //Store files in document store
+ private void storeResults(){
+
+ }
+
+ private void fetchResults(){
+
+ }
+}
diff --git a/src/main/java/com/redhat/pctsec/model/ScanTask.java b/src/main/java/com/redhat/pctsec/model/ScanTask.java
new file mode 100644
index 0000000..3c1cddb
--- /dev/null
+++ b/src/main/java/com/redhat/pctsec/model/ScanTask.java
@@ -0,0 +1,64 @@
+package com.redhat.pctsec.model;
+
+
+import io.vertx.mutiny.core.eventbus.EventBus;
+import jakarta.enterprise.context.Dependent;
+import jakarta.inject.Inject;
+
+//@ApplicationScoped
+@Dependent
+public class ScanTask {
+
+
+ @Inject
+ EventBus bus;
+ public ScanTaskState state;
+
+ public void setTektonRunId(String tektonRunId) {
+ this.tektonRunId = tektonRunId;
+ }
+
+ public String tektonRunId;
+
+ public ScanRequest scanRequest;
+
+
+ public ScanTask(ScanRequest scanRequest) {
+ this();
+ this.scanRequest = scanRequest;
+ this.bus = scanRequest.getBus();
+ }
+
+
+ public ScanTask(){
+ }
+
+
+ /*
+ public ScanTask(ScanRequest scanRequest)
+ {
+ this(
+ this.scanRequest = scanRequest;
+ }
+
+ */
+ public void execute(){
+ bus.publish("tekton", this);
+ }
+
+ public ScanTaskState getState() {
+ return state;
+ }
+
+ public void setState(ScanTaskState state) {
+ this.state = state;
+ }
+
+ public ScanRequest getScanRequest() {
+ return scanRequest;
+ }
+
+ public void setScanRequest(ScanRequest scanRequest) {
+ this.scanRequest = scanRequest;
+ }
+}
diff --git a/src/main/java/com/redhat/pctsec/model/ScanTaskState.java b/src/main/java/com/redhat/pctsec/model/ScanTaskState.java
new file mode 100644
index 0000000..6f4fa1a
--- /dev/null
+++ b/src/main/java/com/redhat/pctsec/model/ScanTaskState.java
@@ -0,0 +1,3 @@
+package com.redhat.pctsec.model;
+
+public enum ScanTaskState {AWAIT, TRIGGERED, RUNNING, SUCCESS, FAULURE}
diff --git a/src/main/java/com/redhat/pctsec/rest/v1alpha1/ScanResource.java b/src/main/java/com/redhat/pctsec/rest/v1alpha1/ScanResource.java
index 4889806..f160b18 100644
--- a/src/main/java/com/redhat/pctsec/rest/v1alpha1/ScanResource.java
+++ b/src/main/java/com/redhat/pctsec/rest/v1alpha1/ScanResource.java
@@ -1,11 +1,9 @@
package com.redhat.pctsec.rest.v1alpha1;
-import com.redhat.pctsec.model.Git;
-import com.redhat.pctsec.model.Scan;
-import com.redhat.pctsec.model.ScanRequest;
-import com.redhat.pctsec.model.ScanRequests;
+import com.redhat.pctsec.model.*;
import com.redhat.pctsec.model.api.request.pssaas;
import com.redhat.pctsec.model.jpa.ScanRepository;
+import io.vertx.mutiny.core.eventbus.EventBus;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.transaction.Transactional;
@@ -25,6 +23,9 @@ public class ScanResource {
@Inject
ScanRepository sr;
+ @Inject
+ EventBus bus;
+
@POST
@Path("PSSaaS")
@Consumes({ "application/json" })
@@ -55,8 +56,11 @@ public class ScanResource {
@GET
@Path("{id}/run")
- public String scanRequestExe(String id){
- return "We'd normally have a json payload here, with pipeline UID";
+ public List scanRequestExe(String id)
+ {
+ Scan s = sr.findById(UUID.fromString(id));
+ return s.scanRequests.execute(bus);
+ //return "We'd normally have a json payload here, with pipeline UID";
}
diff --git a/src/main/java/com/redhat/pctsec/tekton/TaskHandler.java b/src/main/java/com/redhat/pctsec/tekton/TaskHandler.java
new file mode 100644
index 0000000..b76dbe3
--- /dev/null
+++ b/src/main/java/com/redhat/pctsec/tekton/TaskHandler.java
@@ -0,0 +1,136 @@
+package com.redhat.pctsec.tekton;
+import com.redhat.pctsec.model.RequestType;
+import com.redhat.pctsec.model.ScanTask;
+import com.redhat.pctsec.model.ScanTaskState;
+import io.fabric8.kubernetes.api.model.ConfigMapVolumeSource;
+import io.fabric8.kubernetes.api.model.PersistentVolumeClaimVolumeSource;
+import io.fabric8.kubernetes.api.model.PodSecurityContext;
+import io.fabric8.kubernetes.api.model.PodSecurityContextBuilder;
+import io.fabric8.tekton.client.DefaultTektonClient;
+import io.fabric8.tekton.client.TektonClient;
+import io.fabric8.tekton.client.DefaultTektonClient;
+import io.fabric8.tekton.client.TektonClient;
+import io.fabric8.tekton.pipeline.v1beta1.*;
+
+import io.quarkus.vertx.ConsumeEvent;
+
+import jakarta.inject.Inject;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.eclipse.microprofile.config.inject.ConfigProperty;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class TaskHandler {
+
+ @ConfigProperty(name = "quarkus.openshift.namespace")
+ String NAMESPACE;
+ @ConfigProperty(name = "tekton.pipeline.ref")
+ String PIPELINE_REFERENCE;
+ @ConfigProperty(name = "tekton.service-account")
+ String SERVICE_ACCOUNT;
+
+ @ConfigProperty(name = "tekton.task.ref")
+ String TASK_REFERENCE;
+
+ @Inject TektonClient tektonClient;
+
+ @ConsumeEvent("tekton")
+ private ScanTask consume(ScanTask scanTask)
+ {
+
+ switch(scanTask.getScanRequest().getType())
+ {
+ case BREW:
+ scanTask.setTektonRunId(invokeScanTask(scanTask.getScanRequest().brewBuild.buildRef));
+ scanTask.setState(ScanTaskState.RUNNING);
+ break;
+
+ case PNC:
+ String repo = scanTask.getScanRequest().pncBuild.SCMURL().toString();
+ String ref = scanTask.getScanRequest().pncBuild.revision();
+ scanTask.setTektonRunId(invokeOshScmScanPipeline(repo, ref));
+ scanTask.setState(ScanTaskState.RUNNING);
+ break;
+
+ case GIT:
+ scanTask.setTektonRunId(invokeOshScmScanPipeline(scanTask.getScanRequest().git.repo.toString(), scanTask.getScanRequest().git.ref));
+ scanTask.setState(ScanTaskState.RUNNING);
+ break;
+ }
+
+ return scanTask;
+ }
+
+ public String invokeScanTask(String buildId) {
+ // String buildId = "xterm-366-8.el9";
+ String scanProfile = "snyk-only-unstable";
+
+ // random taskrun name generating for now
+ TaskRun taskRun = new TaskRunBuilder().withNewMetadata().withName("osh-scan-taskrun-" + RandomStringUtils.randomAlphanumeric(8).toLowerCase())
+ .endMetadata()
+ .withNewSpec()
+ .withServiceAccountName(SERVICE_ACCOUNT)
+ .withNewTaskRef()
+ .withName(TASK_REFERENCE)
+ .endTaskRef()
+ .withParams(
+ new Param("buildId", new ArrayOrString(buildId)),
+ new Param("scanProfile", new ArrayOrString(scanProfile)))
+ .endSpec()
+ .build();
+
+ tektonClient.v1beta1().taskRuns().inNamespace(NAMESPACE).resource(taskRun).create();
+
+ return taskRun.getMetadata().getName();
+ }
+
+ public String invokeOshScmScanPipeline(String repo, String ref) {
+
+ PodSecurityContext securityContext = new PodSecurityContextBuilder()
+ .withRunAsNonRoot(true)
+ .withRunAsUser(65532L)
+ .build();
+
+ WorkspaceBinding sourcesWorkspaceBinding = new WorkspaceBindingBuilder()
+ .withName("sources")
+ .withPersistentVolumeClaim(new PersistentVolumeClaimVolumeSource("osh-client-sources", null))
+ .build();
+
+ WorkspaceBinding sourceTarsWorkspaceBinding = new WorkspaceBindingBuilder()
+ .withName("source-tars")
+ .withPersistentVolumeClaim(new PersistentVolumeClaimVolumeSource("osh-client-source-tars", null))
+ .build();
+
+ WorkspaceBinding sslCaDirectoryWorkspaceBinding = new WorkspaceBindingBuilder()
+ .withName("ssl-ca-directory")
+ .withConfigMap(new ConfigMapVolumeSource(null, null, "config-trusted-cabundle", null))
+ .build();
+
+ List workspaceBindings = new ArrayList<>();
+ workspaceBindings.add(sourcesWorkspaceBinding);
+ workspaceBindings.add(sourceTarsWorkspaceBinding);
+ workspaceBindings.add(sslCaDirectoryWorkspaceBinding);
+
+ PipelineRun pipelineRun = new PipelineRunBuilder()
+ .withNewMetadata().withName("osh-scm-scan-" + RandomStringUtils.randomAlphanumeric(8).toLowerCase()).endMetadata()
+ .withNewSpec()
+ .withNewPodTemplate()
+ .withSecurityContext(securityContext)
+ .endPodTemplate()
+ .withServiceAccountName(SERVICE_ACCOUNT)
+ .withNewPipelineRef().withName(PIPELINE_REFERENCE).endPipelineRef()
+ .addNewParam().withName("repo-url").withNewValue(repo).endParam()
+ .addNewParam().withName("revision").withNewValue(ref).endParam()
+ .withWorkspaces(workspaceBindings)
+ .endSpec()
+ .build();
+
+ tektonClient.v1beta1().pipelineRuns().inNamespace(NAMESPACE).resource(pipelineRun).create();
+
+ return pipelineRun.getMetadata().getName();
+ }
+
+
+}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 1115fea..23de497 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -29,6 +29,8 @@
%dev.quarkus.hibernate-orm.database.generation=drop-and-create
#Always provide swagger ui
%dev.quarkus.swagger-ui.always-include=true
+%dev.quarkus.openshift.service-account=osh-wrapper-client-sa
+%dev.quarkus.openshift.namespace=pct-security-tooling
%stage.quarkus.openshift.name=osh
%stage.quarkus.openshift.service-account=osh-wrapper-client-sa
@@ -42,6 +44,7 @@ quarkus.arc.remove-unused-beans=false
%stage.quarkus.openshift.route.expose=false
%stage.quarkus.openshift.route.target-port=https
%stage.quarkus.openshift.route.tls.insecure-edge-termination-policy=redirect
+%stage.quarkus.openshift.namespace=pct-security-tooling
##########################################
# Kerberos Specifics #
@@ -58,5 +61,9 @@ quarkus.arc.remove-unused-beans=false
%stage.quarkus.openshift.config-map-volumes.osh-wrapper-config-vol.items."linux-krb5.conf".path=linux-krb5.conf
%stage.quarkus.openshift.mounts.osh-wrapper-config-vol.read-only=true
+tekton.pipeline.ref=osh-client-from-source
+tekton.task.ref=osh-scan-task
+tekton.service-account=${%stage.quarkus.openshift.service-account}
+