Comprensión del inventario para DevSecOps

En DevSecOps, su inventario actúa como una lista centralizada crítica de todos los bloques de construcción que componen su sistema de software. Se convierte en el único punto de información de todo lo que necesita para desarrollar, desplegar y mantener sus aplicaciones de forma segura en IBM Cloud. Esto es lo que normalmente se incluye en este inventario:

  • Recursos deIBM Cloud: incluye servidores virtuales, funciones sin servidor, bases de datos Cloudant y cualquier otro servicio que haya suministrado en el entorno de IBM Cloud.

  • Detalles de infraestructura como código (IaC): incluye configuraciones de Terraform, variables de entorno almacenadas en IBM® Cloud Foundry Artifactoryy otros valores que dictan cómo se configuran y protegen los recursos de IBM Cloud.

  • Dependencias de aplicación: Son servicios de terceros, API y microservicios en los que se basan las aplicaciones en la nube para funcionar de forma perfecta.

  • IBM® Key Protect for IBM Cloud® Secretos: hace referencia a información confidencial esencial para el funcionamiento del sistema, como contraseñas, claves de API y claves de cifrado. Estos requieren un control meticuloso y un almacenamiento seguro en IBM Key Protect.

Estructura y contenido de un inventario

El modelo de inventario realiza un seguimiento de los siguientes elementos del artefacto:

  • Nombre del artefacto
  • Entorno o región en la que se desplegará.
  • Ubicación de compilación de un artefacto (ejecución de conducto, confirmar sha)
  • Firma del artefacto creado

Realizar un seguimiento de las pruebas durante compilaciones y despliegues de artefactos. Esto también ayuda con la gestión de cambios y las auditorías de conformidad.

Ramas

El inventario se implementa en un repositorio Git (repo). Git es autosuficiente en el seguimiento y auditoría de cambios.

Las ramas se utilizan como entornos. La rama principal (master) la ha escrito y actualizado la interconexión de integración continua. Se actualizan otros entornos a partir de la rama maestra utilizando promociones. Para obtener más información sobre las promociones, consulte la sección Promoción.

Contenido de inventario

El inventario contiene una entrada de inventario para cada artefacto que participa en el despliegue. Una entrada de inventario apunta a un solo artefacto. Las entradas de inventario son archivos JSON que se pueden estructurar en carpetas y cuyo nombre utiliza el nombre de la entrada.

Las carpetas de inventario forman parte del nombre de la entrada.

Ejemplo

Elija un nombre de la siguiente lista de nombres de entrada como nombre de servicio:

  • auth/service
  • auth/db
  • ui/service
  • main_service
  • helm-charts/main_service

El contenido se implementa en el inventario utilizando la siguiente estructura:

/
├── auth
│   ├── service
│   └── db
├── ui
│   └── service
├── helm-charts
│   └── main_service
└ main_service

Formato de entrada del inventario

Aunque el tipo Entry representa el esquema de la entrada de inventario utilizando la sintaxis de tipografía, puede convertirlo para que se utilice el esquema JSON.

interface Entry {
  repository_url: string;
  artifact: string;
  build_number: number;
  commit_sha: string;
  name: string;
  pipeline_run_id: string;
  version: string;

  app_artifacts: {
    signature: string;
    provenance: string;

    [key: string]: any;
  }

  type: string;
  sha256: string;
  provenance: string;
  signature: string;
}

Ejemplo

Entrada de inventario para el tipo de imagen de activo

