# This template implements a generic set of terraform-related testing/linting jobs. It is usually included in product
# pipelines via the /auto-devops/terraform-pipeline.yml template. However, in some situations it might be necessary to
# include this template directly, for example if a specific repository is not suitable for CI pipeline deployments but
# you still wish to test/lint the Terraform code.
#
# This template includes four jobs in the test stage, terraform-validate, terraform-fmt, tflint, and trivy. By default,
# the jobs run on every commit pushed or if a merge request is open. However, this can be changed by overriding
# .test-job-rules in your local .gitlab-ci.yml file if required. For more info see the comments alongside each of these
# job definitions below.
#
# Disabling jobs
#
# Following the AutoDevOps model, if the following variables are defined, the associated jobs will be disabled:
#
# - TERRAFORM_VALIDATE_DISABLED
# - TERRAFORM_FMT_DISABLED
# - TFLINT_DISABLED
# - TRIVY_DISABLED

# Rules which only run test jobs on commit pipelines if there is not an active MR. This avoids duplicate jobs being
# created.
.test-job-rules:
  - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
  - if: "$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS"
    when: never
  - if: "$CI_COMMIT_BRANCH || $CI_COMMIT_TAG"

terraform-validate:
  stage: test
  image: ${TERRAFORM_DEPLOY_IMAGE}:${TERRAFORM_DEPLOY_VERSION}
  script: |
    terraform init -backend=false
    terraform validate
  rules:
    - if: $TERRAFORM_VALIDATE_DISABLED
      when: never
    - !reference [.test-job-rules]
  tags:
    - $GKE_RUNNER_TAG
  needs: []

terraform-fmt:
  stage: test
  image: ${TERRAFORM_DEPLOY_IMAGE}:${TERRAFORM_DEPLOY_VERSION}
  script: terraform fmt -diff -recursive -check
  rules:
    - if: $TERRAFORM_FMT_DISABLED
      when: never
    - !reference [.test-job-rules]
  tags:
    - $GKE_RUNNER_TAG
  needs: []

# The tflint (https://github.com/terraform-linters/tflint) tool contains many linting rules and is basically the
# community standard. We are enabling almost all available rules.
tflint:
  stage: test
  image:
    name: ghcr.io/terraform-linters/tflint:latest
    entrypoint: [""]
  before_script: |
    if [ ! -f .tflint.hcl ]; then
    cat > .tflint.hcl <<EOL
    plugin "terraform" {
      enabled = true
      preset  = "all"
    }
    EOL
    fi
  script: |
    tflint --init
    tflint --recursive --disable-rule=terraform_standard_module_structure
  rules:
    - if: $TFLINT_DISABLED
      when: never
    - !reference [.test-job-rules]
  tags:
    - $GKE_RUNNER_TAG
  needs: []

