// Pipeline de construction des images Docker des services Zéphir def call() { pipeline { agent { label 'common' } parameters { string( name: 'targetUrl', description: 'URL cible pour l\'audit' ) string( name: 'basicAuthUsername', description: "Nom d'utilisateur pour l'authentication 'Basic Auth' (si besoin)", defaultValue: '' ) password( name: 'basicAuthPassword', description: "Mot de passe pour l'authentication 'Basic Auth' (si besoin)", defaultValue: '' ) string( name: 'basicAuthDomain', description: "Nom de domaine pour l'authentication 'Basic Auth' (si besoin)", defaultValue: '' ) string( name: 'authFormUrl', description: "URL du formulaire d'authentication (si besoin)", defaultValue: '' ) string( name: 'authFormUsername', description: "Nom d'utilisateur du formulaire d'authentication (si besoin)", defaultValue: '' ) password( name: 'authFormPassword', description: "Mot de passe du formulaire d'authentication (si besoin)", defaultValue: '' ) string( name: 'authFormCheckUrl', description: "URL de vérification de la réussite de l'authentication (si besoin)", defaultValue: '' ) string( name: 'authFormCheckString', description: "Chaine de caractères à rechercher pour vérifier la réussite de l'authentication (si besoin)", defaultValue: '' ) string( name: 'authFormUsernameField', description: "Nom du champ 'nom utilisateur' du formulaire d'authentication (si besoin)", defaultValue: '' ) string( name: 'authFormPasswordField', description: "Nom du champ 'mot de passe' du formulaire d'authentication (si besoin)", defaultValue: '' ) string( name: 'authFormDataFormat', description: "Patron de formatage des données POST du formulaire d'authentification (si besoin). Exemple: username=%U&password=%P", defaultValue: '' ) string( name: 'verbose', description: "Mode verbeux", defaultValue: 'False' ) string( name: 'auditTimeout', description: "Délai maximum pour la réalisation de l'audit (en minutes)", defaultValue: '60' ) } stages { stage("Check parameters") { steps { script { if (!params.targetUrl?.trim()) { error("L'URL cible n'est pas définie !") } } } } stage("Run W3AF audit") { steps { script { def w3afImage = buildDockerImage() def dockerArgs = """ -e W3AF_TARGET_URL='${params.targetUrl}' -e W3AF_BASIC_AUTH_USERNAME='${params.basicAuthUsername}' -e W3AF_BASIC_AUTH_PASSWORD='${params.basicAuthPassword}' -e W3AF_BASIC_AUTH_DOMAIN='${params.basicAuthDomain}' -e W3AF_AUTH_FORM_URL='${params.authFormUrl}' -e W3AF_AUTH_FORM_USERNAME='${params.authFormUsername}' -e W3AF_AUTH_FORM_PASSWORD='${params.authFormPassword}' -e W3AF_AUTH_FORM_DATA_FORMAT='${params.authFormDataFormat}' -e W3AF_AUTH_FORM_CHECK_URL='${params.authFormCheckUrl}' -e W3AF_AUTH_FORM_CHECK_STRING='${params.authFormCheckString}' -e W3AF_AUTH_FORM_USERNAME_FIELD='${params.authFormUsernameField}' -e W3AF_AUTH_FORM_PASSWORD_FIELD='${params.authFormPasswordField}' -e W3AF_VERBOSE='${params.verbose}' """ timeout(params.auditTimeout.toInteger()) { w3afImage.inside(dockerArgs) { sh 'mkdir -p reports' sh 'rm -f reports/*' sh 'envtpl -o audit.w3af /home/w3af/w3af/audit.w3af.tmpl' sh '/home/w3af/w3af/w3af_console -y -n -s audit.w3af' } } } } } stage("Check discovered vulnerabilities") { steps { script { def totalMediumVulnerabilities = sh( script: "grep 'MEDIUM' reports/report.html | wc -l", returnStdout: true ).toInteger() def totalHighVulnerabilities = sh( script: "grep 'HIGH' reports/report.html | wc -l", returnStdout: true ).toInteger() if (totalHighVulnerabilities == 0 && totalMediumVulnerabilities == 0) { return } wrap([$class: 'BuildUser']) { rocketSend ( avatar: 'https://jenkins.cadol.es/static/b5f67753/images/headshot.png', message: """ Des vulnérabilités ont été trouvées lors de l'audit de l'URL `${params.targetUrl}`: - Criticité HAUTE: ${totalHighVulnerabilities} vulnérabilité(s) trouvée(s) - Criticité MOYENNNE: ${totalMediumVulnerabilities} vulnérabilité(s) trouvée(s) [Voir le job](${env.RUN_DISPLAY_URL}) @${env.BUILD_USER_ID ? env.BUILD_USER_ID : 'here'} """.stripIndent(), rawMessage: true ) } } } } } post { always { publishHTML target: [ allowMissing: true, alwaysLinkToLastBuild: false, keepAll: true, reportDir: 'reports', reportFiles: 'report.html', reportName: "Rapport d'audit" ] } failure { wrap([$class: 'BuildUser']) { rocketSend ( avatar: 'https://jenkins.cadol.es/static/b5f67753/images/headshot.png', message: """ Le test de sécurité pour `${params.targetUrl}` a échoué: [Voir le job](${env.RUN_DISPLAY_URL}) @${env.BUILD_USER_ID ? env.BUILD_USER_ID : 'here'} """.stripIndent(), rawMessage: true ) } } } } } def buildDockerImage() { dir ('.w3af') { def resourceFiles = [ 'com/cadoles/w3af/audit.w3af.tmpl', 'com/cadoles/w3af/Dockerfile', 'com/cadoles/w3af/run-audit.sh' ]; for (res in resourceFiles) { def fileContent = libraryResource res def fileName = res.substring(res.lastIndexOf("/")+1) writeFile file:fileName, text:fileContent } def safeJobName = URLDecoder.decode(env.JOB_NAME).toLowerCase().replace('/', '-').replace(' ', '-') def imageTag = "${safeJobName}-${env.BUILD_ID}" return docker.build("w3af:${imageTag}", ".") } }