DEV Community

Cover image for Desplegar app en Okteto con Gitlab CI II
Daniel J. Saldaña
Daniel J. Saldaña

Posted on • Originally published at danieljsaldana.dev on

Desplegar app en Okteto con Gitlab CI II

En este tutorial nos enfocaremos en realizar un pequeño refactor y añadir unos nuevos jobs de cara al siguiente tutorial.

Aquí os dejo los objetivos que abordaremos:

  • Buildear con Kaniko y subir la imagen a Docker Hub.
  • Agregar GitGuardian para detectar contraseñas y token.
  • Analizar imagen con Trivy.
  • Analizaremos con Kube-linter los manifiestos de kubernetes.
  • Integrar Sonar para buscar vulnerabilidades.
  • Redefinir flujo de CI.

Como siempre aquí os dejo el repositorio que usaremos.

Daniel J. Saldaña / app-okteto · GitLab

Recordamos que el tutorial lo podrá encontrar en la rama main, ya que verá que actualmente existen más ramas, las cuales están enfocadas en los siguientes labs.

stages:
  - test
  - scanning
  - review
  - build
  - production

variables:
  IMAGE_GITGUARDIAN: gitguardian/ggshield:latest
  IMAGE_DOCKER: docker:stable
  IMAGE_KANIKO: gcr.io/kaniko-project/executor:v1.9.0-debug
  IMAGE_SONAR: sonarsource/sonar-scanner-cli:latest
  IMAGE_OKTETO: okteto/okteto:1.13.4
  IMAGE_HELM: alpine/helm

kubelinter:
  stage: test
  image: $IMAGE_DOCKER
  services:
    - docker:dind
  script:
    - docker run -v $PWD/charts:/dir -v $PWD/lint/config.yaml:/etc/config.yaml stackrox/kube-linter lint /dir --config /etc/config.yaml
  only:
    - branches
  except:
    - main

sonarcloud-check:
  stage: test
  image:
    name: $IMAGE_SONAR
  variables:
    SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar"
    GIT_DEPTH: "0"
  cache:
    key: "${CI_JOB_NAME}"
    paths:
      - .sonar/cache
  script:
    - sonar-scanner
  only:
    - branches
  except:
    - main

gitguardian:
  stage: scanning
  needs:
    - kubelinter
    - sonarcloud-check
  image:
    name: $IMAGE_GITGUARDIAN
  script:
    - ggshield secret scan ci
  only:
    - branches
  except:
    - main

deploy-review:
  stage: review
  image: $IMAGE_OKTETO
  needs: ["gitguardian"]
  variables:
    APP: $CI_COMMIT_REF_SLUG
    VA_ENV: review
  script:
    - okteto preview deploy $VA_ENV-$CI_COMMIT_REF_SLUG-$OKTETO_USERNAME --scope personal --branch $CI_COMMIT_REF_NAME --repository $CI_REPOSITORY_URL --wait
  environment:
    name: review/$CI_COMMIT_REF_SLUG
    url: https://${CI_PROJECT_TITLE}-${VA_ENV}-${CI_COMMIT_REF_SLUG}-${OKTETO_USERNAME}.cloud.okteto.net
    on_stop: stop-review
  only:
    - branches
  except:
    - main

stop-review:
  stage: review
  needs: ["deploy-review"]
  image: $IMAGE_OKTETO
  when: delayed
  start_in: 30 minutes
  variables:
    APP: $CI_COMMIT_REF_SLUG
    VA_ENV: review
  environment:
    name: review/$CI_COMMIT_REF_SLUG
    action: stop
  script:
    - okteto preview destroy $VA_ENV-$CI_COMMIT_REF_SLUG-$OKTETO_USERNAME
  only:
    - branches
  except:
    - main

build-docker:
  stage: build
  image: $IMAGE_DOCKER
  services:
    - docker:dind
  variables:
    REGISTRY_HOST: docker.io
    DOCKER_HUB_IMAGE: app-okteto
    REGISTRY_IMAGE: index.docker.io/danieljesussp/app-okteto
  script:
    - docker login -u "$DOCKER_HUB_USER" -p "$DOCKER_HUB_PASSWORD" $REGISTRY_HOST
    - >
      docker build
      --no-cache
      --tag $REGISTRY_IMAGE:$CI_COMMIT_SHA
      .
    - docker push $REGISTRY_IMAGE:$CI_COMMIT_SHA
  only:
    refs:
      - main

build-kaniko:
  stage: build
  image:
    name: $IMAGE_KANIKO
    entrypoint: [""]
  variables:
    DOCKER_HUB_REGISTRY: registry.gitlab.com
  script:
    - /kaniko/executor
      --context ${CI_PROJECT_DIR}
      --dockerfile ${CI_PROJECT_DIR}/Dockerfile
      --destination $DOCKER_HUB_REGISTRY/$CI_PROJECT_PATH:$CI_COMMIT_SHA
  only:
    refs:
      - main

container_scanning:
  image:
    name: docker.io/aquasec/trivy:latest
    entrypoint: [""]
  needs: ["build-kaniko"]
  stage: build
  variables:
    FULL_IMAGE_NAME: $DOCKER_HUB_REGISTRY/$CI_PROJECT_PATH:$CI_COMMIT_SHA
  script:
    - trivy --version
    - trivy image --clear-cache
    - trivy image --exit-code 0 --cache-dir .trivycache/ --no-progress --security-checks vuln "$FULL_IMAGE_NAME"
    - trivy image --exit-code 1 --cache-dir .trivycache/ --severity CRITICAL --no-progress --security-checks vuln "$FULL_IMAGE_NAME"
  cache:
    paths:
      - .trivycache/
  only:
    refs:
      - main