# Trivy (https://aquasecurity.github.io/trivy) is a comprehensive and versatile security scanner. Trivy has scanners
# that look for security issues, and targets where it can find those issues. This job uploads a junit report of the test
# results which is viewable in the merge request UI. To ignore specific checks see -
# https://aquasecurity.github.io/trivy/v0.50/docs/configuration/filtering/#trivyignoreyaml. By default, we're ignoring
# certain checks which we have decided to allow due to our boilerplate template design.
# Excluded general checks:
#   - name: AVD-GCP-0017
#     link: https://avd.aquasec.com/misconfig/google/sql/avd-gcp-0017/
#     description: Ensure that Cloud SQL Database Instances are not publicly exposed
#     severity: High
#     reason: It is recommended that database instances should be configured so that they are not available over 
#             the public internet, but to internal compute resources that access them. Valid recommendation, but not
#             always applicable due to our system design limitations.
#   - name: AVD-GCP-0029
#     link: https://avd.aquasec.com/misconfig/google/compute/avd-gcp-0029/
#     description: VPC flow logs should be enabled for all subnetworks
#     severity: Low
#     reason: Just a recommendation to have this feature enabled as VPC flow logs record
#             information about all traffic, which can help with reviewing anomalous traffic.
#   - name: AVD-GCP-0066
#     link: https://avd.aquasec.com/misconfig/google/storage/avd-gcp-0066/
#     description: Cloud Storage buckets should be encrypted with a customer-managed key
#     severity: Low
#     reason: It is recommended to use customer-managed keys. Using unmanaged keys makes rotation and general management
#             difficult. However, in our case, it might bring additional operational overhead so this check is disabled.
# Excluded PostgreSQL configuration-related checks:
#   - name: AVD-GCP-0014
#     link: https://avd.aquasec.com/misconfig/google/sql/avd-gcp-0014/
#     description: Temporary file logging should be enabled for all temporary files
#     severity: Medium
#     reason: Trivy suggests setting `settings.database_flags["log_temp_files"]` to "0" for sql instance. Default value in
#             PostgreSQL is "-1" (i.e. disabled). See https://pgpedia.info/l/log_temp_files.html for more information.
#   - name: AVD-GCP-0016
#     link: https://avd.aquasec.com/misconfig/google/sql/avd-gcp-0016/
#     description: Ensure that logging of connections is enabled
#     severity: Medium
#     reason: Trivy suggests setting `settings.database_flags["log_connections"]` to "on" for sql instance.
#             Default value in PostgreSQL is "off" (i.e. disabled). By default, PostgreSQL only logs the errors
#             generated by unsuccessful connections. Setting this option to "on" will log all.
#             See https://pgpedia.info/l/log_connections.html for more information.
#   - name: AVD-GCP-0020
#     link: https://avd.aquasec.com/misconfig/google/sql/avd-gcp-0020/
#     description: Ensure that logging of lock waits is enabled.
#     severity: Medium
#     reason: Trivy suggests setting `settings.database_flags["log_lock_waits"]` to "on" for sql instance.
#             Default value in PostgreSQL is "off" (i.e. disabled). A configuration parameter determining whether a log
#             message is produced when a session waits longer than deadlock_timeout to acquire a lock.
#             See https://pgpedia.info/l/log_lock_waits.html for more information.
#   - name: AVD-GCP-0022
#     link: https://avd.aquasec.com/misconfig/google/sql/avd-gcp-0022/
#     description: Ensure that logging of disconnections is enabled.
#     severity: Medium
#     reason: Trivy suggests setting `settings.database_flags["log_disconnections"]` to "on" for sql instance.
#             Default value in PostgreSQL is "off" (i.e. disabled). Logging disconnections provides useful diagnostic
#             data such as session length, which can identify performance issues in an application and
#             potential DoS vectors. See https://pgpedia.info/l/log_connections.html for more information.
#   - name: AVD-GCP-0025
#     link: https://avd.aquasec.com/misconfig/google/sql/avd-gcp-0025/ 
#     description: Ensure that logging of checkpoints is enabled
#     severity: Medium
#     reason: Trivy suggests setting `settings.database_flags["log_checkpoints"]` to "on" for sql instance.
#             This is disabled in PostgreSQL 8.3 ~ PostgreSQL 14 and enabled by default since PostgreSQL 15.
#             Different projects use different versions so this check is disabled.
#             See https://pgpedia.info/l/log_checkpoints.html for more information.
trivy:
  stage: test
  image:
    name: aquasec/trivy:latest
    entrypoint: [""]
  variables:
    TRIVY_IGNORE: |-
      AVD-GCP-0014
      AVD-GCP-0016
      AVD-GCP-0017
      AVD-GCP-0020
      AVD-GCP-0022
      AVD-GCP-0025
      AVD-GCP-0029
      AVD-GCP-0066
  before_script: |
    mkdir ${TF_DATA_DIR}
    for i in $TRIVY_IGNORE; do echo $i >> .trivyignore; done
  script: |
    trivy fs --scanners misconfig --format json --output trivy.json --exit-code 1 .
  after_script: |
    trivy convert --format template --template "@/contrib/junit.tpl" --output ${TF_DATA_DIR}/${CI_COMMIT_REF_SLUG}-trivy.junit trivy.json
    trivy convert --format table --output trivy.out trivy.json && cat trivy.out
  rules:
    - if: $TRIVY_DISABLED
      when: never
    - !reference [.test-job-rules]
  tags:
    - $GKE_RUNNER_TAG
  allow_failure: true
  artifacts:
    expire_in: 1 week
    when: always
    reports:
      junit: ${TF_DATA_DIR}/${CI_COMMIT_REF_SLUG}-trivy.junit
  needs: []
