Comprensione dell'inventario per DevSecOps

In DevSecOps, l'inventario funge da elenco critico centralizzato di tutti gli elementi che compongono il sistema software. Diventa l'unico punto di informazione di cui hai bisogno per sviluppare, distribuire e gestire le tue applicazioni in modo sicuro su IBM Cloud. Ecco cosa viene incluso in questo inventario:

  • IBM Cloud risorse: include i server virtuali, le funzioni senza server, i database Cloudant e tutti gli altri servizi di cui hai eseguito il provisioning nel tuo ambiente IBM Cloud.

  • Dettagli dell'infrastruttura come codice (IaC): questo include le configurazioni Terraform, le variabili di ambiente memorizzate in IBM® Cloud Foundry Artifactorye altre impostazioni che indicano come le tue risorse IBM Cloud sono configurate e protette.

  • Dipendenze applicazione: si tratta di servizi di terzi, API e microservizi su cui si basano le tue applicazioni cloud per funzionare in modo impeccabile.

  • IBM® Key Protect for IBM Cloud® Segreti: si riferisce alle informazioni sensibili essenziali per il funzionamento del sistema, come password, chiavi API e chiavi di crittografia. Questi richiedono un controllo meticoloso e un'archiviazione protetta in IBM Key Protect.

Struttura e contenuto di un inventario

Il modello di inventario tiene traccia dei seguenti elementi della risorsa utente:

  • Nome della risorsa utente
  • Ambiente o regione in cui verrà distribuito.
  • Percorso build di una risorsa utente (esecuzione pipeline, commit sha)
  • Firma della risorsa utente creata

Tenere traccia delle prove durante le build e le distribuzioni delle risorse utente. Ciò aiuta anche con la gestione delle modifiche e i controlli di conformità.

Rami

L'inventario è implementato in un repository (repo) Git. Git è autosufficiente nella traccia e nel controllo delle modifiche.

I rami vengono utilizzati come ambienti. Il ramo principale (master) viene scritto e aggiornato dalla pipeline di integrazione continua. Altri ambienti vengono aggiornati dal ramo principale utilizzando le promozioni. Per ulteriori informazioni sulle promozioni, consultare la sezione Promozione.

Contenuto inventario

L'inventario contiene una voce di inventario per ogni risorsa utente che partecipa alla distribuzione. Una voce di inventario punta a una singola risorsa utente. Le voci di inventario sono file JSON che è possibile strutturare in cartelle e che vengono denominati utilizzando il nome della voce.

Le cartelle di inventario fanno parte del nome della voce.

Esempio

Scegliere un nome dal seguente elenco di nomi di voci come nome servizio:

  • aut/servizio
  • aut/db
  • ui/servizio
  • servizio principale
  • helm - charts/main_service

Il contenuto viene implementato nell'inventario utilizzando la seguente struttura:

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

Formato voce inventario

Sebbene il tipo Entry rappresenti lo schema della voce di inventario utilizzando la sintassi typescript, è possibile convertirlo in uno schema 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;
}

Esempio

Voce di inventario per il tipo di immagine dell'asset

{
  "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
}

Voce di inventario per il tipo di asset non immagine, come i grafici helm e di distribuzione

{
  "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
}

Utilizzare il comando cacao inventory add per scrivere nell'inventario.

Flusso di lavoro inventario

L'inventario contiene diversi rami diversi dal ramo master. Questi rami possono rappresentare fasi di distribuzione, ambienti o regioni o una combinazione di entrambi. La struttura di questi rami dipende dalla configurazione e dall'utilizzo.

Scritture CI nell'inventario

Il ramo master è popolato da build di integrazione continua. L'ultimo commit nella destinazione (in questo caso denominato staging) contiene una tag che mostra che si è trattato dell'ultima distribuzione conclusa.

Se il ramo predefinito per l'inventario è commutato in un altro ramo, è necessario modificare i commit dal ramo predefinito precedente nel nuovo ramo predefinito per rendere lineare la cronologia di commit Git.

È possibile saltare la scrittura nell'inventario personalizzando lo script di rilascio. Per ulteriori informazioni, consultare Release to inventory.

'integrazione continua scrive nell'inventario
'integrazione continua scrive nell'inventario

Promozione

Una richiesta di pull viene creata quando si verifica la promozione a un ramo di destinazione. Il contenuto della richiesta di pull popola i campi della richiesta di modifica. Una volta revisionata la richiesta di pull, è possibile unirla.

Promozione di un ramo di destinazione tramite una PR
Promozione di un ramo di destinazione tramite una PR

Delta e distribuzione

Una volta unita la richiesta di pull della promozione, è possibile avviare la pipeline di distribuzione. Il delta di distribuzione è la differenza tra il contenuto dell'ultima distribuzione conclusa e la distribuzione corrente. Il delta di distribuzione elenca gli elementi dell'inventario che vengono distribuiti.

Flusso della pipeline di distribuzione che mostra i dettagli delta di distribuzione
Figura 3. Flusso pipeline di distribuzione che mostra dettagli delta di distribuzione

Conclusione inventario

Al termine della distribuzione, è possibile spostare la tag latest in avanti.

Durante il trigger della modalità di sviluppo, i tag non saranno avanzati. Lo scopo del trigger della modalità di sviluppo è solo per testare la pipeline CD.

L'implementazione completa
L'implementazione completa

Promuovi ad altri ambienti

