diff --git a/Dockerfile b/Dockerfile
index 8d376e8e..148a239d 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,12 +1,17 @@
-FROM maven:3.6-jdk-8
-
+FROM maven:3.8.4-openjdk-17 AS build
WORKDIR /app
+COPY . .
+RUN mvn package -DskipTests
-COPY . .
-
-RUN mvn package -DskipTests && \
- mv target/demo-0.0.1-SNAPSHOT.jar /run/demo.jar
-
+FROM openjdk:18-alpine AS run
+WORKDIR /run
+COPY --from=build /app/target/demo-0.0.1-SNAPSHOT.jar demo.jar
+ARG USER=devops
+ENV HOME /home/$USER
+RUN adduser -D $USER && chown $USER:$USER /run/demo.jar
+RUN apk add --no-cache curl
+HEALTHCHECK --interval=30s --timeout=10s --retries=2 --start-period=20s \
+ CMD curl -f http://localhost:8080/ || exit 1
+USER $USER
EXPOSE 8080
-
-CMD java -jar /run/demo.jar
+CMD java -jar /run/demo.jar
diff --git a/Jenkinsfile b/Jenkinsfile
index 2fc1e0d2..b138f7a4 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -1,4 +1,7 @@
pipeline {
+ environment {
+ ARGO_SERVER = '104.197.60.253:32100'
+ }
agent {
kubernetes {
yamlFile 'build-agent.yaml'
@@ -18,7 +21,7 @@ pipeline {
}
}
}
- stage('Test') {
+ stage('Static Analysis') {
parallel {
stage('Unit Tests') {
steps {
@@ -27,6 +30,60 @@ pipeline {
}
}
}
+ stage('SCA') {
+ steps {
+ container('maven') {
+ catchError(buildResult: 'SUCCESS', stageResult:'FAILURE') {
+ sh 'mvn org.owasp:dependency-check-maven:check'
+ }
+ }
+ }
+ post {
+ always {
+ archiveArtifacts allowEmptyArchive: true,artifacts: 'target/dependency-check-report.html', fingerprint:true, onlyIfSuccessful: true
+ // dependencyCheckPublisher pattern: 'report.xml'
+ }
+ }
+ }
+ stage('OSS License Checker') {
+ steps {
+ container('licensefinder') {
+ sh 'ls -al'
+ sh '''#!/bin/bash --login
+ /bin/bash --login
+ rvm use default
+ gem install license_finder
+ license_finder
+ '''
+ }
+ }
+ }
+ stage('Generate SBOM') {
+ steps {
+ container('maven') {
+ sh 'mvn org.cyclonedx:cyclonedx-maven-plugin:makeAggregateBom'
+ }
+ }
+ post {
+ success {
+ //dependencyTrackPublisher projectName:'sample-spring-app', projectVersion: '0.0.1', artifact:'target/bom.xml', autoCreateProjects: true, synchronous: true
+ archiveArtifacts allowEmptyArchive: true,artifacts: 'target/bom.xml', fingerprint: true,onlyIfSuccessful: true
+ }
+ }
+ }
+ }
+ }
+ stage('SAST') {
+ steps {
+ container('slscan') {
+ sh 'scan --type java,depscan --build'
+ }
+ }
+ post {
+ success {
+ archiveArtifacts allowEmptyArchive: true,
+ artifacts: 'reports/*', fingerprint: true, onlyIfSuccessful:true
+ }
}
}
stage('Package') {
@@ -38,13 +95,44 @@ pipeline {
}
}
}
+ stage('Build with Kaniko') {
+ steps {
+ container('kaniko') {
+ sh '/kaniko/executor -f `pwd`/Dockerfile -c `pwd` --insecure --skip-tls-verify --cache=true --destination=docker.io/vinycoolguy/dsodemo'
+ }
}
}
+ }
+ }
+
+ stage('Image Analysis') {
+ parallel {
+ stage('Image Linting') {
+ steps {
+ container('docker-tools') {
+ sh 'dockle docker.io/vinycoolguy/dsodemo'
+ }
+ }
+ }
+ stage('Image Scan') {
+ steps {
+ container('docker-tools') {
+ sh 'trivy image vinycoolguy/dsodemo'
+ }
+ }
+ }
+ }
+ }
stage('Deploy to Dev') {
+ environment {
+ AUTH_TOKEN = credentials('argocd-jenkins-deployer-token')
+ }
steps {
- // TODO
- sh "echo done"
+ container('docker-tools') {
+ sh 'docker run -t schoolofdevops/argocd-cli argocd app sync dso-demo --insecure --server $ARGO_SERVER --auth-token $AUTH_TOKEN'
+ sh 'docker run -t schoolofdevops/argocd-cli argocd app wait dso-demo --health --timeout 300 --insecure --server $ARGO_SERVER --auth-token $AUTH_TOKEN'
+ }
}
}
}
diff --git a/build-agent.yaml b/build-agent.yaml
index c9efebe3..88014de2 100644
--- a/build-agent.yaml
+++ b/build-agent.yaml
@@ -23,6 +23,22 @@ spec:
name: docker-sock
- mountPath: /tmp/trivycache/
name: trivycache
+ - name: slscan
+ image: shiftleft/sast-scan
+ imagePullPolicy: Always
+ command:
+ - cat
+ tty: true
+ - name: kaniko
+ image: gcr.io/kaniko-project/executor:v1.6.0-debug
+ imagePullPolicy: Always
+ command:
+ - sleep
+ args:
+ - 99d
+ volumeMounts:
+ - name: jenkins-docker-cfg
+ mountPath: /kaniko/.docker
- name: trufflehog
image: rmkanda/trufflehog
command:
@@ -43,3 +59,11 @@ spec:
- name: trivycache
hostPath:
path: /tmp/trivycache/
+ - name: jenkins-docker-cfg
+ projected:
+ sources:
+ - secret:
+ name: regcred
+ items:
+ - key: .dockerconfigjson
+ path: config.json
diff --git a/deploy/dso-demo-deploy.yaml b/deploy/dso-demo-deploy.yaml
new file mode 100644
index 00000000..76161e8b
--- /dev/null
+++ b/deploy/dso-demo-deploy.yaml
@@ -0,0 +1,26 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ creationTimestamp: null
+ labels:
+ app: dso-demo
+ name: dso-demo
+spec:
+ replicas: 1
+ selector:
+ matchLabels:
+ app: dso-demo
+ strategy: {}
+ template:
+ metadata:
+ creationTimestamp: null
+ labels:
+ app: dso-demo
+ spec:
+ containers:
+ - image: vinycoolguy/dsodemo
+ name: dsodemo
+ ports:
+ - containerPort: 8080
+ resources: {}
+status: {}
diff --git a/deploy/dso-demo-svc.yaml b/deploy/dso-demo-svc.yaml
new file mode 100644
index 00000000..8931ce9f
--- /dev/null
+++ b/deploy/dso-demo-svc.yaml
@@ -0,0 +1,19 @@
+apiVersion: v1
+kind: Service
+metadata:
+ creationTimestamp: null
+ labels:
+ app: dso-demo
+ name: dso-demo
+spec:
+ ports:
+ - name: "8080"
+ nodePort: 30080
+ port: 8080
+ protocol: TCP
+ targetPort: 8080
+ selector:
+ app: dso-demo
+ type: NodePort
+status:
+ loadBalancer: {}
diff --git a/doc/dependency_decisions.yml b/doc/dependency_decisions.yml
index cad03c45..e91d2688 100644
--- a/doc/dependency_decisions.yml
+++ b/doc/dependency_decisions.yml
@@ -40,14 +40,14 @@
- :who:
:why:
:versions:
- - 1.2.3
+ - 1.2.6
:when: 2020-05-31 15:28:30.302764000 Z
- - :approve
- logback-classic
- :who:
:why:
:versions:
- - 1.2.3
+ - 1.2.6
:when: 2020-05-31 15:29:03.621478000 Z
- - :approve
- jakarta.xml.bind-api
@@ -70,3 +70,9 @@
:versions:
- 1.3.5
:when: 2020-05-31 15:29:53.045616000 Z
+- - :permit
+ - New BSD
+ - :who:
+ :why:
+ :versions: []
+ :when: 2020-09-29
diff --git a/pom.xml b/pom.xml
index 9c2e8aad..4aec8086 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
org.springframework.boot
spring-boot-starter-parent
- 2.4.3
+ 2.5.5
com.demo
@@ -16,6 +16,7 @@
1.8
+ 2.17.0
@@ -47,6 +48,9 @@
org.owasp
dependency-check-maven
6.1.1
+
+ 8
+
diff --git a/src/main/java/com/demo/demo/DemoApplication.java b/src/main/java/com/demo/demo/DemoApplication.java
index b4943e0c..95b8bf7f 100644
--- a/src/main/java/com/demo/demo/DemoApplication.java
+++ b/src/main/java/com/demo/demo/DemoApplication.java
@@ -11,7 +11,7 @@ public class DemoApplication {
@GetMapping("/")
public String available() {
- return "DevSecOps Demo
";
+ return "DevSecOps Demo Updated
";
}
public static void main(String[] args) {