# =====================================================================================================================
# === JIB template variant
# =====================================================================================================================
spec:
  inputs:
    jib-snapshot-image:
      description: Maven Jib Snapshot image
      default: $CI_REGISTRY_IMAGE/snapshot:$CI_COMMIT_REF_SLUG
    jib-release-image:
      description: Maven Jib Release image
      default: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME
    skopeo-image:
      description: The image used to publish images with Skopeo
      default: quay.io/skopeo/stable:latest
    jib-build-args:
      description: '[Jib Maven Plugin arguments](https://github.com/GoogleContainerTools/jib/tree/master/jib-maven-plugin#extended-usage)'
      default: -Djib.to.image=$MAVEN_JIB_SNAPSHOT_IMAGE
    jib-prod-publish-strategy:
      description: Defines the publish to production strategy.
      options:
      - none
      - manual
      - auto
      default: manual
    jib-publish-args:
      description: Additional [`skopeo copy` arguments](https://github.com/containers/skopeo/blob/master/docs/skopeo-copy.1.md#options)
      default: ''
    trivy-disabled:
      description: Disable Maven Trivy
      type: boolean
      default: false
    trivy-image:
      description: The docker image used to scan images with Trivy
      default: registry.hub.docker.com/aquasec/trivy:latest
    trivy-addr:
      description: The Trivy server address
      default: ''
    trivy-security-level-threshold:
      description: 'Severities of vulnerabilities to be displayed (comma separated values:
        `UNKNOWN`, `LOW`, `MEDIUM`, `HIGH`, `CRITICAL`)'
      options:
      - UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL
      - LOW,MEDIUM,HIGH,CRITICAL
      - MEDIUM,HIGH,CRITICAL
      - HIGH,CRITICAL
      - CRITICAL
      default: UNKNOWN,LOW,MEDIUM,HIGH,CRITICAL
    trivy-args:
      description: Additional `trivy client` arguments
      default: --ignore-unfixed --vuln-type os
    sbom-image:
      default: registry.hub.docker.com/anchore/syft:debug
    sbom-opts:
      description: Options for syft used for SBOM analysis
      default: --catalogers rpm-db-cataloger,alpmdb-cataloger,apkdb-cataloger,dpkgdb-cataloger,portage-cataloger
---
variables:
  MAVEN_SBOM_IMAGE: $[[ inputs.sbom-image ]]
  MAVEN_SBOM_OPTS: $[[ inputs.sbom-opts ]]
  MAVEN_TRIVY_SECURITY_LEVEL_THRESHOLD: $[[ inputs.trivy-security-level-threshold ]]
  MAVEN_TRIVY_IMAGE: $[[ inputs.trivy-image ]]
  MAVEN_TRIVY_ARGS: $[[ inputs.trivy-args ]]
  MAVEN_JIB_SNAPSHOT_IMAGE: $[[ inputs.jib-snapshot-image ]]
  MAVEN_JIB_RELEASE_IMAGE: $[[ inputs.jib-release-image ]]
  MAVEN_JIB_BUILD_ARGS: $[[ inputs.jib-build-args ]]
  MAVEN_JIB_PROD_PUBLISH_STRATEGY: $[[ inputs.jib-prod-publish-strategy ]]
  MAVEN_SKOPEO_IMAGE: $[[ inputs.skopeo-image ]]
  MAVEN_JIB_PUBLISH_ARGS: $[[ inputs.jib-publish-args ]]
  MAVEN_TRIVY_DISABLED: $[[ inputs.trivy-disabled ]]
  MAVEN_TRIVY_ADDR: $[[ inputs.trivy-addr ]]

.mvn-jib-scripts: &mvn-jib-scripts |
  # BEGSCRIPT
  set -e
  
  function configure_registries_auth() {
    maven_jib_snapshot_authn_token=$(echo -n "${MAVEN_JIB_REGISTRY_SNAPSHOT_USER:-${MAVEN_JIB_REGISTRY_USER:-$CI_REGISTRY_USER}}:${MAVEN_JIB_REGISTRY_SNAPSHOT_PASSWORD:-${MAVEN_JIB_REGISTRY_PASSWORD:-$CI_REGISTRY_PASSWORD}}" | base64 | tr -d '\n')
    maven_jib_snapshot_registry_host=$(echo "$MAVEN_JIB_SNAPSHOT_IMAGE" | cut -d/ -f1)

    maven_jib_release_authn_token=$(echo -n "${MAVEN_JIB_REGISTRY_RELEASE_USER:-${MAVEN_JIB_REGISTRY_USER:-$CI_REGISTRY_USER}}:${MAVEN_JIB_REGISTRY_RELEASE_PASSWORD:-${MAVEN_JIB_REGISTRY_PASSWORD:-$CI_REGISTRY_PASSWORD}}" | base64 | tr -d '\n')
    maven_jib_release_registry_host=$(echo "$MAVEN_JIB_RELEASE_IMAGE" | cut -d/ -f1)

    maven_jib_snapshot_config_json=$(echo -n "{\"auths\":{\"$maven_jib_snapshot_registry_host\":{\"auth\":\"$maven_jib_snapshot_authn_token\"},\"HttpHeaders\":{\"User-Agent\":\"$USER_AGENT\"}}}")
    maven_jib_release_config_json=$(echo -n "{\"auths\":{\"$maven_jib_release_registry_host\":{\"auth\":\"$maven_jib_release_authn_token\"},\"HttpHeaders\":{\"User-Agent\":\"$USER_AGENT\"}}}")

    BUILDTOOL_HOME=${BUILDTOOL_HOME:-$HOME}
    # Create Docker auth config (supported by Jib)
    mkdir -p "$BUILDTOOL_HOME/.docker"
    echo "${maven_jib_snapshot_config_json}" > $BUILDTOOL_HOME/.docker/config.json
    echo "${maven_jib_release_config_json}" > $BUILDTOOL_HOME/.docker/release-config.json
    
    log_info "Registry authentication configured for \\e[33;1m${maven_jib_snapshot_registry_host}\\e[0m"
  }
  
  configure_registries_auth

  # ENDSCRIPT
  