{
  "repository_url": "https://github.com/test-org/compliance-app-20201211", # source code repository url of the image artifact
  "artifact": "us.icr.io/namespace/hello-compliance-app:20201217081811-master-b85e3d472e9cc35b429c39e8c3f9eb282738c20a@sha256:da36831d5154307ac9ca4b8d900df2da0c6c14754977c32479dc62994b5722d0", # image artifact name, should be in a format like <static_name>:<version>@sha256:<sha256> OR <static_name>@sha256:<sha256>
  "build_number": 21, # pipeline build number
  "commit_sha": "b85e3d472e9cc35b429c39e8c3f9eb282738c20a",  # should be a proper git commit sha
  "name": "hello-compliance-app", # name of the inventory entry file name
  "pipeline_run_id": "f21321bf-9054-4bf3-80a8-4fb34743b7d9", # pipeline run id where artifact was built
  "version": "v1",  # version of the artifact
  "app_artifacts": {}, # any additional information can be stored here
  "type": "image",
  "sha256": "sha256:da36831d5154307ac9ca4b8d900df2da0c6c14754977c32479dc62994b5722d0",
  "provenance": "us.icr.io/namespace/hello-compliance-app:20201217081811-master-b85e3d472e9cc35b429c39e8c3f9eb282738c20a@sha256:da36831d5154307ac9ca4b8d900df2da0c6c14754977c32479dc62994b5722d0", # The fully qualified URL where artifact is stored, in case of image artifact, it is same as the artifact field
  "signature": "owFNUX1IE3EY3vwAEy0VyoSJdkVWtu0+d3eTjNIIi0jETCSU3353cz+83V23myi2BlFgYiUFqSmZLciUzCJkRYJp9IEWFWXB0hAyrBQxEjIIuhFSf70vL8/7vM/zPi3JsaYEc+TnbqG8qrnTPDZ8w2WqiqwtacCghnQEgYQ5GzAkiLKO9PpoLyiwRtSsmugWNVGGIubE/D4bgpoNKXag60gCdo8oSYoVKl5VQsDAWIGqOkmcxAmSYHGO4AjC6gU+3eBxcYxICTRLijyEFOOiSR5SvMhBys2LLpIjWYqDJA6wwHYMeUG1+J8GL5CRW/TpVgFVG8VQ4vMAknE4BUA5OIoQGIKhKZwFkIeAdnECj+OCmxQADh2QoFmG5lkWUiTN8gJ0kDxPuxiWJAU8ekyvV6PegK54EcyGiqwDJItatg9Vy0D3a2IUpKg6UuS/T4KaaIC1fzuMDbfhmMGEvIY64FUxJ+Ew3PMU5SADgdNmKs5kTjBlrtsQ99iyY49nns8o6jsXWgkjPiYahClxVcrK5Flngumz2j7YdmD0ecutytsvxxNPHflKlRV2RyqD69NjC6Smji9XuukFyZ+lvM18gUr7F4NXge9YyZPik411tc1n9bKO/hDz7oGaX/ur94OnNHiwOG6n5ZsrsCsvtyvmkH4zOWlrRWuL7fzgj9zlcCTAhtu2LbeGLNfv3Ju0Jc9PZPk7Pm3Ov2CW+2xj8ReX6ooGamZ610yqRM/+8Qo2XnOeyZzbVKgs+f2+9unpJOve4Tmla+PdqftDWkHPm9Vq3nsyZ2DUkmP/nTb7qNw5l2SfWtiSemJx9nLaYOpx6amlOT18aeIwJQhHg1XOjJF9r18NXQvPuL9rH5tSQqbGhyN/AA=="  # The signature of the artifact
}

Entrada de inventario para el tipo de activo no de imagen, como despliegue, diagramas de Helm

