Entendendo o inventário para DevSecOps
Em DevSecOps, seu inventário funciona como uma lista centralizada e crítica de todos os blocos de construção que compõem seu sistema de software. Ele se torna o ponto único de informações para tudo que você precisa para desenvolver, implementar e manter seus aplicativos com segurança no IBM Cloud. Aqui está o que normalmente é incluído neste inventário:
-
IBM Cloud recursos: isso inclui servidores virtuais, funções sem servidor, bancos de dados Cloudant e quaisquer outros serviços que você provisionou em seu ambiente do IBM Cloud.
-
Detalhes da infraestrutura como código (IaC): isso inclui configurações do Terraform, variáveis de ambiente armazenadas em IBM® Cloud Foundry Artifactorye outras configurações que determinam como seus recursos do IBM Cloud são configurados e protegidos.
-
Dependências do Aplicativo: elas são serviços de terceiros, APIs e microsserviços nos quais seus aplicativos em nuvem dependem para funcionar perfeitamente
-
IBM® Key Protect for IBM Cloud® Segredos: Refere-se a informações confidenciais essenciais para a operação do sistema, como senhas, chaves API e chaves de criptografia. Eles requerem controle meticuloso e armazenamento seguro no IBM Key Protect.
Estrutura e conteúdo de um inventário
O modelo de inventário rastreia os seguintes itens do artefato:
- Nome do artefato
- Ambiente ou região em que ele será implementado.
- Local de construção de um artefato (execução de pipeline, confirmação sha)
- Assinatura do artefato construído
Controle a evidência durante construções e implementações de artefatos. Isso também ajuda com o gerenciamento de mudanças e auditorias de conformidade.
Ramificações
O inventário é implementado em um repositório Git (repo). Git é autossuficiente no rastreamento e auditoria de mudanças.
As ramificações são usadas como ambientes. A ramificação principal (master) é gravada e atualizada pelo pipeline de integração contínua. Outros ambientes são atualizados a partir da ramificação principal, por meio de promoções.
Para obter mais informações sobre promoções, consulte a seção Promoção .
Conteúdo do inventário
O inventário contém uma entrada de inventário para cada artefato participante da implementação. Uma entrada de inventário aponta para um único artefato. As entradas de inventário são arquivos JSON que podem ser estruturados em pastas e são nomeados de acordo com o nome da entrada.
As pastas do inventário fazem parte do nome de entrada.
Exemplo
Escolha um nome na lista a seguir de nomes de entrada como um nome de serviço:.
- auth/service
- auth/db
- ui/service
- main_service
- helm-charts/main_service
O conteúdo é implementado no inventário utilizando a seguinte estrutura:
/
├── auth
│ ├── service
│ └── db
├── ui
│ └── service
├── helm-charts
│ └── main_service
└ main_service
Formato de entrada de inventário
Embora o tipo Entry represente o esquema da entrada de inventário usando a sintaxe typescript, é possível fazer uma conversão para que passe a usar o 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;
}
Exemplo
Entrada de inventário para o tipo de imagem de ativo..
{
"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 inventário para o tipo não de imagem de ativo, como implementação, gráficos do 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
}
Use o comando cocoa inventory add para gravar no inventário..
Fluxo de trabalho de inventário
O inventário contém várias ramificações, além da ramificação master. Essas ramificações podem representar estágios, ambientes ou regiões de implementação ou uma combinação desses itens. A estrutura dessas ramificações depende configuração
e do uso.
Gravações de integração contínua no inventário
A ramificação master é preenchida a partir de construções de integração contínua. O último commit no destino (neste caso chamado staging) contém uma tag que mostra que esta foi a última implementação concluída.
Se a ramificação padrão para o inventário for alternada para uma ramificação diferente, será necessário rebasear as confirmações da ramificação padrão anterior na nova ramificação padrão para tornar o histórico de confirmação do Git linear
Você pode pular a escrita para o inventário customizando o script de liberação. Para obter mais informações, consulte Release para o inventário.
Promoção
Uma solicitação pull é criada ao fazer uma promoção para uma ramificação de destino. O conteúdo da solicitação pull preenche os campos da solicitação de mudança. Após a revisão da solicitação pull, é possível mesclá-la.
Delta e implementação
Após a mesclagem da solicitação pull da promoção, é possível iniciar o pipeline de implementação. O delta de implementação é a diferença entre o conteúdo da última implementação concluída e da implementação atual. O delta de implementação lista os itens de inventário que estão sendo implementados.
Conclusão do inventário
Após a conclusão da implementação, é possível mover a tag latest para frente.
Durante o acionador do modo dev, as tags não serão avançadas. O propósito do acionador do modo dev é apenas para testar o pipeline de CD.
Promoção para outros ambientes
As promoções e implementações podem ser feitas entre quaisquer ramificações.
Cenário de inventário
O estado de implementação atual contém o conteúdo a ser implementado em um ambiente. Cada commit promovido na ramificação de destino contém o ID de execução do pipeline e o ID da solicitação de alteração relevantes como uma tag. Há situações em que alguns commits podem ter várias tags, por exemplo, ao fazer uma nova tentativa para executar uma implementação que falhou ou ao implementar novamente. No inventário, são mantidas todas as informações necessárias para reproduzir as implementações.
Configuração para um destino único com várias regiões
Várias tags latest são introduzidas para um único ambiente de destino, de modo que vários pipelines de implantação contínua possam funcionar no mesmo destino, para diferentes tipos de casos de uso. É possível usar, por exemplo,
o mesmo ambiente de destino (como us-south ou eu-de) para várias regiões no ambiente de destino de produção e na ramificação de inventário.
Não é necessário configurar uma filial diferente para cada região usando a propriedade region, como us-south-prod e eu-de-prod, e executar a promoção de forma redundante. Em vez disso, especifique esses
destinos adicionais para a mesma ramificação do inventário e, em seguida, utilize-os como tags Git.
Nessa configuração, a filial prod tem várias tags latest na mesma filial, como us-south_prod_latest e eu-de_prod_latest. Cada pipeline de implantação contínua que é responsável por cada região pode usar
essas tags para implantar.
Por exemplo, um conjunto de alterações que você planeja implantar em todos os lugares pode ser lançado primeiro em uma única região e, em seguida, implantado gradualmente em outras regiões usando pipelines de implantação contínua para atingir essas regiões.
Operações do inventário
No inventário há algumas operações básicas que são executadas por meio da CLI ou simplesmente utilizando Git e a CLI do GitHub.
Comandos de CLI
-
Criar uma solicitação pull de promoção a partir da ramificação principal para a ramificação de destino no ambiente de preparação.
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") -
Para concluir uma implementação, mova a tag
target_latestpara o mesmo commit que a tagpipeline-run-id.cocoa inventory label move \ --to-label="${PIPELINE_RUN_ID}" \ "target_latest"
Git e CLI do GitHub
-
Criar uma solicitação pull de promoção a partir da ramificação principal para a ramificação de destino no ambiente de preparação.
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 -
Para concluir uma implementação, mova a tag
target-latestpara o mesmo commit que a tagpipeline-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 -
Reverter a preparação para um estado anterior, usando Git e a CLI do 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 comum para trabalhar com repositórios Git
Para obter mais informações sobre como trabalhar com repositórios Git, veja estes cenários de exemplo:
Como Excluir Arquivos e Diretórios no Inventário
Um pipeline exclui arquivos ocultos e arquivos .md no inventário por padrão. Crie um arquivo denominado .inventoryignore em seu Repositório de inventário para excluir quaisquer arquivos ou diretórios O pipeline procura
o arquivo .inventoryignore na raiz do repositório..
No entanto, se você preferir um nome diferente para o arquivo de exclusão de inventário, poderá especificá-lo definindo a chave inventory-ignore-file como uma propriedade de ambiente no pipeline. Certifique-se de que esse arquivo
esteja na raiz do repositório de inventário
Por exemplo, se seu arquivo for denominado .custominventoryignore, inclua uma variável de ambiente inventory-ignore-file com o valor custominventoryignore.
Veja a seguir o exemplo de conteúdo do arquivo .custominventoryignore em dois formatos:
.md
sample_file
sample_directory/
# Ignore everything
**
# But keep these artifacts
!sample_directory/
!sample_file
A seguir, explicamos a finalidade das entradas no arquivo de exemplo .custominventoryignore:
.md: exclui todos os arquivos com a extensão.md. Não adicione*no início, como*.md, pois não há suporte para regex.sample_file: exclui o arquivo específico em todo o repositório.sample_directory/: exclui o diretório inteiro. Evite adicionar*no final, usesample_directory/*, pois não há suporte para regex.- Um arquivo sem entradas ou com uma linha vazia fará com que todos os arquivos sejam excluídos. Não deixe entradas ou linhas vazias no arquivo de ignorar inventário.
**: Ignora tudo no repositório.!sample_directory/e!sample_file: Nega a regra de ignorar, mantendo esses arquivos ou diretórios específicos mesmo que**esteja presente.