mvn-build:
  extends: .mvn-base
  script:
    # initialize Docker auth config
    - !reference [.mvn-jib-scripts]
    # build and push snapshot container
    - >- 
      mvn ${TRACE+-X} $MAVEN_CLI_OPTS $mvn_settings_opt $java_proxy_args verify 
      com.google.cloud.tools:jib-maven-plugin:build 
      $MAVEN_JIB_BUILD_ARGS
    - output_coverage
    # create dotenv file
    - jib_digest=$(cat target/jib-image.digest | cut -f2 -d':' )
    - jib_repository=${MAVEN_JIB_SNAPSHOT_IMAGE%:*}
    - jib_tag=${MAVEN_JIB_SNAPSHOT_IMAGE##*:}
    - |
      {
        echo "jib_image=$MAVEN_JIB_SNAPSHOT_IMAGE"
        echo "jib_image_digest=$jib_repository@$jib_digest"
        echo "jib_repository=$jib_repository"
        echo "jib_tag=$jib_tag"
        echo "jib_digest=$jib_digest"  
      } > jib.env
  artifacts:
    reports:
      dotenv:
        - jib.env
      
mvn-sbom:
  extends: .mvn-base
  stage: package-test
  image:
    name: $MAVEN_SBOM_IMAGE
    entrypoint: [""]
  # force no dependency
  dependencies: []
  script:
    # initialize Docker auth config
    - !reference [.mvn-jib-scripts]
    - mkdir -p -m 777 reports
    - /syft packages $MAVEN_JIB_SNAPSHOT_IMAGE $MAVEN_SBOM_OPTS -o cyclonedx-json=reports/mvn-sbom-${jib_digest}.cyclonedx.json
    - chmod a+r reports/mvn-sbom-${jib_digest}.cyclonedx.json
  artifacts:
    name: "SBOM for container from $CI_PROJECT_NAME on $CI_COMMIT_REF_SLUG"
    expire_in: 1 week
    when: always
    paths:
      - "reports/mvn-jib-sbom-*.cyclonedx.json"
    reports:
      cyclonedx: 
        - "reports/mvn-jib-sbom-*.cyclonedx.json"

mvn-trivy:
  extends: .mvn-base
  stage: package-test
  image:
    name: $MAVEN_TRIVY_IMAGE
    entrypoint: [""]
  dependencies: []
  variables:
    TRIVY_CACHE_DIR: ".trivycache/"
  script: |
    # cache cleanup is needed when scanning images with the same tags, it does not remove the database
    trivy image --clear-cache
    export TRIVY_USERNAME=${MAVEN_JIB_REGISTRY_SNAPSHOT_USER:-${MAVEN_JIB_REGISTRY_USER:-$CI_REGISTRY_USER}}
    export TRIVY_PASSWORD=${MAVEN_JIB_REGISTRY_SNAPSHOT_PASSWORD:-${MAVEN_JIB_REGISTRY_PASSWORD:-$CI_REGISTRY_PASSWORD}}
    export basename=$(echo "${MAVEN_JIB_SNAPSHOT_IMAGE}" | sed 's|[/:]|_|g')
    mkdir -p ./reports
    if [[ -z "${MAVEN_TRIVY_ADDR}" ]]; then
      log_warn "\\e[93mYou are using Trivy in standalone mode. To get faster scans, consider setting the MAVEN_TRIVY_ADDR variable to the address of a Trivy server. More info here: https://aquasecurity.github.io/trivy/latest/docs/references/modes/client-server/\\e[0m"
      trivy image --download-db-only
      export trivy_opts="image"
    else
      log_info "You are using Trivy in client/server mode with the following server: ${MAVEN_TRIVY_ADDR}"
      export trivy_opts="image --server ${MAVEN_TRIVY_ADDR}"
    fi
    # Add common trivy arguments
    export trivy_opts="${trivy_opts} --no-progress --severity ${MAVEN_TRIVY_SECURITY_LEVEL_THRESHOLD} ${MAVEN_TRIVY_ARGS}"
    # GitLab format (no fail)
    trivy ${trivy_opts} --format template --exit-code 0 --template "@/contrib/gitlab.tpl" --output reports/docker-trivy-${basename}.gitlab.json $MAVEN_JIB_SNAPSHOT_IMAGE
    # JSON format (no fail)
    if [[ "$DEFECTDOJO_TRIVY_REPORTS" ]]
    then
      trivy ${trivy_opts} --format json --exit-code 0 --output reports/docker-trivy-${basename}.native.json $MAVEN_JIB_SNAPSHOT_IMAGE
    fi
    # console output (fail)
    trivy ${trivy_opts} --format table --exit-code 1 $MAVEN_JIB_SNAPSHOT_IMAGE
  artifacts:
    when: always
    paths:
    - "reports/jib-trivy-*"
    reports:
      container_scanning: "reports/jib-trivy-*.gitlab.json"
  cache:
    paths:
      - .trivycache/
  rules:
    - if: '$MAVEN_TRIVY_DISABLED == "true"'
      when: never
    - !reference [.test-policy, rules]
            
mvn-deploy-release:
  extends: .mvn-base
  image:
    name: "$MAVEN_SKOPEO_IMAGE"
    entrypoint: [""]
  stage: publish
  variables:
    GIT_STRATEGY: none
  script:
    # initialize Docker auth config
    - !reference [.mvn-jib-scripts]
    - |
      if [[ "${SEMREL_INFO_ON}" && "${MVN_SEMREL_RELEASE_DISABLED}" != "true" ]]
      then
        if [[ -z "${SEMREL_INFO_NEXT_VERSION}" ]]
        then
          log_warn "[semantic-release] no new version to release: skip"
          exit 0
        else
          MAVEN_JIB_RELEASE_IMAGE=$(echo "$MAVEN_JIB_RELEASE_IMAGE" | sed "s/\(:.*\)\{0,1\}$/:$SEMREL_INFO_NEXT_VERSION/")
          log_info "[semantic-release] new Image tag is set: $MAVEN_JIB_RELEASE_IMAGE"
        fi
      fi

      if [[ "$MAVEN_JIB_SNAPSHOT_IMAGE" == "$MAVEN_JIB_RELEASE_IMAGE" ]]
      then
        log_warn "\\e[93mYou should consider distinguishing snapshot and release images as they do not differ. Skipping publish phase as image has already been created by previous job.\\e[0m"
        exit 0
      fi
      BUILDTOOL_HOME=${BUILDTOOL_HOME:-$HOME}
      skopeo copy --src-authfile $BUILDTOOL_HOME/.docker/config.json --dest-authfile $BUILDTOOL_HOME/.docker/release-config.json ${MAVEN_JIB_PUBLISH_ARGS} docker://$MAVEN_JIB_SNAPSHOT_IMAGE docker://$MAVEN_JIB_RELEASE_IMAGE
      log_info "Well done, your image is published and can be downloaded by doing: docker pull $MAVEN_JIB_RELEASE_IMAGE"
    - jib_digest=$(skopeo inspect --authfile $BUILDTOOL_HOME/.docker/release-config.json --format='{{ .Digest }}' "docker://$MAVEN_JIB_RELEASE_IMAGE")
    - jib_repository=${MAVEN_JIB_RELEASE_IMAGE%:*}
    - jib_tag=${MAVEN_JIB_RELEASE_IMAGE##*:}
    - |
      {
        echo "jib_image=$MAVEN_JIB_RELEASE_IMAGE"
        echo "jib_image_digest=$jib_repository@$jib_digest"
        echo "jib_repository=$jib_repository"
        echo "jib_tag=$jib_tag"
        echo "jib_digest=$jib_digest" 
      } > jib.env
  artifacts:
    reports:
      dotenv:
        - jib.env
  rules:
    # exclude if $MAVEN_DEPLOY_ENABLED not set
    - if: '$MAVEN_DEPLOY_ENABLED != "true"'
      when: never
    # on tag: if semrel info not enabled or semrel integration disabled
    - if: '$CI_COMMIT_TAG'
    # exclude non-production branches
    - if: '$CI_COMMIT_REF_NAME !~ $PROD_REF'
      when: never
    # exclude if snapshot is same as release image and semrel info not enabled or semrel integration disabled
    - if: '$MAVEN_JIB_SNAPSHOT_IMAGE == $MAVEN_JIB_RELEASE_IMAGE && ($SEMREL_INFO_ON == null || $SEMREL_INFO_ON == "" || $MVN_SEMREL_RELEASE_DISABLED == "true")'
      when: never
    - if: '$MAVEN_JIB_PROD_PUBLISH_STRATEGY == "manual"'
      when: manual
    - if: '$MAVEN_JIB_PROD_PUBLISH_STRATEGY == "auto"'

# =====================================================================================================================
# === Disable Maven template jobs not required for Docker Jib pipeline
# =====================================================================================================================

# mvn-build supersedes - deploys a snapshot container to the registry
mvn-deploy-snapshot:
  rules:
    - when: never