{
  "repository_url": "https://github.com/test-org/compliance-app-20201211",  # source code repository url of the artifact
  "artifact": "deployment.yaml", # artifact name, must be contant every build
  "build_number": 21, # pipeline build number
  "commit_sha": "b85e3d472e9cc35b429c39e8c3f9eb282738c20a", # must be a proper git commit sha
  "name": "hello-compliance-app-deployment", # name of the inventory entry file name
  "pipeline_run_id": "f21321bf-9054-4bf3-80a8-4fb34743b7d9", # pipeline run id where artifact was built
  "version": "v1", # version of the artifact
  "app_artifacts": {}, # any additional information can be stored here
  "type": "deployment", # type of the artifact
  "sha256": "sha256:da36831d5154307ac9ca4b8d900df2da0c6c14754977c32479dc62994b5722d0",  # sha256 of the artifact
  "provenance": "https://raw.github.ibm.com/org/my-app/commit-1/deployment.yaml", # The fully qualified URL where artifact is stored
  "signature": "owFNUX1IE3EY3vwAEy0VyoSJdkVWtu0+d3eTjNIIi0jETCSU3353cz+83V23myi2BlFgYiUFqSmZLciUzCJkRYJp9IEWFWXB0hAyrBQxEjIIuhFSf70vL8/7vM/zPi3JsaYEc+TnbqG8qrnTPDZ8w2WqiqwtacCghnQEgYQ5GzAkiLKO9PpoLyiwRtSsmugWNVGGIubE/D4bgpoNKXag60gCdo8oSYoVKl5VQsDAWIGqOkmcxAmSYHGO4AjC6gU+3eBxcYxICTRLijyEFOOiSR5SvMhBys2LLpIjWYqDJA6wwHYMeUG1+J8GL5CRW/TpVgFVG8VQ4vMAknE4BUA5OIoQGIKhKZwFkIeAdnECj+OCmxQADh2QoFmG5lkWUiTN8gJ0kDxPuxiWJAU8ekyvV6PegK54EcyGiqwDJItatg9Vy0D3a2IUpKg6UuS/T4KaaIC1fzuMDbfhmMGEvIY64FUxJ+Ew3PMU5SADgdNmKs5kTjBlrtsQ99iyY49nns8o6jsXWgkjPiYahClxVcrK5Flngumz2j7YdmD0ecutytsvxxNPHflKlRV2RyqD69NjC6Smji9XuukFyZ+lvM18gUr7F4NXge9YyZPik411tc1n9bKO/hDz7oGaX/ur94OnNHiwOG6n5ZsrsCsvtyvmkH4zOWlrRWuL7fzgj9zlcCTAhtu2LbeGLNfv3Ju0Jc9PZPk7Pm3Ov2CW+2xj8ReX6ooGamZ610yqRM/+8Qo2XnOeyZzbVKgs+f2+9unpJOve4Tmla+PdqftDWkHPm9Vq3nsyZ2DUkmP/nTb7qNw5l2SfWtiSemJx9nLaYOpx6amlOT18aeIwJQhHg1XOjJF9r18NXQvPuL9rH5tSQqbGhyN/AA=="  # The signature of the artifact
}

Utilice el mandato cacao inventory add para escribir en el inventario.

Flujo de trabajo

El inventario contiene varias ramas distintas a la rama master. Estas ramas pueden representar etapas de despliegue, entornos o regiones, o una mezcla de ambos. La estructura de estas ramas depende de la configuración y del uso.

La integración continua graba en el inventario

La rama master se llena a partir de compilaciones de integración continua. La última confirmación en el destino (en este caso denominada staging) contiene una etiqueta que muestra que fue el último despliegue concluido.

Si la rama predeterminada para el inventario se conmuta a una rama diferente, debe cambiar la base de las confirmaciones de la rama predeterminada anterior a la nueva rama predeterminada para que el historial de confirmaciones Git sea lineal.

Puede omitir la escritura en el inventario personalizando el script de release. Para obtener más información, consulte Publicar en inventario.

Integración continua escribe en inventario
' Integración continua escribe en inventario

Promoción

Se crea una solicitud de extracción cuando se promociona a una rama de destino. El contenido de la solicitud de extracción rellena los campos de Solicitud de cambio. Después de revisar la solicitud de extracción, puede fusionarla.

Promover una rama objetivo utilizando un PR
Promover una rama objetivo utilizando un PR

Delta y despliegue

Una vez que se ha fusionado la solicitud de extracción de promoción, puede iniciarse la interconexión de despliegue. El delta de despliegue es la diferencia entre el contenido del último despliegue finalizado y del despliegue actual. El delta de despliegue genera una lista de los artículos de inventario que se están desplegando.

Flujo de conducto de despliegue que muestra detalles de delta de despliegue
Figura 3. Flujo de conducto de despliegue que muestra detalles delta de despliegue

Conclusión de inventario

Cuando finalice el despliegue, podrá mover la etiqueta latest.

Durante el desencadenante de modalidad de desarrollo, las etiquetas no se avanzarán. La finalidad del desencadenante de modalidad de desarrollo es únicamente probar la interconexión de CD.

