188 lines
8.1 KiB
Groovy
188 lines
8.1 KiB
Groovy
pipeline {
|
|
agent {
|
|
kubernetes {
|
|
// Definieren des Pod mit 3 Containern als Build Agent, Trivy und Kaniko
|
|
yaml '''
|
|
apiVersion: v1
|
|
kind: Pod
|
|
spec:
|
|
containers:
|
|
- name: dotnet8
|
|
image: mcr.microsoft.com/dotnet/sdk:8.0
|
|
command:
|
|
- cat
|
|
tty: true
|
|
- name: trivy
|
|
image: aquasec/trivy:latest
|
|
command:
|
|
- cat
|
|
tty: true
|
|
- name: kaniko
|
|
image: gcr.io/kaniko-project/executor:v1.23.1-debug
|
|
command: ["sleep"]
|
|
args: ["99d"]
|
|
'''
|
|
}
|
|
}
|
|
|
|
options {
|
|
// Aktivieren von Log Rotation:
|
|
// *) Letzten 10 Builds werden aufbewahrt
|
|
// ** Builds, die älter als 7 Tage sind, werden gelöscht
|
|
buildDiscarder(logRotator(numToKeepStr: '10', artifactNumToKeepStr: '10', daysToKeepStr: '7'))
|
|
}
|
|
|
|
stages {
|
|
// Auschecken der Sourcen zum App Projekt
|
|
stage('Checkout Source') {
|
|
steps {
|
|
git url: 'https://gitea.dagobert84.duckdns.org/dev-master/secdevops-csharp-app.git',
|
|
branch: 'master'
|
|
}
|
|
}
|
|
|
|
stage('Security: Trivy Scan') {
|
|
steps {
|
|
// Ausführen des 'dotnet restore' für den nachfolgenden Trivy Scan, der diese wiederhergestellte Dateien/NuGet Pakete und Abhängigkeiten scanned
|
|
// Generiert automatisch das obj/ mit der project.assets.json
|
|
// Alle Container eines Pods teilen sich das Jenkins Arbeitsverzeichnis
|
|
container('dotnet8') {
|
|
sh 'dotnet restore'
|
|
}
|
|
|
|
// Ausführen des Trivy Scans
|
|
//
|
|
// Wichtig: trivy ersetzt -> dotnet list package --vulnerable --include-transitive
|
|
container('trivy') {
|
|
// Erzeugen des Directory zum Speichern des Reports
|
|
sh 'mkdir -p reports'
|
|
|
|
// Ausführen des Scans hinsichtlich Vulnerabilities, Miskonfigurationen, Secrets und Licences im Jenkins Arbeitsverzeichnis
|
|
// Abbruch bei bei kritischen Fehlern (--exit-code 1 --severity HIGH,CRITICAL)
|
|
sh 'trivy fs --scanners vuln,misconfig,secret,license --exit-code 1 --severity HIGH,CRITICAL --format template --template "@/contrib/html.tpl" -o reports/trivy-fs-report.html .'
|
|
}
|
|
}
|
|
}
|
|
|
|
// Kompilieren der Anwendung (DLLs werden erzeugt)
|
|
// Schritt muss gar nicht durchgeführt werden, da kaniko das Image erzeugt
|
|
stage('Build with .NET 8') {
|
|
steps {
|
|
// Führt den Build-Befehl im spezialisierten Container aus
|
|
container('dotnet8') {
|
|
sh 'dotnet --version' // Zur Bestätigung der Version
|
|
|
|
sh 'dotnet build --configuration Release' // optimierter Build Prozess ohne Debug und ungenutzt Pfade
|
|
}
|
|
}
|
|
}
|
|
|
|
//stage('Unit Tests') {
|
|
// steps {
|
|
// container('dotnet8') {
|
|
// Erstellt eine XML-Datei im Format 'junit', die Jenkins lesen kann
|
|
// sh 'dotnet test --configuration Release'
|
|
// sh 'dotnet test --configuration Release --logger "junit;LogFileName=results.xml"'
|
|
// }
|
|
//}
|
|
//}
|
|
|
|
stage('Set Build Name') {
|
|
steps {
|
|
script {
|
|
// Setzen des Namen des aktuellen Laufs auf die Version + Build-Nummer
|
|
currentBuild.displayName = "v1.0.0-build-${env.BUILD_NUMBER}"
|
|
}
|
|
}
|
|
}
|
|
|
|
stage('Docker Build & Push') {
|
|
when {
|
|
branch 'master'
|
|
}
|
|
|
|
steps {
|
|
container('kaniko') {
|
|
// Stellt die Informationen aus dem Token in Form von Umgebungsvariablen der Jenkins Pipeline zur Verfügung
|
|
// Nachfolgend werden diese Credentials im JSON Format in config.json geschrieben
|
|
// Vorgehen ist zwar nicht extrem sicher, aber die Lebenszeit im Container ist kurz, dass diese base64 kodierten Daten zurückverwandelt werden könnten
|
|
|
|
// Erzeugen des Directory zum Speichern des Reports, falls das bei einem vorigen Schritt nicht durchgeführt wurde
|
|
sh 'mkdir -p reports'
|
|
|
|
withCredentials([usernamePassword(credentialsId: 'gitea-registry-token',
|
|
usernameVariable: 'GITEA_USER',
|
|
passwordVariable: 'GITEA_TOKEN')]) {
|
|
sh '''
|
|
# WORKAROUND: Dem Container beibringen, wer git.example.com ist, ansonsten funktioniert das Übertragen des Images an Git nicht!!!
|
|
#echo "130.61.26.230 git.example.com" >> /etc/hosts
|
|
|
|
# Erstellt die Docker-Konfiguration für Kaniko
|
|
# Das $(echo ...) Kommando kombiniert User und Token für den Login
|
|
echo "{\\"auths\\":{\\"https://gitea.dagobert84.duckdns.org\\":{\\"auth\\":\\"\$(echo -n \${GITEA_USER}:\${GITEA_TOKEN} | base64)\\"}}}" > /kaniko/.docker/config.json
|
|
|
|
# Der Bau- und Push-Befehl
|
|
# Wir taggen das Image mit 'latest' UND der Build-Nummer zur Sicherheit
|
|
/kaniko/executor --context `pwd` \
|
|
--dockerfile `pwd`/Dockerfile \
|
|
--insecure \
|
|
--build-arg JENKINS_BUILD=${BUILD_NUMBER} \
|
|
--destination https://gitea.dagobert84.duckdns.org/dev-master/secdevops-csharp-app:latest \
|
|
--destination https://gitea.dagobert84.duckdns.org/dev-master/secdevops-csharp-app:${BUILD_NUMBER}
|
|
'''
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
stage('Security: Trivy Image Scan') {
|
|
when {
|
|
branch 'master'
|
|
}
|
|
steps {
|
|
|
|
// Trivy Scan wird auf das Image im Git Repository angewendet. Das Image wird heruntergeladen.
|
|
container('trivy') {
|
|
// 1. Scan ausführen und als HTML-Report speichern (Achte auf den neuen Dateinamen)
|
|
sh '''
|
|
trivy image --insecure \
|
|
--severity HIGH,CRITICAL \
|
|
--format template \
|
|
--template "@/contrib/html.tpl" \
|
|
--exit-code 1 \
|
|
-o reports/trivy-image-report.html \
|
|
https://gitea.dagobert84.duckdns.org/dev-master/secdevops-csharp-app:latest
|
|
'''
|
|
|
|
// Den Scan ein zweites Mal kurz ohne Report ausführen, damit die Pipeline bei Lücken blockiert
|
|
// sh 'trivy image --insecure --exit-code 1 --severity HIGH,CRITICAL 130.61.26.230:30080/dev-master/secdevops-csharp-app:latest'
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
post {
|
|
failure {
|
|
script {
|
|
currentBuild.description = "Build Fehler. Ev. Sicherheits-Check fehlgeschlagen! Details im Trivy Security Report."
|
|
}
|
|
}
|
|
always {
|
|
// Suchen und Einelen von etwaigen Testreports von JUnit. Keine Vorhanden? -auch ok
|
|
junit testResults: '**/*.xml', allowEmptyResults: true
|
|
|
|
// Verwenden des HTML Publisher Modules zum Schreiben der gefundenen Testreports in das Build Menu und speichert den HTML Bericht dann historisch ab (keepAll)
|
|
publishHTML([
|
|
allowMissing: false,
|
|
alwaysLinkToLastBuild: true,
|
|
keepAll: true,
|
|
reportDir: 'reports',
|
|
reportFiles: 'trivy-fs-report.html,trivy-image-report.html',
|
|
reportName: 'Trivy Security Report'
|
|
])
|
|
|
|
// Schreiben des Build Status in das Build Log
|
|
echo "Pipeline beendet: ${currentBuild.result}"
|
|
}
|
|
}
|
|
} |