È possibile promuovere e distribuire da qualsiasi ramo a un altro.

Promozione che utilizza una PR da staging a prod branch
Promozione che utilizza una PR da staging a prod branch

Gruppo di inventario

Lo stato distribuito corrente contiene il contenuto da distribuire a un ambiente. Ogni commit promosso nel ramo di destinazione contiene l'ID di esecuzione della pipeline pertinente e l'ID richiesta di modifica come tag. Alcuni commit possono avere più tag, ad esempio, quando si tenta nuovamente una distribuzione o una distribuzione non riuscita. L'inventario contiene tutte le informazioni per ripetere le distribuzioni.

Diagramma del flusso di distribuzione con i tag
Diagramma del flusso di distribuzione con i tag

Uso dei tag

La tabella seguente mostra le etichette d'inventario disponibili.

Etichette dell'inventario
Tag Descrizione
latest Contrassegnare lo stato corrente, correttamente distribuito e concluso dell'inventario su un ramo.
pipeline run id Contrassegna lo stato dell'inventario corrente nel ramo, con l'ID di esecuzione della pipeline o il numero di build della distribuzione effettiva. Per evitare la sovrapposizione del contenuto dell'inventario quando vengono attivate le distribuzioni parallele, utilizzare questa tag per fare riferimento all'hash del punto di inventario effettivo nella cronologia del ramo.
change request id (facoltativo) Contrassegna lo stato corrente di un ID della richiesta di modifica per tracciare gli ID della richiesta di modifica nell'inventario, in una rappresentazione cronologica.

Configurazione per una singola destinazione con più regioni

Sono state introdotte più tag latest per un singolo ambiente di destinazione in modo che più pipeline di distribuzione continua possano funzionare sulla stessa destinazione, per diversi tipi di casi di utilizzo. È possibile utilizzare, ad esempio, lo stesso ambiente di destinazione (come us-south o eu-de) per più regioni nell'ambiente di destinazione della produzione e nel ramo di inventario.

Non è necessario configurare un ramo differente per ogni regione utilizzando la proprietà region, come us-south-prod e eu-de-prod, ed eseguire la promozione in modo ridondante. Specificare invece queste destinazioni aggiuntive per lo stesso ramo di inventario e utilizzarle come tag Git.

In questa configurazione, il ramo prod ha più tag latest sullo stesso ramo, come us-south_prod_latest e eu-de_prod_latest. Ogni pipeline di distribuzione continua responsabile per ogni regione può utilizzare tali tag per la distribuzione.

Filiale di produzione con più tag più recenti per regione
Filiale di produzione con più tag più recenti per regione

Ad esempio, una serie di modifiche che prevedi di distribuire ovunque potrebbe essere rilasciata prima in una singola regione e poi gradualmente distribuita ad altre regioni utilizzando le pipeline di distribuzione continua come destinazione per tali regioni.

Operazioni di inventario

L'inventario contiene alcune operazioni di base che vengono eseguite utilizzando la CLI o Git puro e la CLI GitHub.

Comandi della CLI

  1. Creare una richiesta di pull della promozione dal master al ramo di destinazione in fase di preparazione.

    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. Concludere una distribuzione spostando la tag target_latest nello stesso commit della tag pipeline-run-id.

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

Git e la CLI GitHub

  1. Creare una richiesta di pull della promozione dal master al ramo di destinazione in fase di preparazione.

    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. Concludere una distribuzione spostando la tag target-latest nello stesso commit della tag 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. Ripristina la preparazione a uno stato precedente utilizzando Git e la CLI 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
    

Casi di utilizzo comuni per l'utilizzo dei repository Git

Per ulteriori informazioni sull'utilizzo dei repository Git, vedi questi scenari di esempio:

Come escludere file e directory nell'inventario

Uno - Pipeline esclude i file nascosti e i file .md nell'inventario per default. Creare un file denominato .inventoryignore nel repository di inventario per escludere eventuali file o directory. La pipeline ricerca il file .inventoryignore nella root del repository.

Tuttavia, se si preferisce un nome diverso per il file di esclusione dell'inventario, è possibile specificarlo impostando la chiave inventory-ignore-file come proprietà dell'ambiente nella pipeline. Assicurarsi che questo file si trova nella root del repository di inventario.

Ad esempio, se il file è denominato .custominventoryignore, aggiungere una variabile di ambiente inventory-ignore-file con il valore custominventoryignore.

Di seguito è riportato un esempio di contenuto per il file .custominventoryignore in due formati:

.md
sample_file
sample_directory/
# Ignore everything
**

# But keep these artifacts
!sample_directory/
!sample_file

Di seguito viene spiegato lo scopo delle voci del file di esempio .custominventoryignore:

  • .md: Esclude tutti i file con estensione .md. Non aggiungere * all'inizio, come *.md, poiché la regex non è supportata.
  • sample_file: Esclude il file specifico in tutto il repository.
  • sample_directory/: Esclude l'intera directory. Evitare di aggiungere * alla fine, utilizzare sample_directory/*, poiché la regex non è supportata.
  • Se un file non contiene voci o una riga vuota, tutti i file vengono esclusi. Non lasciare voci o righe vuote nel file di ignoranza dell'inventario.
  • **: Ignora tutto ciò che è presente nel repository.
  • !sample_directory/ e !sample_file: nega la regola di ignoranza, mantenendo questi file o directory specifici anche se ** è presente.