'

Despliegue completado
Despliegue completado

Promocionar a otros entornos

Puede promocionar y desplegar de una rama a cualquier otra.

Promoción utilizando un PR de la rama staging a la rama prod
Promoción utilizando un PR de la rama staging a la rama prod

Entorno de inventario

El estado desplegado actual contiene el contenido que se va a desplegar en un entorno. Cada confirmación promovida en la rama de destino contiene el ID de ejecución del pipeline y el ID de solicitud de cambio como etiqueta. Algunas confirmaciones pueden tener varias etiquetas, por ejemplo, cuando se vuelve a intentar un despliegue fallido o se vuelve a desplegar. El inventario contiene cada fragmento de información para reproducir los despliegues.

Diagrama de flujo de despliegue con etiquetas
Diagrama de flujo de despliegue con etiquetas

Utilización de etiquetas

La siguiente tabla muestra las etiquetas de inventario disponibles.

Etiquetas de inventario
Etiqueta Descripción
latest Etiqueta el estado actual, desplegado correctamente y concluido del inventario en una rama.
pipeline run id Etiqueta el estado de inventario actual en la rama, con el ID de ejecución de interconexión o el número de compilación del despliegue real. Para evitar el solapamiento de contenido de inventario cuando se desencadenan despliegues en paralelo, utilice esta etiqueta para hacer referencia al hash de punto de inventario real en el historial de ramas.
change request id (opcional) Etiqueta el estado actual de un ID de solicitud de cambio para realizar un seguimiento de los ID de solicitud de cambio en el inventario, en una representación histórica.

Configuración para un único destino con varias regiones

Se introducen varias etiquetas latest para un único entorno de destino, de modo que varias canalizaciones de despliegue continuo puedan funcionar en el mismo destino, para distintos tipos de casos de uso. Puede utilizar, por ejemplo, el mismo entorno de destino (como us-south o eu-de) para varias regiones en el entorno de destino de producción y la rama de inventario.

No es necesario configurar una rama diferente para cada región utilizando la propiedad region, como us-south-prod y eu-de-prod, y ejecutar la promoción de forma redundante. En su lugar, especifique estos destinos adicionales para la misma rama de inventario y, a continuación, utilícelas como etiquetas Git.

En esta configuración, la rama prod tiene varias etiquetas latest en la misma rama, como us-south_prod_latest y eu-de_prod_latest. Cada canal de despliegue continuo responsable de cada región puede utilizar esas etiquetas para el despliegue.

Rama de producción con varias etiquetas más recientes por región
Rama de producción con varias etiquetas más recientes por región

Por ejemplo, un conjunto de cambios que usted planea desplegar en todas partes podría ser lanzado a una sola región en primer lugar, y luego desplegado gradualmente a otras regiones mediante el uso de tuberías de despliegue continuo para apuntar a esas regiones.

Operaciones de inventario

El inventario contiene algunas operaciones básicas que se ejecutan utilizando la CLI o utilizando Git puro y la CLI de GitHub.

mandatos de CLI

  1. Cree una solicitud de extracción de promoción de maestro a la rama de destino en transferencia.

    cocoa inventory promote \
      --source="master" \
      --target="staging" \
      --priority="moderate" \
      --assigned-to="assignee@ibm.com" \
      --description="Change description" \
      --purpose="Change purpose" \
      --impact="Change impact" \
      --backout-plan="Details on backout and rollback")
    
  2. Concluya un despliegue moviendo la etiqueta target_latest a la misma confirmación que la etiqueta pipeline-run-id.

    cocoa inventory label move \
      --to-label="${PIPELINE_RUN_ID}" \
      "target_latest"
    

