Jenkins CI との統合 
このガイドでは、プッシュのたびに Mayhem が自動的に API をテストできるよう Jenkins Pipeline をセットアップする方法を説明します。
Jenkins と Mayhem を連携するためのパイプライン構成 
コードまたは API をテストして JUnit レポートとして結果を収集するよう Jenkinsスクリプト パイプライン  を構成するには、Jenkinsfile を作成します。
コード テスト 
 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
36 
37 
38 
39 
40 
41 
42 
43 
44 
45 
46 
47 
48 
49 
50 
51 
52 
53 
54 
55 
56 
57 
58 
59 
60 
61 
62 
63 
64 
65 
66 
67 
68 
69 
70 
71 
72 
73 
74 
75 
76 
77 
78 
79 
80 
81 
82 
83 
84 
85 
86 
87 
88 
89 
90 pipeline   { 
     agent   any 
     stages   { 
         stage ( 'Setup' )   { 
             steps   { 
                 echo   'Setting up..' 
                 withCredentials ([ usernamePassword ( credentialsId:   'MAYHEM_CREDENTIALS' ,   usernameVariable:   'MAYHEM_USERNAME' ,   passwordVariable:   'MAYHEM_TOKEN' )])   { 
                     sh   """ 
                      # Setup aarch64 (preinstalled) and x86_64 (download to install) 
                      mkdir -p ~/bin 
                      export PATH=\${PATH}:~/bin 
                      curl -Lo ~/bin/mayhem-x86_64 ${MAYHEM_URL}/cli/Linux/mayhem  && chmod +x ~/bin/mayhem-x86_64 
                      # Login to mayhem and docker 
                      mayhem-\$(arch) login --url ${MAYHEM_URL} --token ${MAYHEM_TOKEN} 
                      REGISTRY=\$(mayhem-\$(arch) docker-registry) 
                      echo "${MAYHEM_TOKEN}" | docker login -u ${MAYHEM_USERNAME} --password-stdin \${REGISTRY} 
                    """ 
                 } 
             } 
         } 
         stage ( 'Build' )   { 
             steps   { 
                 echo   'Building..' 
                 sh   """ 
                    echo "Compiling the code..." 
                    export PATH=\${PATH}:~/bin 
                    REGISTRY=\$(mayhem-\$(arch) docker-registry) 
                    docker build --platform=linux/amd64 -t \${REGISTRY}/lighttpd:${env.BRANCH_NAME} . 
                    docker push \${REGISTRY}/lighttpd:${env.BRANCH_NAME} 
                    echo "Compile complete." 
                  """ 
             } 
         } 
         stage ( 'Mayhem for Code' )   { 
             matrix   { 
                 agent   any 
                 axes   { 
                     axis   { 
                         name   'TARGET' 
                         values   'lighttpd' ,   'mayhemit' 
                     } 
                 } 
                 stages   { 
                     stage ( 'Mayhem for Code' )   { 
                         steps   { 
                             echo   'Scanning..' 
                             sh   """#!/bin/bash 
                                  export PATH=\${PATH}:~/bin 
                                  REGISTRY=\$(mayhem-\$(arch) docker-registry) 
                                  # Run Mayhem 
                                  echo "mayhem-\$(arch) --verbosity info run . --project forallsecure/mcode-action-examples --owner forallsecure --image \${REGISTRY}/lighttpd:${env.BRANCH_NAME} --file mayhem/Mayhemfile.${TARGET} --duration 60 --branch-name ${env.BRANCH_NAME} --revision ${env.GIT_COMMIT} 2>/dev/null" 
                                  run=\$(mayhem-\$(arch) --verbosity info run . --project forallsecure/mcode-action-examples --owner forallsecure --image \${REGISTRY}/lighttpd:${env.BRANCH_NAME} --file mayhem/Mayhemfile.${TARGET} --duration 60 --branch-name ${env.BRANCH_NAME} --revision ${env.GIT_COMMIT} 2>/dev/null); 
                                  # Fail if no output was given 
                                  if [ -z "\${run}" ]; then exit 1; fi 
                                  # Determine run name 
                                  runName=\$(echo \${run} | awk -F / '{ print \$(NF-1) }'); 
                                  # Wait for job to complete and artifacts to be ready 
                                  mayhem-\$(arch) --verbosity info wait \${run} --owner forallsecure --sarif sarif-\${runName}.sarif --junit junit-\${runName}.xml; 
                                  status=\$(mayhem-\$(arch) --verbosity info show --owner forallsecure --format json \${run} | jq '.[0].status') 
                                  if [[ \${status} == *"stopped"* || \${status} == *"failed"* ]]; then exit 2; fi 
                                  defects=\$(mayhem-\$(arch) --verbosity info show --owner forallsecure --format json \${run} | jq '.[0].defects|tonumber') 
                                  if [[ \${defects} -gt 0 ]]; then echo "\${defects} defects found!"; exit 3; fi 
                              """ 
                         } 
                     } 
                 } 
                 post   { 
                     always   { 
                         echo   'Archive....' 
                         archiveArtifacts   artifacts:   'junit-*.xml, sarif-*.sarif' , 
                           allowEmptyArchive:   true , 
                           fingerprint:   true , 
                           onlyIfSuccessful:   false 
                         junit   'junit-*.xml' 
                         recordIssues ( 
                             enabledForFailure:   true , 
                             tool:   sarif ( id:   "sarif-${TARGET}" ,   pattern:   'sarif-*.sarif' ) 
                         ) 
                     } 
                 } 
             } 
         } 
     } 
} 
 
