#########################################################################################################################################################
### WARNING : Manual jobs defined with rules key ARE BLOCKING as long as this issue is unresolved : https://gitlab.com/gitlab-org/gitlab/issues/34077 ###
#########################################################################################################################################################

image: docker:19.03.0

# Disable TLS just for the docker daemon running locally, TLS is still used to deploy built images!
variables:
  DOCKER_TLS_CERTDIR: ""
  DOCKER_DRIVER: overlay2

services:
    - docker:19.03.0-dind

# The file variables will be kept accross jobs : it contains useful informations about modified
# Dockerfile / docker-compose in the last commit
cache:
 paths:
  - variables

stages:
  - ci-base
  - build
  - security-tests
  - push

# Hidden key meant to be included in other jobs, for factorization
.pull-modified-image: &pull-modified-image
  image: $REGISTRY_PROD/pica-ci-base
  tags: [build]
  before_script:
    - echo $REGISTRY_PASSWORD | docker login $REGISTRY -u $REGISTRY_USERNAME --password-stdin
    - source variables
    - docker pull $MODIFIED_IMAGE_FULL_TEST

# Build the base image used for all further steps : this is done only when pica-ci's Dockerfile is modified
pica-ci-base:
  stage: ci-base
  tags: [build]
  before_script:
    - echo $REGISTRY_PROD_PASSWORD | docker login $REGISTRY_PROD -u $REGISTRY_PROD_USERNAME --password-stdin
  script:
    - docker build -f pica-ci-base/Dockerfile . -t $REGISTRY_PROD/pica-ci-base:latest
    - docker push $REGISTRY_PROD/pica-ci-base:latest
  after_script:
    - docker logout $REGISTRY_PROD
  only:
    changes:
      - "pica-ci-base/*"
    refs:
      - master
      - dev-ci

# Create a file a few environment variables added (which Dockerfile has been modified, the complete name of the image...)
# The file will be an artifact shared with further steps
set-variables:
  stage: ci-base
  tags: [build]
  image: $REGISTRY_PROD/pica-ci-base
  script:
    - chmod +x ./get-modified-image.sh
    - ./get-modified-image.sh
  # If the Dockerfile is changed, force the build.
  # Otherwise, may be triggered manually.
  when: always

# Build the image that was modified
build:
  stage: build
  tags: [build]
  image: $REGISTRY_PROD/pica-ci-base
  before_script:
    - echo $REGISTRY_PASSWORD | docker login $REGISTRY -u $REGISTRY_USERNAME --password-stdin
    - source variables
  script:
    - docker build -f $MODIFIED_IMAGE/Dockerfile $MODIFIED_IMAGE -t $MODIFIED_IMAGE_FULL_TEST
    - docker push $MODIFIED_IMAGE_FULL_TEST
  after_script:
    - docker logout $REGISTRY
  # If the Dockerfile is changed, force the build.
  # Otherwise, may be triggered manually.
  rules:
    - changes:
      - "**/Dockerfile"
      when: always
    - when: manual

# Run CoreOS' Clair and make the CI failed if a critical vulnerability isn't in the whitelist
clair:
  stage: security-tests
  <<: *pull-modified-image
  script:
    - docker run -d --name db arminc/clair-db:latest
    - docker run -p 6060:6060 -d --link db:postgres --name clair --restart on-failure arminc/clair-local-scan:latest
    - wget https://github.com/arminc/clair-scanner/releases/download/v8/clair-scanner_linux_amd64
    - mv clair-scanner_linux_amd64 clair-scanner
    - chmod +x clair-scanner
    - while( ! wget -q -O /dev/null http://docker:6060/v1/namespaces ) ; do sleep 1 ; done
    - ./clair-scanner -c http://docker:6060 --ip $(hostname -i) -r clair-report.json -l clair.log -w $MODIFIED_IMAGE/clair-whitelist.yml --threshold="High" $MODIFIED_IMAGE_FULL_TEST
  artifacts:
    paths:
      - clair-report.json
      - clair.log
  rules:
    - changes:
      - "**/Dockerfile"
      - "**/docker-compose.yml"
      - "**/clair-whitelist.yml"
      when: always
    - when: manual

# Run docker-bench-security and upload the results
docker-bench-security:
  stage: security-tests
  script:
    # Change the Docker Compose to use the "testing" image, not yet pushed on production registry
    - sed -i -e "s|$MODIFIED_IMAGE_FULL|$MODIFIED_IMAGE_FULL_TEST|g" $MODIFIED_IMAGE/docker-compose.yml
    # If *.example secrets files exist, remove the .example extension to be able to start the container
    # Indeed these file are used in Docker Compose with env_file directive
    - if [[ -d $MODIFIED_IMAGE/secrets ]]; then for i in $MODIFIED_IMAGE/secrets/*.example ; do cp $i $(echo $i| cut -d '.' -f1,2); done; fi;
    # Let docker-compose create the required volumes and networks
    - "sed -i -e 's/external: true/external: false/g' $MODIFIED_IMAGE/docker-compose.yml"
    - cat $MODIFIED_IMAGE/docker-compose.yml
    - cd $MODIFIED_IMAGE
    - docker-compose up -d
    - git clone https://github.com/docker/docker-bench-security.git
    - cd docker-bench-security
    - sh docker-bench-security.sh -c container_images,container_runtime,docker_security_operations,community_checks -l ../../report.
  after_script:
    - docker logout $REGISTRY
  artifacts:
    paths:
      - report.txt
  rules:
    - changes:
      - "**/Dockerfile"
      - "**/docker-compose.yml"
      when: always
    - when: manual

# Push the generated image on the production registry,
# once it passed all security tests and has been successfully built
# and run on the test virtual machine
push-prod:
  stage: push
  <<: *pull-modified-image
  script:
    - docker tag $MODIFIED_IMAGE_FULL_TEST $MODIFIED_IMAGE_FULL
    - echo $REGISTRY_PROD_PASSWORD | docker login $REGISTRY_PROD -u $REGISTRY_PROD_USERNAME --password-stdin
    # MODIFIED_IMAGE_FULL already should include the registry URL
    - docker push $MODIFIED_IMAGE_FULL
  after_script:
    - docker logout $REGISTRY_PROD
  only:
    refs:
      - master
  when: manual