CLI de Git y GitHub

  1. Cree una solicitud de extracción de promoción de maestro a la rama de destino en transferencia.

    promote() {
    
      if [ -z $1 ] || [ -z $2 ]; then
        echo "Missing source and target"
        exit 1
      fi
    
      local source="$1"
      local target="$2"
    
      if ! git show-ref "refs/remotes/origin/$target"; then
        # Create a new target branch, from the beginning of master
        git checkout master
        git checkout -b "$target" $(git rev-list --max-parents=0 HEAD)
        git_push
      fi
    
      git checkout "$source"
      git pull --rebase
    
      # Create a promotion branch for the PR
      # this can be discarded after the Promotion PR merge
      git checkout -b "promote-$source-to-$target"
      git push --set-upstream origin "promote-$source-to-$target"
    
      # Create PR from promotion branch to target branch
      gh pr create \
        --base "$target" \
        --head "promote-$source-to-$target" \
        --title "Promote $source to $target" \
        --body "" \
        --repo "https://github.com/org/inventory-repository"
    
      # promotion branch can be deleted once the PR was merged
    }
    
    $ promote master staging
    
  2. Concluya un despliegue moviendo la etiqueta target-latest a la misma confirmación que la etiqueta pipeline-run-id.

    conclude () {
      local target="$1"
      local tag="$2"
    
      latest="$1-latest"
    
      # remove the latest tag
      git push origin ":refs/tags/$latest"
      # find the commit hash of the target tag
      sha=$(git rev-list -n 1 $tag)
    
      # add the latest tag to the same commit of the target tag
      git tag -fa "$latest" -m "" $sha
      git push --tags --force
    }
    
    $ conclude staging pipeline-run-fe33b05c
    
  3. Se revierte la transferencia a un estado anterior utilizando la CLI de Git y GitHub.

    revert () {
      local branch="$1"
      local commit="$2"
    
      # create a revert branch from the target branch
      git checkout "$branch"
      git pull --rebase
      git checkout -b "$branch-revert"
    
      # revert commits since the target commit, then commit and push
      git revert -n $(git rev-list --no-merges HEAD...$commit)
      git commit -m "revert $branch to $commit"
      git push --set-upstream origin "$branch-revert"
    
      # create PR from revert branch to the target branch
      gh pr create \
        --base "$branch" \
        --head "$branch-revert" \
        --title "Revert $branch to $commit" \
        --body "" \
        --repo "$REPO"
    
      # revert branch can be deleted once the PR was merged
    }
    
    $ revert staging ba3b8e5ed3320e6b4981077e1a1627f08de4f511
    

Casos de uso común para trabajar con repositorios de Git

Para obtener más información sobre cómo trabajar con repositorios de Git, consulte estos casos de ejemplo:

Cómo excluir archivos y directorios en el inventario

One-Pipeline excluye archivos ocultos y archivos .md en el inventario de forma predeterminada. Cree un archivo denominado .inventoryignore en el repositorio de inventario para excluir los archivos o directorios. La interconexión busca el archivo .inventoryignore en la raíz del repositorio.

Sin embargo, si prefiere un nombre diferente para el archivo de exclusión de inventario, puede especificarlo estableciendo la clave inventory-ignore-file como una propiedad de entorno dentro de su canalización. Asegúrese de que este archivo esté en la raíz del repositorio de inventario.

Por ejemplo, si el archivo se denomina .custominventoryignore, añada una variable de entorno inventory-ignore-file con el valor custominventoryignore.

A continuación se muestra el contenido de ejemplo del archivo .custominventoryignore en dos formatos:

.md
sample_file
sample_directory/
# Ignore everything
**

# But keep these artifacts
!sample_directory/
!sample_file

A continuación se explica la finalidad de las entradas del archivo de ejemplo .custominventoryignore:

  • .md: Excluye todos los archivos con la extensión .md. No añada * al principio, como *.md, ya que no se admite regex.
  • sample_file: Excluye el fichero específico en todo el repositorio.
  • sample_directory/: Excluye todo el directorio. Evite añadir * al final, utilice sample_directory/*, ya que no se admite regex.
  • Un archivo sin entradas o una línea vacía hará que se excluyan todos los archivos. Por favor, no deje entradas o líneas vacías en el archivo de ignorar inventario.
  • **: Ignora todo lo que hay en el repositorio.
  • !sample_directory/ y !sample_file: Anula la regla de ignorar, manteniendo estos archivos o directorios específicos incluso si ** está presente.