API テスト 
 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
36 
37 
38 
39 
40 
41 
42 
43 
44 
45 
46 // Run the build on a node with the 'docker' label 
node ( "docker" )   { 
   checkout   scm 
   // MAPI_TOKEN - The API Token secret text added to Credentials 
   withCredentials ([ 
       string ( credentialsId:   "${MAPI_TOKEN}" ,   variable:   "MAPI_TOKEN" ) 
       ])   { 
     // 
     // 1. BUILD AND TEST YOUR API HERE 
     // 
     stage ( "Run Mayhem" )   { 
         // 
         // 2. Start your API 
         //    eg. http://localhost:8080/api 
         // 
         // 
         // 3. Download the CLI (or use Jenkins Tools 
         // see: https://github.com/jenkinsci/custom-tools-plugin/blob/master/README.md) 
         // Replace $(MAYHEM_URL) with your instance's URL, e.g., https://app.mayhem.security 
         // 
         sh   ''' 
        curl -Lo mapi $(MAYHEM_URL)/cli/mapi/linux-musl/latest/mapi \ 
          && chmod +x mapi 
        ''' 
         // 
         // 4. Check your API 
         // 
         sh   ''' 
          mapi run my-api auto <path_to_openapi_spec> \ 
            --url 'http://localhost:8080/api' \ 
            --junit results.xml 
        ''' 
         // 
         // 5.  Collect junit results 
         // 
         junit   testResults:   'results.xml' 
     } 
   } 
} 
 
Mayhem と Jenkins の統合 
Mayhem と Jenkins を適切に統合するのに必要な Jenkinsfile について説明したので、次は、動作するサンプルを確認します。
Jenkins で構成を動作させるには、Jenkins で次の認証情報を設定する必要があります。このサンプルでは、次のパイプライン変数が設定されています。
MAYHEM_CREDENTIALS: ユーザー名とパスワードを受け取ります。ユーザー名は Mayhem ユーザーであり、パスワードは Mayhem API トークンです。MAYHEM_URL: Mayhem サーバーの URL です。https://app.mayhem.security を設定します。 
さらに、上記の Jenkinsfile 構成では、Docker イメージをビルドして GitHub Container Registry にプッシュします。そのため、プロジェクトの可視性が Public に設定されていることを確認し、Mayhem が GitHub Container Registry からリポジトリの Docker イメージをプルできるようにします。
上記の手順を完了すると、Jenkins パイプラインを実行できるようになります。パイプラインはターゲットに対して Mayhem ランを実行し、脆弱性をテストします。