deploy-production:
  stage: production
  image:
    name: $IMAGE_HELM
    entrypoint: [""]
  needs: ["container_scanning"]
  variables:
    VA_ENV: production
  environment:
    name: production
    url: https://${CI_PROJECT_TITLE}-${OKTETO_USERNAME}.cloud.okteto.net
  script:
    - export KUBECONFIG=${ENV_KUBECONFIG}:${KUBECONFIG:-$HOME/.kube/config}
    # "Simple" hack to dynamically set
    - sed -i 's/_CI_PROJECT_TITLE/'"${CI_PROJECT_TITLE}"'/' "charts/templates/NOTES.txt"
    - sed -i 's/_VA_ENV/'""'/' "charts/templates/NOTES.txt"
    - sed -i 's/_CI_COMMIT_REF_SLUG/'""'/' "charts/templates/NOTES.txt"
    - sed -i 's/_OKTETO_USERNAME/'"-${OKTETO_USERNAME}"'/' "charts/templates/NOTES.txt"
    - helm upgrade $CI_PROJECT_NAME ./charts
      --values=./charts/values.yaml
      --install --atomic
  only:
    refs:
      - main

uninstall-production:
  stage: production
  needs: ["deploy-production"]
  image:
    name: $IMAGE_HELM
    entrypoint: [""]
  when: delayed
  start_in: 30 minutes
  environment:
    name: production
    url: https://${CI_PROJECT_TITLE}-production-$CI_COMMIT_REF_SLUG-$OKTETO_USERNAME.cloud.okteto.net
  script:
    - export KUBECONFIG=${ENV_KUBECONFIG}:${KUBECONFIG:-$HOME/.kube/config}
    - helm uninstall $CI_PROJECT_NAME
  only:
    refs:
      - main

Enter fullscreen mode Exit fullscreen mode

Vamos a explicar brevemente los cambios más relevantes que tendremos.

En primera instancia agregaremos a nuestro CI la herramienta KubeLinter. Esta solución me encanta y siempre que puedo trato de recomendarla a los distintos clientes con los que trabajo. Ya que nos permite analizar nuestros manifiestos de Kubernetes. Nos ofrece reglas de seguridad y es capaz que identifica los errores de configuración y programación en las implementaciones de Kubernetes.

kubelinter:
  stage: test
  image: $IMAGE_DOCKER
  services:
    - docker:dind
  script:
    - docker run -v $PWD/charts:/dir -v $PWD/lint/config.yaml:/etc/config.yaml stackrox/kube-linter lint /dir --config /etc/config.yaml
  only:
    - branches
  except:
    - main

Enter fullscreen mode Exit fullscreen mode

En el siguiente paso agregaremos SonarSource para analizar la calidad de nuestro código. Esta herramienta es totalmente gratuita si nuestro repositorio es gratuito, por lo que solo tendremos que crear nuestro proyecto en ella.

sonarcloud-check:
  stage: test
  image:
    name: $IMAGE_SONAR
  variables:
    SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar"
    GIT_DEPTH: "0"
  cache:
    key: "${CI_JOB_NAME}"
    paths:
      - .sonar/cache
  script:
    - sonar-scanner
  only:
    - branches
  except:
    - main

Enter fullscreen mode Exit fullscreen mode

Ahora ha llegado el momento de GitGuardian. Esta herramienta nos permitirá analizar nuestros commit en busca de contraseñas o token que puedan ocasionar una falla de seguridad. Si no conocéis os la recomiendo sin ninguna duda, incluye un plan gratuito.

gitguardian:
  stage: scanning
  needs:
    - kubelinter
    - sonarcloud-check
  image:
    name: $IMAGE_GITGUARDIAN
  script:
    - ggshield secret scan ci
  only:
    - branches
  except:
    - main

Enter fullscreen mode Exit fullscreen mode

En el siguiente paso, emplearemos Kaniko para buildear nuestra imagen y subirla a Docker Hub. Kaniko construye imágenes sin necesidad de un demonio Docker, haciendo el proceso de construcción más seguro. Cada capa de la imagen se construye en el espacio de usuario, así que no hay necesidad de disponer de privilegios de acceso para generar una imagen.

build-kaniko:
  stage: build
  image:
    name: $IMAGE_KANIKO
    entrypoint: [""]
  variables:
    DOCKER_HUB_REGISTRY: registry.gitlab.com
  script:
    - /kaniko/executor
      --context ${CI_PROJECT_DIR}
      --dockerfile ${CI_PROJECT_DIR}/Dockerfile
      --destination $DOCKER_HUB_REGISTRY/$CI_PROJECT_PATH:$CI_COMMIT_SHA
  only:
    refs:
      - main

Enter fullscreen mode Exit fullscreen mode

Como último paso, agregaremos Trivy es una herramienta Open Source para escanear imágenes de contenedores en busca de vulnerabilidades en los paquetes del sistema operativo y las dependencias de las aplicaciones.

container_scanning:
  image:
    name: docker.io/aquasec/trivy:latest
    entrypoint: [""]
  needs: ["build-kaniko"]
  stage: build
  variables:
    FULL_IMAGE_NAME: $DOCKER_HUB_REGISTRY/$CI_PROJECT_PATH:$CI_COMMIT_SHA
  script:
    - trivy --version
    - trivy image --clear-cache
    - trivy image --exit-code 0 --cache-dir .trivycache/ --no-progress --security-checks vuln "$FULL_IMAGE_NAME"
    - trivy image --exit-code 1 --cache-dir .trivycache/ --severity CRITICAL --no-progress --security-checks vuln "$FULL_IMAGE_NAME"
  cache:
    paths:
      - .trivycache/
  only:
    refs:
      - main

Enter fullscreen mode Exit fullscreen mode

¡Nos vemos en la tercera parte de este bloque de tutoriales!

次回まで

Top comments (0)