diff --git a/templates/CVE_Scan.gitlab-ci.yml b/templates/CVE_Scan.gitlab-ci.yml index c9f3c24..f011b68 100644 --- a/templates/CVE_Scan.gitlab-ci.yml +++ b/templates/CVE_Scan.gitlab-ci.yml @@ -35,8 +35,11 @@ echo echo "=======================================================" echo - # Login to registries + # Preparing DOCKER_CONFIG and login to registries - | + echo "Preparing DOCKER_CONFIG and login to registries" + mkdir -p "${workdir}/docker" + export DOCKER_CONFIG="${workdir}/docker" echo ${PROD_REGISTRY_PASSWORD} | docker login --username="${PROD_REGISTRY_USER}" --password-stdin ${PROD_REGISTRY} echo ${DEV_REGISTRY_PASSWORD} | docker login --username="${DEV_REGISTRY_USER}" --password-stdin ${DEV_REGISTRY} echo @@ -94,6 +97,47 @@ fi echo "CVE Scan will be applied to the following tags of ${MODULE_NAME} module:" echo "${module_tags[@]}" + + # Functions + trivy_scan() { + ${workdir}/bin/trivy i --policy "${TRIVY_POLICY_URL}" --cache-dir "${workdir}/bin/trivy_cache" --skip-db-update --skip-java-db-update --exit-code 0 --severity "${severity}" --ignorefile "${module_workdir}/.trivyignore" --format ${1} ${2} ${3} --quiet ${4} --username "${trivy_registry_user}" --password "${trivy_registry_pass}" --image-src remote + } + send_report() { + echo "" + echo " Uploading trivy ${1} report for image \"${IMAGE_NAME}\" of \"${MODULE_NAME}\" module" + echo "" + curl -s -S -o /dev/null --fail-with-body -X POST \ + --retry 5 \ + --retry-delay 10 \ + --retry-all-errors \ + ${DD_URL}/api/v2/reimport-scan/ \ + -H "accept: application/json" \ + -H "Authorization: Token ${DD_TOKEN}" \ + -F "auto_create_context=True" \ + -F "minimum_severity=Info" \ + -F "active=true" \ + -F "verified=true" \ + -F "scan_type=Trivy Scan" \ + -F "close_old_findings=true" \ + -F "do_not_reactivate=false" \ + -F "push_to_jira=false" \ + -F "file=@${2}" \ + -F "product_type_name=External Modules" \ + -F "product_name=$MODULE_NAME" \ + -F "scan_date=${date_iso}" \ + -F "engagement_name=${1}" \ + -F "service=${MODULE_NAME} / ${IMAGE_NAME}" \ + -F "group_by=component_name+component_version" \ + -F "deduplication_on_engagement=false" \ + -F "tags=external_module,module:${MODULE_NAME},image:${IMAGE_NAME},branch:${module_tag},${dd_short_release_tag},${dd_full_release_tag},${dd_default_branch_tag}" \ + -F "test_title=[${MODULE_NAME}]: ${IMAGE_NAME}:${module_tag}" \ + -F "version=${dd_image_version}" \ + -F "build_id=${IMAGE_HASH}" \ + -F "commit_hash=${CI_COMMIT_SHA}" \ + -F "branch_tag=${module_tag}" \ + -F "apply_tags_to_findings=true" + } + # Scan in loop for provided list of tags for module_tag in ${module_tags[@]}; do dd_default_branch_tag="" @@ -151,50 +195,31 @@ if [ "${additional_image_detected}" == true ]; then if [ "${TRIVY_REPORTS_LOG_OUTPUT}" != "false" ]; then - ${workdir}/bin/trivy i --policy "${TRIVY_POLICY_URL}" --cache-dir "${workdir}/bin/trivy_cache" --skip-db-update --skip-java-db-update --exit-code 0 --severity ${severity} --ignorefile "${module_workdir}/.trivyignore" --format table --scanners vuln --quiet "${module_image}:${module_tag}" --username "${trivy_registry_user}" --password "${trivy_registry_pass}" --image-src remote + # CVE Scan + trivy_scan "table" "--scanners vuln" "" "${module_image}:${module_tag}" + # License scan + trivy_scan "table" "--scanners license --license-full" "" "${module_image}:${module_tag}" fi - ${workdir}/bin/trivy i --policy "${TRIVY_POLICY_URL}" --cache-dir "${workdir}/bin/trivy_cache" --skip-db-update --skip-java-db-update --exit-code 0 --severity $severity --ignorefile "${module_workdir}/.trivyignore" --format json --scanners vuln --output "${module_reports}/d8_${MODULE_NAME}_${IMAGE_NAME}_report.json" --quiet "${module_image}:${module_tag}" --username "${trivy_registry_user}" --password "${trivy_registry_pass}" --image-src remote + # CVE Scan + trivy_scan "json" "--scanners vuln" "--output ${module_reports}/ext_${MODULE_NAME}_${IMAGE_NAME}_report.json" "${module_image}:${module_tag}" + # License scan + trivy_scan "json" "--scanners license --license-full" "--output ${module_reports}/ext_${MODULE_NAME}_${IMAGE_NAME}_report_license.json" "${module_image}:${module_tag}" else if [ "${TRIVY_REPORTS_LOG_OUTPUT}" != "false" ]; then - ${workdir}/bin/trivy i --policy "${TRIVY_POLICY_URL}" --cache-dir "${workdir}/bin/trivy_cache" --skip-db-update --skip-java-db-update --exit-code 0 --severity ${severity} --ignorefile "${module_workdir}/.trivyignore" --format table --scanners vuln --quiet "${module_image}@${IMAGE_HASH}" --username "${trivy_registry_user}" --password "${trivy_registry_pass}" --image-src remote + # CVE Scan + trivy_scan "table" "--scanners vuln" "" "${module_image}@${IMAGE_HASH}" + # License scan + trivy_scan "table" "--scanners license --license-full" "" "${module_image}@${IMAGE_HASH}" fi - ${workdir}/bin/trivy i --policy "${TRIVY_POLICY_URL}" --cache-dir "${workdir}/bin/trivy_cache" --skip-db-update --skip-java-db-update --exit-code 0 --severity ${severity} --ignorefile "${module_workdir}/.trivyignore" --format json --scanners vuln --output "${module_reports}/d8_${MODULE_NAME}_${IMAGE_NAME}_report.json" --quiet "${module_image}@${IMAGE_HASH}" --username "${trivy_registry_user}" --password "${trivy_registry_pass}" --image-src remote + # CVE Scan + trivy_scan "json" "--scanners vuln" "--output ${module_reports}/ext_${MODULE_NAME}_${IMAGE_NAME}_report.json" "${module_image}@${IMAGE_HASH}" + # License scan + trivy_scan "json" "--scanners license --license-full" "--output ${module_reports}/ext_${MODULE_NAME}_${IMAGE_NAME}_report_license.json" "${module_image}@${IMAGE_HASH}" fi echo " Done" - echo "" - echo " Uploading trivy CVE report for image ${IMAGE_NAME} of ${MODULE_NAME} module" - echo "" - curl -s -S -o /dev/null --fail-with-body -X POST \ - --retry 5 \ - --retry-delay 10 \ - --retry-all-errors \ - ${DD_URL}/api/v2/reimport-scan/ \ - -H "accept: application/json" \ - -H "Content-Type: multipart/form-data" \ - -H "Authorization: Token ${DD_TOKEN}" \ - -F "auto_create_context=True" \ - -F "minimum_severity=Info" \ - -F "active=true" \ - -F "verified=true" \ - -F "scan_type=Trivy Scan" \ - -F "close_old_findings=true" \ - -F "do_not_reactivate=false" \ - -F "push_to_jira=false" \ - -F "file=@${module_reports}/d8_${MODULE_NAME}_${IMAGE_NAME}_report.json" \ - -F "product_type_name=Deckhouse images" \ - -F "product_name=$MODULE_NAME" \ - -F "scan_date=${date_iso}" \ - -F "engagement_name=CVE Test: ${MODULE_NAME} Images" \ - -F "service=${MODULE_NAME} / ${IMAGE_NAME}" \ - -F "group_by=component_name+component_version" \ - -F "deduplication_on_engagement=false" \ - -F "tags=deckhouse_image,module:${MODULE_NAME},image:${IMAGE_NAME},branch:${module_tag},${dd_short_release_tag},${dd_full_release_tag},${dd_default_branch_tag}" \ - -F "test_title=[${MODULE_NAME}]: ${IMAGE_NAME}:${module_tag}" \ - -F "version=${dd_image_version}" \ - -F "build_id=${IMAGE_HASH}" \ - -F "commit_hash=${CI_COMMIT_SHA}" \ - -F "branch_tag=${module_tag}" \ - -F "apply_tags_to_findings=true" + + send_report "CVE" "${module_reports}/ext_${MODULE_NAME}_${IMAGE_NAME}_report.json" + send_report "License" "${module_reports}/ext_${MODULE_NAME}_${IMAGE_NAME}_report_license.json" done < <(jq -rc 'to_entries[]' <<< "${digests}") done rm -rf ${workdir} diff --git a/templates/Setup.gitlab-ci.yml b/templates/Setup.gitlab-ci.yml index 765277b..fe1bb09 100644 --- a/templates/Setup.gitlab-ci.yml +++ b/templates/Setup.gitlab-ci.yml @@ -5,34 +5,58 @@ # $DEV_MODULES_REGISTRY - dev registry path # $DEV_MODULES_REGISTRY_LOGIN - login to dev registry # $DEV_MODULES_REGISTRY_PASSWORD - password to dev registry +# $PROD_MODULES_REGISTRY - prod registry path +# $PROD_MODULES_REGISTRY_LOGIN - login to prod registry +# $PROD_MODULES_REGISTRY_PASSWORD - password to prod registry # $SOURCE_REPO - Source repository address for the module # $SOURCE_REPO_SSH_KEY - SSH private key for the source repository -# $DEV_MODULES_REGISTRY_PASSWORD - password to dev registry -# $DEV_MODULES_REGISTRY_PASSWORD - password to dev registry -# $DEV_MODULES_REGISTRY_PASSWORD - password to dev registry -# $DEV_MODULES_REGISTRY_PASSWORD - password to dev registry # SVACE_ANALYZE_HOST - hostname of the svace analyze vm # SVACE_ANALYZE_SSH_USER: - ssh user to connect with to svace analyze vm -# SVACE_ANALYZE_SSH_PRIVATE_KEY- svace analyze server ssh private key +# SVACE_ANALYZE_SSH_PRIVATE_KEY - svace analyze server ssh private key +# MODULE_EDITION (Optional) - one of [ce,fe,be,se,se-plus], only needed to check ALLOW_BE for the basic edition. +# ALLOW_BE (Optional) - if MODULE_EDITION=be, must be set to "true" for the build/deploy. +# DECKHOUSE_LIB_HELM_VERSION - version of deckhouse lib-helm that will be downloaded variables: MODULES_MODULE_NAME: "${CI_PROJECT_NAME}" MODULES_MODULE_TAG: ${CI_COMMIT_REF_NAME} - BASE_IMAGES_VERSION: v0.5.7 + BASE_IMAGES_VERSION: v0.5.8 WERF_REPO: ${MODULES_MODULE_SOURCE}/${MODULES_MODULE_NAME} WERF_VERSION: "2 stable" before_script: + # Deny BE without ALLOW_BE=true + - | + echo "=== Check ALLOW_BE ===" + echo "MODULE_EDITION: ${MODULE_EDITION}" + echo "ALLOW_BE: ${ALLOW_BE}" + if [[ ${MODULE_EDITION} == "be" && ${ALLOW_BE} != "true" ]]; then + echo "BE edition don't allowed without ALLOW_BE=true" + exit 0 + fi + # Setup tag + - | + echo "=== Setup tag ===" + if [[ ${CI_COMMIT_REF_NAME} != "main" ]]; then + export MODULES_MODULE_TAG=$(echo "${CI_COMMIT_REF_NAME}"|sed -e 's/\//-/g') + fi + echo "MODULES_MODULE_TAG: ${MODULES_MODULE_TAG}" # Setup trdl - | - trdl_version=$(curl -s https://tuf.trdl.dev/targets/channels/0/stable) - curl -sSLO "https://tuf.trdl.dev/targets/releases/$trdl_version/linux-amd64/bin/trdl" - install -D trdl ~/bin/trdl - rm trdl - export PATH=$PATH:~/bin + if ! command -v trdl; then + export PATH=$PATH:~/bin + trdl_target_version=$(curl -s https://tuf.trdl.dev/targets/channels/0/stable) + trdl_installed_version=$(trdl | tail -n 1 | sed -E 's/Version: v([0-9\.]+)/\1/') + if [[ "$trdl_installed_version" != "$trdl_target_version" ]]; then + curl -sSLO "https://tuf.trdl.dev/targets/releases/$trdl_target_version/linux-amd64/bin/trdl" + install -D trdl ~/bin/trdl + rm trdl + fi + fi # Setup werf - | + echo "=== Setup werf ===" trdl add werf https://tuf.werf.io 1 b7ff6bcbe598e072a86d595a3621924c8612c7e6dc6a82e919abe89707d7e3f468e616b5635630680dd1e98fc362ae5051728406700e6274c5ed1ad92bea52a2 source $(trdl use werf ${WERF_VERSION:-1.2 stable}) source $(werf ci-env gitlab --as-file) @@ -44,58 +68,90 @@ before_script: if [[ "x${MODULES_REGISTRY_PASSWORD}" == "x" ]]; then MODULES_REGISTRY_PASSWORD="${CI_REGISTRY_PASSWORD}" fi - werf cr login -u ${MODULES_REGISTRY_LOGIN} -p ${MODULES_REGISTRY_PASSWORD} ${MODULES_REGISTRY} + - | # old logic + echo "=== Werf login ===" + if [[ -n "${MODULES_REGISTRY_LOGIN}" && -n "${MODULES_REGISTRY_PASSWORD}" && -n "${MODULES_REGISTRY}" ]]; then + echo "MODULES_REGISTRY_LOGIN: ${MODULES_REGISTRY_LOGIN}" + echo "MODULES_REGISTRY: ${MODULES_REGISTRY}" + werf cr login -u ${MODULES_REGISTRY_LOGIN} -p ${MODULES_REGISTRY_PASSWORD} ${MODULES_REGISTRY} + fi + + - | + echo "=== Werf prod login ===" + if [[ -n "${PROD_MODULES_REGISTRY_LOGIN}" && -n "${PROD_MODULES_REGISTRY_PASSWORD}" && -n "${PROD_MODULES_REGISTRY}" ]]; then + echo "PROD_MODULES_REGISTRY_LOGIN: ${PROD_MODULES_REGISTRY_LOGIN}" + echo "PROD_MODULES_REGISTRY: ${PROD_MODULES_REGISTRY}" + werf cr login -u ${PROD_MODULES_REGISTRY_LOGIN} -p ${PROD_MODULES_REGISTRY_PASSWORD} ${PROD_MODULES_REGISTRY} + fi + + - | + echo "=== Werf dev login ===" if [[ -n "${DEV_MODULES_REGISTRY_LOGIN}" && -n "${DEV_MODULES_REGISTRY_PASSWORD}" && -n "${DEV_MODULES_REGISTRY}" ]]; then + echo "DEV_MODULES_REGISTRY_LOGIN: ${DEV_MODULES_REGISTRY_LOGIN}" + echo "DEV_MODULES_REGISTRY: ${DEV_MODULES_REGISTRY}" werf cr login -u ${DEV_MODULES_REGISTRY_LOGIN} -p ${DEV_MODULES_REGISTRY_PASSWORD} ${DEV_MODULES_REGISTRY} fi + # Setup dmt - | + echo "=== Werf dmt ===" trdl add dmt https://trrr.flant.dev/trdl-dmt/ 3 e77d785600a8c8612b84b93a5a2e4c48188d68f7478356d0708213e928bf67b024ed412e702dc32930da5c5bfc9b1c44be3ee7a292f923327815c91c6c3c3833 source $(trdl use dmt 0 stable) # Download base images yaml file - - env | grep BASE_IMAGES_VERSION - - curl --fail -sSLO https://fox.flant.com/api/v4/projects/deckhouse%2Fbase-images/packages/generic/base_images/${BASE_IMAGES_VERSION}/base_images.yml + - | + echo "=== Download base images yaml file ===" + echo "BASE_IMAGES_VERSION: ${BASE_IMAGES_VERSION}" + curl --fail -sSLO https://fox.flant.com/api/v4/projects/deckhouse%2Fbase-images/packages/generic/base_images/${BASE_IMAGES_VERSION}/base_images.yml + + # Download deckhouse lib-helm archive + - | + if [[ -n "${DECKHOUSE_LIB_HELM_VERSION}" ]]; then + mkdir charts + curl --fail -sSLO https://github.com/deckhouse/lib-helm/releases/download/deckhouse_lib_helm-${DECKHOUSE_LIB_HELM_VERSION}/deckhouse_lib_helm-${DECKHOUSE_LIB_HELM_VERSION}.tgz --output-dir ./charts + fi # Add ssh keys - | - [[ -z "${SOURCE_REPO_SSH_KEY}" || -z "${SVACE_ANALYZE_SSH_PRIVATE_KEY}" ]] && exit 0 + echo "=== Add ssh keys ===" + if [[ -n "${SOURCE_REPO_SSH_KEY}" || -n "${SVACE_ANALYZE_SSH_PRIVATE_KEY}" ]]; then - eval $(ssh-agent) - trap "kill -3 ${SSH_AGENT_PID}" ERR EXIT HUP INT QUIT TERM - export SSH_KNOWN_HOSTS=~/.ssh/known_hosts - mkdir -p ~/.ssh - touch ~/.ssh/known_hosts + eval $(ssh-agent) + trap "kill -3 ${SSH_AGENT_PID}" ERR EXIT HUP INT QUIT TERM + export SSH_KNOWN_HOSTS=~/.ssh/known_hosts + mkdir -p ~/.ssh + touch ~/.ssh/known_hosts - if [[ -n "${SOURCE_REPO_SSH_KEY}" ]]; then - ssh-add - <<< "${SOURCE_REPO_SSH_KEY}" - if [[ -n "${SOURCE_REPO}" ]]; then - HOST=$(grep -oP '(?<=@)[^/:]+' <<< ${SOURCE_REPO}) - HOST_KEYS=$(ssh-keyscan -H "$HOST" 2>/dev/null) - while IFS= read -r KEY_LINE; do - CONSTANT_PART=$(awk '{print $2, $3}' <<< "$KEY_LINE") - if ! grep -q "$CONSTANT_PART" ~/.ssh/known_hosts; then - echo "$KEY_LINE" >> ~/.ssh/known_hosts - fi - done <<< "$HOST_KEYS" + if [[ -n "${SOURCE_REPO_SSH_KEY}" ]]; then + ssh-add - <<< "${SOURCE_REPO_SSH_KEY}" + if [[ -n "${SOURCE_REPO}" ]]; then + HOST=$(grep -oP '(?<=@)[^/:]+' <<< ${SOURCE_REPO}) + HOST_KEYS=$(ssh-keyscan -H "$HOST" 2>/dev/null) + while IFS= read -r KEY_LINE; do + CONSTANT_PART=$(awk '{print $2, $3}' <<< "$KEY_LINE") + if ! grep -q "$CONSTANT_PART" ~/.ssh/known_hosts; then + echo "$KEY_LINE" >> ~/.ssh/known_hosts + fi + done <<< "$HOST_KEYS" + fi fi - fi - if [[ -n "${SVACE_ANALYZE_SSH_PRIVATE_KEY}" ]]; then - ssh-add - <<< "${SVACE_ANALYZE_SSH_PRIVATE_KEY}" - if [[ -n "${SVACE_ANALYZE_HOST}" ]]; then - echo "Adding svace ssh key (ignoring errors)." - set +e - HOST=${SVACE_ANALYZE_HOST} - HOST_KEYS=$(ssh-keyscan -H "$HOST" 2>/dev/null) - while IFS= read -r KEY_LINE; do - CONSTANT_PART=$(awk '{print $2, $3}' <<< "$KEY_LINE") - if ! grep -q "$CONSTANT_PART" ~/.ssh/known_hosts; then - echo "$KEY_LINE" >> ~/.ssh/known_hosts - fi - done <<< "$HOST_KEYS" - set -e + if [[ -n "${SVACE_ANALYZE_SSH_PRIVATE_KEY}" ]]; then + ssh-add - <<< "${SVACE_ANALYZE_SSH_PRIVATE_KEY}" + if [[ -n "${SVACE_ANALYZE_HOST}" ]]; then + echo "Adding svace ssh key (ignoring errors)." + set +e + HOST=${SVACE_ANALYZE_HOST} + HOST_KEYS=$(ssh-keyscan -H "$HOST" 2>/dev/null) + while IFS= read -r KEY_LINE; do + CONSTANT_PART=$(awk '{print $2, $3}' <<< "$KEY_LINE") + if ! grep -q "$CONSTANT_PART" ~/.ssh/known_hosts; then + echo "$KEY_LINE" >> ~/.ssh/known_hosts + fi + done <<< "$HOST_KEYS" + set -e + fi fi fi diff --git a/templates/Svace_Analayze.gitlab-ci.yml b/templates/Svace_Analayze.gitlab-ci.yml index 747b94a..0ce0bf9 100644 --- a/templates/Svace_Analayze.gitlab-ci.yml +++ b/templates/Svace_Analayze.gitlab-ci.yml @@ -217,9 +217,12 @@ variables: --form project=\"${project_name}\" \ --form branch=\"${branch_name}\" \ --form file=@\"${archive_name}\" \ - --form options=\"--project-group ${PROJECT_GROUP}\" \ - --form options=\"--if-no-group ${IF_NO_GROUP}\" \ - --form options=\"--field COMMIT_HASH:${COMMIT_HASH}\"" + --form options='{\"values\":[ \ + {\"option\":\"project-group\",\"value\":\"${PROJECT_GROUP}\"}, \ + {\"option\":\"if-no-group\",\"value\":\"${IF_NO_GROUP}\"}, \ + {\"option\":\"field\",\"value\":\"CI_COMMIT_HASH:${COMMIT_HASH}\"}, \ + {\"option\":\"field\",\"value\":\"CI_COMMIT_REF_NAME:${COMMIT_REF_NAME}\"} \ + ]}'" info "Importing \"${project_name}\"..." response=$(send_request "${svacer_import}" $request_attempts) @@ -259,9 +262,43 @@ variables: fi } + define_import_params() { + local -n project="${1}" + local -n branch="${2}" + if [[ $(send "[[ -f ${proj}/.svace-dir/import-settings ]] && echo true || echo false") == true ]]; then + import_settings=$(send "cat /${proj}/.svace-dir/import-settings") + while IFS='=' read -r key val; do + case "$key" in + ProjectName) + project=$val + ;; + Branch) + branch=$val + ;; + *) + warning "Undefined import setting \"${key}=${val}\" will be ommited!" + ;; + esac + done <<< "${import_settings}" + fi + } + + get_svace_bin() { + proj="${1}" + svace_version=$(send "cat ${proj}/.svace-dir/svace-dir.version | awk 'FNR==3{print}'") + + svace_bin="/opt/svace-${svace_version}/bin/svace" + if [[ $(send "[[ -x ${svace_bin} ]] && echo true || echo false") == true ]]; then + echo "${svace_bin}" + else + echo "svace" + error "\"${svace_bin}\" is not executable on analyze server. Using default." + fi + } + echo "Searching for current build artifacts on server by path: /${SVACE_ANALYZE_DIR}/${COMMIT_HASH}" if [[ $(send "[[ -d /${SVACE_ANALYZE_DIR}/${COMMIT_HASH} ]] && echo true || echo false") == false ]]; then - echo "::warning file=$(realpath "$0")::Specified commit directory doesn't exists on analyze server." && exit 0 + warning "Specified commit directory doesn't exists on analyze server." && exit 1 fi projects=$(send "find /${SVACE_ANALYZE_DIR}/${COMMIT_HASH} \\( -type d -iname .svace-dir -o -iname *.tar.gz \\) -exec dirname {} \\;") @@ -273,10 +310,17 @@ variables: svacer_proj=${proj#/${SVACE_ANALYZE_DIR}/${COMMIT_HASH}/} build_item=${svacer_proj##*/} + import_project=${svacer_proj} + import_branch=${COMMIT_REF_NAME} + if [[ $(send "[[ -d ${proj}/.svace-dir ]] && echo true || echo false") == true ]]; then + define_import_params import_project import_branch + svace_bin=$(get_svace_bin "${proj}") + info "Using svace binary: $svace_bin" + info "Start analyzing project \"${svacer_proj}\" ..." - send "svace config --svace-dir ${proj} THREAD_NUMBER auto" - send "svace analyze --set-config SKIP_UNREACHABLE_PROCEDURE_ANALYSIS=${SKIP_UNREACHABLE_PROCEDURE_ANALYSIS} --quiet --svace-dir ${proj}" + send "${svace_bin} config --svace-dir ${proj} THREAD_NUMBER auto" + send "${svace_bin} analyze --set-config SKIP_UNREACHABLE_PROCEDURE_ANALYSIS=${SKIP_UNREACHABLE_PROCEDURE_ANALYSIS} --quiet --svace-dir ${proj}" success "Analysis completed successfully!" info "Start archiving project \"${svacer_proj}\" ..." diff --git a/templates/gitleaks.gitlab-ci.yml b/templates/gitleaks.gitlab-ci.yml new file mode 100644 index 0000000..8562fd0 --- /dev/null +++ b/templates/gitleaks.gitlab-ci.yml @@ -0,0 +1,135 @@ +variables: + GITLEAKS_VERSION: "v8.28.0" + +.gitleaks_scan: + stage: gitleaks + variables: + GIT_DEPTH: 0 + before_script: [] + script: + - | + set -euo pipefail + + # ========== Install Gitleaks ========== + echo "๐Ÿ“ฅ Installing Gitleaks $GITLEAKS_VERSION..." + file_ver="${GITLEAKS_VERSION#v}" + arch="$(uname -m)" + case "$arch" in + x86_64|amd64) pkg_arch="linux_x64" ;; + aarch64|arm64) pkg_arch="linux_arm64" ;; + *) echo "Unsupported arch: $arch"; exit 1 ;; + esac + + base="https://github.com/gitleaks/gitleaks/releases/download/$%7BGITLEAKS_VERSION%7D" + tgz="gitleaks_${file_ver}_${pkg_arch}.tar.gz" + curl -sSL "$base/$tgz" -o gitleaks.tgz + tar -xzf gitleaks.tgz gitleaks + chmod +x gitleaks + mkdir -p "$HOME/.local/bin" + mv gitleaks "$HOME/.local/bin/" + export PATH="$HOME/.local/bin:$PATH" + gitleaks version + + # ========== Check for config ========== + if [[ -f "gitleaks.toml" ]]; then + CONFIG_ARG="-c gitleaks.toml" + echo "โœ… Found config: gitleaks.toml" + else + CONFIG_ARG="" + echo "โš ๏ธ Config file not found. Proceeding with default rules." + fi + + # ========== Run scan ========== + GITLEAKS_EXIT=0 + if [[ "$SCAN_MODE" == "diff" ]]; then + echo "๐Ÿ•ต๏ธ Running in DIFF mode..." + + BASE_COMMIT=$(git merge-base "origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" "$CI_COMMIT_SHA") + HEAD_COMMIT="$CI_COMMIT_SHA" + + echo "โ–ถ Target branch: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME" + echo "โ–ถ Base commit (merge-base): $BASE_COMMIT" + echo "โ–ถ Head commit: $HEAD_COMMIT" + echo "โ–ถ Scanning range: ${BASE_COMMIT}..${HEAD_COMMIT}" + + gitleaks detect --no-banner --report-format json --report-path gitleaks.json $CONFIG_ARG --source . --log-opts "${BASE_COMMIT}..${HEAD_COMMIT}" || GITLEAKS_EXIT=$? + elif [[ "$SCAN_MODE" == "full" ]]; then + echo "๐Ÿ•ต๏ธ Running in FULL mode..." + gitleaks detect --no-banner --report-format json --report-path gitleaks.json $CONFIG_ARG --source . || GITLEAKS_EXIT=$? + else + echo "โŒ Unknown SCAN_MODE: $SCAN_MODE" + exit 1 + fi + + echo "๐Ÿ” Gitleaks exit code: $GITLEAKS_EXIT" + + # ========== Parse and print results ========== + echo "๐Ÿ“ค Parsing gitleaks.json for CI log output..." + echo "DEBUG: Checking gitleaks.json file..." + ls -lh gitleaks.json || echo "โš ๏ธ gitleaks.json not found!" + + if [[ -s gitleaks.json ]]; then + COUNT=$(jq length gitleaks.json) + echo "โŒ Leaks found: $COUNT" + echo "" + echo "DEBUG: Attempting to parse and display leaks..." + + jq -r ' + def norm: + { + file: (.File // .file // .Target // .Location.File // "unknown"), + line: (.StartLine // .Line // .Location.StartLine // 0), + rule: (.RuleID // .Rule // .Description // "unknown"), + commit: (.Commit // .commit // "") + }; + (if type=="object" and has("findings") then .findings + elif type=="array" then . + else [] end)[] | norm + | "โ€ข [\(.rule)] \(.file):\(.line) \(.commit[0:7] // "no-commit") '$CI_PROJECT_URL'/blob/\(.commit)/\(.file)#L\(.line)" + ' gitleaks.json | head -n 200 + + echo "" + echo "DEBUG: Finished displaying leaks" + + # Fail the job if leaks were found + if [[ "$COUNT" -gt 0 ]]; then + echo "" + echo "โŒ Pipeline failed due to $COUNT leak(s). Review gitleaks.json artifact." + exit 1 + fi + else + echo "โœ… No leaks found." + fi + + after_script: + - echo "๐Ÿงน Cleaning up runner workspace..." + - rm -f "$HOME/.local/bin/gitleaks" gitleaks.tgz || true + + artifacts: + when: always + paths: + - gitleaks.json + + allow_failure: false + +gitleaks_diff: + extends: .gitleaks_scan + variables: + SCAN_MODE: "diff" + rules: + - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' + +gitleaks_full_manual: + extends: .gitleaks_scan + variables: + SCAN_MODE: "full" + rules: + - if: '$CI_PIPELINE_SOURCE == "web"' + +gitleaks_full_scheduled: + extends: .gitleaks_scan + variables: + SCAN_MODE: "full" + rules: + - if: '$CI_PIPELINE_SOURCE == "schedule"' +