<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Kelly Lima</title>
    <description>The latest articles on Forem by Kelly Lima (@keelylima).</description>
    <link>https://forem.com/keelylima</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F589363%2Fe6d4432d-04c1-4779-9674-1957a317a9da.jpeg</url>
      <title>Forem: Kelly Lima</title>
      <link>https://forem.com/keelylima</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/keelylima"/>
    <language>en</language>
    <item>
      <title>IAM Identity Center com Terraform</title>
      <dc:creator>Kelly Lima</dc:creator>
      <pubDate>Sat, 27 Jan 2024 02:20:54 +0000</pubDate>
      <link>https://forem.com/keelylima/identity-center-com-terraform-2oac</link>
      <guid>https://forem.com/keelylima/identity-center-com-terraform-2oac</guid>
      <description>&lt;p&gt;Recentemente tive um projeto no trabalho envolvendo o Identity Center da AWS (sucessor do Single Sign-On), quis deixar aqui de uma forma mais simples e prática coisas que fui aprendendo.&lt;/p&gt;




&lt;p&gt;Para ficar um pouco melhor a visualização do que será feito, elaborei a imagem abaixo: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1npevlbc8u5af7b68axh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1npevlbc8u5af7b68axh.png" alt="Imagem do fluxo que será feito" width="800" height="508"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Falando das etapas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Criação de um grupo;&lt;/li&gt;
&lt;li&gt;Adicionar membro ao grupo;&lt;/li&gt;
&lt;li&gt;Criação da Permission Set;&lt;/li&gt;
&lt;li&gt;Adicionar policies na Permission Set;&lt;/li&gt;
&lt;li&gt;Criar o que é chamado Account Assignment;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Algumas explicações básicas: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Permission Set&lt;/strong&gt; é a forma que o Identity Center trabalha com permissões, por trás nada mais é que uma role que é atribuída à um grupo/usuário;&lt;/li&gt;
&lt;li&gt;Esse processo que chamamos de &lt;strong&gt;Account Assignment&lt;/strong&gt; nada mais é que criar o vínculo da Permission Set com a conta que você quer (por exemplo, conta de produção, desenvolvimento, etc). Caso você não conheça muito sobre a estrutura do Identity Center, de forma resumida, ele é centralizado, ou seja, todas as minhas permissões para todas as minhas contas irão ficar centralizada em uma conta só dentro do Identity Center, por isso precisamos criar esse vínculo para que ele saiba em qual conta essas permissões se aplicam. &lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Código
&lt;/h2&gt;

&lt;p&gt;Tentei trazer um exemplo de código que possa ser reutilizado, para ficar um pouco mais elaborado e vocês conseguirem visualizar algo a mais e não ser um exemplo tão simples.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;OBS 01:&lt;/strong&gt; Estou considerando que você já tenha conhecimento de AWS e Terraform, logo suas credenciais/região já devem estar configuradas.&lt;br&gt;
&lt;strong&gt;OBS 02:&lt;/strong&gt; O código só funciona com a versão do provider AWS &amp;gt;= 5.14. Explico melhor sobre no final.&lt;/p&gt;

&lt;p&gt;Nós teremos um arquivo de &lt;code&gt;locals&lt;/code&gt; chamado &lt;code&gt;local.tf&lt;/code&gt; que terá:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
data "aws_ssoadmin_instances" "my_sso" {}

output "arns" {
  value = tolist(data.aws_ssoadmin_instances.my_sso.arns)[0]
}

output "identity_store_id" {
  value = tolist(data.aws_ssoadmin_instances.my_sso.identity_store_ids)[0]
}

# sempre vamos acabar precisando utilizar esse id e esse arn em outros lugares
locals {
  identity_store_id  = tolist(data.aws_ssoadmin_instances.my_sso.identity_store_ids)[0]
  identity_store_arn = tolist(data.aws_ssoadmin_instances.my_sso.arns)[0]
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nós teremos um outro arquivo chamado &lt;code&gt;user-group.tf&lt;/code&gt;, nesse arquivo nós iremos colocar um exemplo de estrutura de usuários que queremos adicionar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
variable "user_group" {
  description = "Create users in Identity Center"
  default = {
    "kelly.lima" = {
      email      = "kelly.lima@email.com"
      group      = ["group-a"]
      first_name = "Kelly"
      last_name  = "Lima"
    }
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Um arquivo chamado &lt;code&gt;policies-managed.tf&lt;/code&gt; onde colocaremos policies gerenciadas pela AWS a forma de adicioná-las é diferente das policies personalizadas. Nas gerenciadas nós teremos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
variable "policies_managed" {
  description = "Policies Managed (AWS)"
  type        = list(string)
  default = [
    "arn:aws:iam::aws:policy/ReadOnlyAccess",
    "arn:aws:iam::aws:policy/AWSBillingReadOnlyAccess"
  ]
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esses valores de &lt;code&gt;arn&lt;/code&gt; serão padrão. Você pode pegar esses valores dentro do próprio IAM.&lt;/p&gt;

&lt;p&gt;Arquivo de policies personalizadas se chamará &lt;code&gt;policies-custom.tf&lt;/code&gt; e terá:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
variable "policy_group_a" {
  description = "Policies Custom"
  type        = list(string)
  default = [
    "policies-group-a",
    "policies-default"
  ]
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No exemplo acima, podemos ver que no Identity Center as policies customizadas nós devemos passar o nome, pois o resource &lt;code&gt;aws_ssoadmin_customer_managed_policy_attachment&lt;/code&gt; (que iremos utilizar em breve) ele só aceita nome da policy e não o arn. Nesse caso eu estou considerando que essa policy já foi criada utilizando o resource &lt;code&gt;aws_iam_policy&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Teremos um arquivo que chamaremos de &lt;code&gt;accounts.tf&lt;/code&gt; onde terá:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
variable "accounts_aws" {
  description = "Accounts AWS"
  default = {
    "prod" = {
      number = "123456789345"
    },
    "dev" = {
      number = "458456789345"
    }
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este é um exemplo de como poderia ficar várias contas, mas nós iremos considerar apenas a conta "prod" para facilitar.&lt;/p&gt;

&lt;p&gt;Agora nós teremos o nosso último arquivo onde iremos construir todo esse processo que temos na imagem do começo, ficaria:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
# Criação do Group A
resource "aws_identitystore_group" "group_a" {
  identity_store_id = local.identity_store_id
  display_name      = "group-a"
  description       = "sso group a"
}

# Adciona os membros baseado no group em var.user_group
resource "aws_identitystore_group_membership" "membership_group_a" {
  for_each          = { for user in local.group_members : user =&amp;gt; aws_identitystore_user.user_sso[user].user_id }
  depends_on        = [aws_identitystore_user.user_sso]
  identity_store_id = local.identity_store_id
  group_id          = aws_identitystore_group.group_a.group_id
  member_id         = each.value
}

# Criação da Permission Set
resource "aws_ssoadmin_permission_set" "permission_set_group_a" {
  name         = "PermissionGroupA"
  instance_arn = local.identity_store_arn
  description  = "Permission Set Custom"
}

# Adiciona as policies managed AWS na Permission Set
resource "aws_ssoadmin_managed_policy_attachment" "policy_managed_group_a" {
  instance_arn       = local.identity_store_arn
  count              = length(var.policies_managed)
  managed_policy_arn = var.policies_managed[count.index]
  permission_set_arn = aws_ssoadmin_permission_set.permission_set_group_a.arn
}

# Adiciona as policies customizadas na Permission Set
resource "aws_ssoadmin_customer_managed_policy_attachment" "policy_custom" {
  for_each = {
    for policy_key, policy_value in var.policy_group_a :
    policy_key =&amp;gt; var.policy_group_a[policy_key]
  }
  instance_arn       = local.identity_store_arn
  permission_set_arn = aws_ssoadmin_permission_set.permission_set_group_a.arn
  customer_managed_policy_reference {
    name = each.value
    path = "/"
  }
}

# Adiciona a Permission Set com o Group A à conta "prod"
resource "aws_ssoadmin_account_assignment" "prod_env" {
  for_each = {
    for key, key_value in local.permission_set_arns :
    value_key =&amp;gt; local.permission_set_arns[value_key]
  }
  instance_arn       = local.identity_store_arn
  permission_set_arn = each.value

  principal_id   = aws_identitystore_group.group_a.group_id
  principal_type = "GROUP"

  target_id   = var.accounts_aws["prod"].number
  target_type = "AWS_ACCOUNT"
}

locals {
# Aqui você pode colocar outros arns de Permission Sets
  permission_set_arns = [aws_ssoadmin_permission_set.permission_set_group_a.arn]

# Deixei esse locals no mesmo arquivo e não no arquivo local.tf apenas para questão didática, ficar mais prático de visualizar
  group_members = [
    for user, details in var.user_group :
    user if contains(details.group, "group-a")
  ]
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Alguns pontos:
&lt;/h2&gt;

&lt;p&gt;Como podem ver é utilizado o &lt;code&gt;depends_on&lt;/code&gt; no resource &lt;code&gt;aws_identitystore_group_membership&lt;/code&gt; foi colocado pois o código estava dando um bug na hora do apply, o Terraform reclamava de adicionar um membro que não existia ainda. Há outros problemas similares quando rodamos o destroy envolvendo Permission Sets, em alguns casos ele reclama do estado que está recebendo (espera estado A e recebe B), ao rodar o comando novamente ele consegue finalizar a exclusão do resource, é realmente um bug nos states do Terraform. Tentei utilizar o &lt;code&gt;depends_on&lt;/code&gt; nesse caso também, mas não obtive sucesso, você pode ver melhor sobre nesses links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/hashicorp/terraform-provider-aws/issues/26757"&gt;https://github.com/hashicorp/terraform-provider-aws/issues/26757&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/hashicorp/terraform-provider-aws/issues/26807"&gt;https://github.com/hashicorp/terraform-provider-aws/issues/26807&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sobre o aviso que deixo acima da versão ser &amp;gt;= 5.14 é por conta desses bugs, antes da versão 5.14 eles ocorriam com maior frequência, houve várias &lt;a href="https://github.com/hashicorp/terraform-provider-aws/blob/v5.14.0/CHANGELOG.md#5140-unreleased"&gt;correções&lt;/a&gt; referentes a Permission Set.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Bom, eu tentei ser o mais sucinta possível, espero que tenha ajudado, qualquer coisa só perguntar. Valeu! ✌️&lt;/p&gt;

</description>
      <category>security</category>
      <category>aws</category>
      <category>terraform</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Se preparando para a certificação AWS Solution Architect Associate (SAA-C03)</title>
      <dc:creator>Kelly Lima</dc:creator>
      <pubDate>Mon, 08 May 2023 20:27:15 +0000</pubDate>
      <link>https://forem.com/keelylima/se-preparando-para-a-certificacao-aws-solution-architect-associate-saa-c03-2nja</link>
      <guid>https://forem.com/keelylima/se-preparando-para-a-certificacao-aws-solution-architect-associate-saa-c03-2nja</guid>
      <description>&lt;p&gt;Recentemente passei na certificação &lt;strong&gt;AWS Solution Architect Associate (SAA-C03)&lt;/strong&gt; e decidi compartilhar aqui quais foram os passos que tomei nessa saga. &lt;/p&gt;

&lt;p&gt;Bom, começo avisando que trabalho com Cloud AWS há 2 anos, mas o meu contato maior foi no último ano.&lt;br&gt;
Eu sei que é possível tirar sem nenhuma experiência mas a própria AWS recomenda pelo menos 1 ano de contato com AWS para realizar. &lt;/p&gt;

&lt;h2&gt;
  
  
  A Saga
&lt;/h2&gt;

&lt;p&gt;Levei quase 6 meses de estudo, porque eu estudava uma hora por dia, alguns dias menos, alguns dias mais, eu realmente decidi fazer no meu tempo pois queria aproveitar o aprendizado também, além disso estava tendo uma mentoria por um colega do trabalho, o que foi muito bom para tirar algumas dúvidas.&lt;/p&gt;

&lt;p&gt;Eu utilizei para estudo o &lt;a href="https://www.udemy.com/course/aws-certified-solutions-architect-associate-saa-c03/"&gt;curso&lt;/a&gt; do Stephane Maarek, na Udemy. Este curso é realmente bom e com preço acessível &lt;del&gt;na promoção&lt;/del&gt;, foi o meu maior guia nessa saga, após a finalização do curso eu passei para os simulados, foi ai que entrou as minhas maiores dúvidas.&lt;/p&gt;

&lt;p&gt;Fiquei um mês fazendo simulados, fiz simulados do &lt;a href="https://www.udemy.com/course/aws-certified-solutions-architect-associate-amazon-practice-exams-saa-c03/"&gt;Jon Bonso&lt;/a&gt;, &lt;a href="https://www.udemy.com/course/aws-certified-solutions-architect-associate-practice-tests-k/"&gt;Neal Davis&lt;/a&gt; e os do &lt;a href="https://www.whizlabs.com/aws-solutions-architect-associate/"&gt;Whizlabs&lt;/a&gt;.&lt;br&gt;
No caso do &lt;strong&gt;Jon Bonso&lt;/strong&gt; e do &lt;strong&gt;Neal Davis&lt;/strong&gt;, eles são da &lt;strong&gt;Udemy&lt;/strong&gt;, são 6 simulados cada.&lt;br&gt;
Já do &lt;strong&gt;WhizLabs&lt;/strong&gt; são 6 simulados mais 12 simulados menores em assuntos específicos como RDS, EBS, SQS e outros. Além disso, no final eles deixam mais um simulado que seria um &lt;em&gt;Final Test&lt;/em&gt;.  &lt;/p&gt;

&lt;p&gt;Bom, desses três os que eu achei mais parecido com a prova foram os do &lt;strong&gt;Neal Davis&lt;/strong&gt; e do &lt;strong&gt;Whizlabs&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Os do &lt;strong&gt;Jon Bonso&lt;/strong&gt; são muito bons para aprendizado, eles são mais difíceis, as questões são mais longas e complexas, então acho que vale a pena para aprender, mas não levaria ele como base pois pode acabar dando uma desanimada com os resultados dos simulados, digo isso porque foram os primeiros que fiz e eu reprovei em 5 dos 6 de primeira. Acertava em média 65%, e no último acertei 73%. Na segunda vez eu acertei 90% pra cima em todos.&lt;/p&gt;

&lt;p&gt;Já nos do &lt;strong&gt;Neal Davis&lt;/strong&gt; eu passei de primeira em 5 dos 6. Acertei em média 80% e no último acertei 69%. Não fiz esses novamente, eu apenas estudei o que errei. &lt;/p&gt;

&lt;p&gt;Lá vamos nós para mais simulados, fui para os do &lt;strong&gt;WhizLabs&lt;/strong&gt;, na primeira vez eu reprovei em 3 e passei em 3. Na WhizLabs para passar é mais exigente pede 80%, já na Udemy é 72%. Na WhizLabs os que eu reprovei de primeira eu acertei em média 68%, nos que passei eu acertei 89%. Na segunda vez eu acertei uma média de 98%.&lt;/p&gt;

&lt;p&gt;Quando eu estava fazendo os simulados foi onde surgiu a minha maior dúvida: &lt;strong&gt;Como saber se estou pronta pra prova?&lt;/strong&gt; Afinal, se estou reprovando em simulado de primeira, como vou fazer a prova? E se esse simulado fosse a minha prova? Bom, vamos lá. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Primeira coisa que notei:&lt;/strong&gt;&lt;br&gt;
Os simulados que reprovei de primeira normalmente eles estavam focados em Networking (VCP, VPN, Transit Gateway e etc) e esse é um tema que tenho dificuldade, estudo &lt;del&gt;insisto&lt;/del&gt; bastante mas ainda sim sei que é algo que posso melhorar.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Segunda coisa que notei:&lt;/strong&gt;&lt;br&gt;
Alguns simulados tem questões com serviços que &lt;strong&gt;não foram&lt;/strong&gt; abordados a fundo no curso ou até mesmo comentado, foram pouquíssimas questões, mas foi interessante para conhecer e estudar, ai que entra a documentação da AWS, principalmente a parte de &lt;strong&gt;FAQ&lt;/strong&gt; dos serviços, isso ajuda muito nos estudos.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terceira coisa que notei:&lt;/strong&gt;&lt;br&gt;
Cheguei a conclusão de que se você estiver &lt;strong&gt;passando de primeira com uns 80%&lt;/strong&gt;, dá pra fazer a prova já. Prova não é fácil, mas teve simulados que achei mais difícil que a prova.&lt;/p&gt;

&lt;h2&gt;
  
  
  A temida prova
&lt;/h2&gt;

&lt;p&gt;A prova possui 65 questões dividida entre múltipla escolha e resposta múltipla (mais de 1 alternativa correta).&lt;/p&gt;

&lt;p&gt;A prova que fiz abordou muito banco de dados (&lt;strong&gt;RDS, Aurora e DynamoDB&lt;/strong&gt;), teve muitas questões envolvendo desacoplar serviços, logo, utilização de &lt;strong&gt;SNS, SQS, Kinesis&lt;/strong&gt;. Questões de &lt;strong&gt;S3, envolvendo Lifecycle&lt;/strong&gt;. Esses foram os tópicos mais abordados. Questão de Networking tiveram apenas 2 (que me recordo agora), poucas questões sobre KMS, Secrets Manager. No geral, são esses assuntos que me recordo. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deixo como dica:&lt;/strong&gt; Estude questões de &lt;strong&gt;custo&lt;/strong&gt;, teve muitas questões que o cenário envolvia onde se teria menos custo, logo tinha algumas pegadinhas, pois as vezes uma alternativa parece correta, porém ela é mais cara. Por exemplo, de forma resumida, teve uma questão que falava sobre Alta Disponibilidade de Banco de Dados mas o principal era o custo, e uma das alternativas falava do Aurora, porém havia outra que falava sobre RDS, que é mais barato no cenário da questão, então é importante estar atento.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Importante:&lt;/strong&gt; O resultado da prova &lt;strong&gt;não sai na hora&lt;/strong&gt;, leva em média 24hrs. No meu caso levou 23hrs para sair o resultado. Sim, aguenta coração que a ansiedade bate.&lt;/p&gt;

&lt;p&gt;No final, eu tirei &lt;strong&gt;871&lt;/strong&gt; na prova. Eu sai da prova com sentimento misto, algumas questões eu sabia, outras fiquei em dúvida entre 2 alternativas, imagino que é normal sair com sentimento de preocupação. &lt;/p&gt;

&lt;p&gt;Enfim, espero que isso ajude alguém tentei trazer pontos que não encontrei em outros artigos e era a minha dúvida, fico a disposição para tirar dúvidas sobre e &lt;strong&gt;boa sorte&lt;/strong&gt;! 🤘&lt;/p&gt;

</description>
      <category>aws</category>
      <category>certification</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Pipeline Prowler</title>
      <dc:creator>Kelly Lima</dc:creator>
      <pubDate>Sun, 19 Feb 2023 02:38:46 +0000</pubDate>
      <link>https://forem.com/keelylima/pipeline-prowler-2123</link>
      <guid>https://forem.com/keelylima/pipeline-prowler-2123</guid>
      <description>&lt;p&gt;Antes de tudo, gostaria de dizer o que me motivou a criar esse artigo/tutorial, bom, sou nova na área de segurança e percebi que tenho muita dificuldade em encontrar artigos/tutoriais em português, em específico de Cloud, vejo muito o básico da teoria sendo explicado, mas vejo pouca prática, então decidi unir o útil ao agradável, passar os conhecimentos que tenho (são poucos e talvez não tão bem definidos) mas espero que possa ajudar alguém e também me ajudar, pois escrevendo para outras pessoas preciso conhecer melhor ainda o assunto o que me faz estudar mais ainda. 💙&lt;/p&gt;




&lt;h2&gt;
  
  
  Mas o que é o Prowler?
&lt;/h2&gt;

&lt;p&gt;Prowler é uma ferramenta &lt;strong&gt;open-source&lt;/strong&gt; de segurança, neste caso, voltado para segurança Cloud, em específico AWS. Ele funciona como um scan, scanea o seu ambiente baseado em diversos padrões de controle, um exemplo seria o CIS. Dei um resumo do resumo sobre, você pode ver melhor sobre ele &lt;a href="https://github.com/prowler-cloud/prowler"&gt;aqui&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;No desenvolvimento dessa &lt;em&gt;pipeline&lt;/em&gt; eu quebrei muito a cabeça, primeiro por não conhecer Jenkins (quem dirá Jenkinsfile) e entender o conceito do Prowler mas não ter visto em prática, no final ela ficou bem mais simples, mas acredite, para alguém que só conhecia e mexia com Angular, foi um desafio legal.&lt;/p&gt;

&lt;p&gt;Agora vamos lá, de forma resumida nós iremos criar um Jenkinsfile e trabalhar com imagem Docker do Prowler dentro. O Prowler já possui uma imagem feita e já possui diversos parâmetros que podemos passar, o que facilita bastante o desenvolvimento, de forma resumida nós teremos duas grandes etapas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dar pull na imagem Docker do Prowler;&lt;/li&gt;
&lt;li&gt;Executar o scan.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;OBS:&lt;/strong&gt; Fiz esse tutorial para pessoas que conheçam o básico de Jenkinsfile/estrutura, assim como de AWS (Access Keys).&lt;/p&gt;




&lt;p&gt;Vamos lá, primeiro que iremos subir essa &lt;em&gt;pipeline&lt;/em&gt; através de um arquivo Jenkinsfile e ele no final ficará assim:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0HXP1aer--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/10k3m4ygzu9ulj2ykqsz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0HXP1aer--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/10k3m4ygzu9ulj2ykqsz.png" alt="Imagem do código da pipeline" width="880" height="767"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Simples, não? Bom, agora vou explicar um pouquinho cada &lt;em&gt;stage&lt;/em&gt; que temos:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Primeiro &lt;em&gt;stage&lt;/em&gt; chamado: &lt;strong&gt;Pipeline Info&lt;/strong&gt; é apenas visual, eu gosto de ter um primeiro &lt;em&gt;stage&lt;/em&gt; apenas para retornar que está inicializando, para mim deixa a usabilidade melhor, mas caso você não queira, pode ignorar.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Segundo &lt;em&gt;stage&lt;/em&gt; chamado: &lt;strong&gt;Setting up Prowler&lt;/strong&gt; container é onde fazemos um docker pull da imagem do Prowler, como comentei, Prowler já possui uma imagem própria configurada dentro do Docker Hub, pode ver melhor aqui.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Terceiro &lt;em&gt;stage&lt;/em&gt; chamado &lt;strong&gt;Setting up envs AWS and run Prowler&lt;/strong&gt;, é onde a magia toda acontece e tenho alguns pontos para colocar sobre, primeiro:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Nos &lt;em&gt;steps&lt;/em&gt; nós temos um comando withAWS, mas o que é isso? Bom, withAWS é um comando que vem do plugin Pipeline: AWS Steps, você pode ver melhor sobre &lt;a href="https://plugins.jenkins.io/pipeline-aws/"&gt;aqui&lt;/a&gt;, bom esse comando em específico é para &lt;em&gt;setar&lt;/em&gt; uma "autorização" para os próximos passos, ou seja, uma credencial diretamente, uma role, um profile. No exemplo acima nós estamos passando uma role, e as permissões que essa role precisa ter, você pode encontrar &lt;a href="https://github.com/prowler-cloud/prowler#aws-managed-iam-policies"&gt;aqui&lt;/a&gt; no Github do projeto.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Após passarmos as credenciais que serão usadas, nós iremos passar um script, com alguns pontos que vamos abordar por partes, primeiro, vamos imaginar que iremos passar o comando docker run sem estar dentro de um script, ele irá ficar assim:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TlnaBMWH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/drwfzsjpc1wgsdc0mzc9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TlnaBMWH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/drwfzsjpc1wgsdc0mzc9.png" alt="Imagem do código da pipeline" width="880" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
Vamos falar um pouco sobre cada parâmetro que estamos passando:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;--rm        | para remover nosso _container_ após a execução
--name      | é onde passamos o nome do nosso container
--env       | são variáveis de ambiente para pegar os valores das nossas credenciais da AWS para poder executar o scan
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Esses são os parâmetros mínimos que precisam ser passados para executar o Prowler, e você pode ver melhor sobre na documentação &lt;a href="https://github.com/prowler-cloud/prowler"&gt;aqui&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Agora vamos falar dos outros:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;-f        | para filtrarmos por uma região específica
-M        | caso queiramos salvar o resultado do nosso scan, é com esse parâmetro que escolhemos o formato do resultado, pode ser HTML, Json e outros, no exemplo estamos selecionando HTML 
-B        | para salvar o nosso resultado em um Bucket S3 nós podemos passar esse parâmetro com nome do mesmo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Algumas observações, o &lt;em&gt;output&lt;/em&gt; no formato HTML é muito útil, similar a um &lt;em&gt;dashboard&lt;/em&gt; e podemos filtrar por serviço, controle, o que deu falha ou sucesso, sem contar que conta com outras informações como um score que você pode utilizar para ter uma base da saúde do seu ambiente.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Uma outra observação, estamos sempre utilizando a última versão da imagem lançada e não uma fixa, está desse jeito para fins didáticos, mas eu recomendo que em um ambiente produtivo seja definido uma versão específica para evitar problemas de compatibilidade no futuro.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Vamos voltar para o nosso código completo? No nosso código completo o último &lt;em&gt;stage&lt;/em&gt; fica:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vL5Eolie--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kk63esm4v1q1z1czcy1u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vL5Eolie--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kk63esm4v1q1z1czcy1u.png" alt="Imagem do código da pipeline" width="880" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Por que executamos desse jeito com o nosso comando docker run em volta de um &lt;em&gt;script&lt;/em&gt; e não diretamente igual no exemplo acima que usamos para explicar os comandos? Na verdade, nós podemos executar igual está acima, sem ter um &lt;em&gt;script&lt;/em&gt; em volta e ele irá executar todo o comando, mas teremos um problema no retorno do Jenkins. Nossa pipeline irá retornar como &lt;strong&gt;Failure&lt;/strong&gt; mesmo tendo executado tudo da forma correta, pois o Jenkins irá retornar exit code 3, como mostro abaixo:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--z26yoDUm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jai53f6auhhh1uhk6b8j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--z26yoDUm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jai53f6auhhh1uhk6b8j.png" alt="Imagem do erro na pipeline" width="880" height="167"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Aparentemente quando se executa um Shell Script no Jenkins, tudo que for diferente de 0 (que é sucesso) ele irá lançar um erro de exceção e "quebrar" a pipeline, então nós devemos tratar esse retorno, nós tratamos exatamente na parte que colocamos o &lt;strong&gt;returnStatus: true&lt;/strong&gt;, podemos ver melhor &lt;a href="https://www.jenkins.io/doc/pipeline/steps/workflow-durable-task-step/#sh-shell-script"&gt;aqui&lt;/a&gt; na documentação do Jenkins sobre esse parâmetro para Shell Scripts.&lt;/p&gt;

&lt;p&gt;Admito que levei algumas horas de pesquisa e ainda não compreendi a fundo o porque de ele retornar exit code 3, mas descobri que não é algo incomum o Jenkins retornar erros e as pessoas tratarem dessa forma por se tratar de um falso positivo. Também dá para tratar erros específicos utilizando if/else.&lt;/p&gt;

&lt;p&gt;Peguei essa dica &lt;a href="https://stackoverflow.com/questions/69571607/jenkins-treats-any-non-zero-exit-code-as-error"&gt;aqui&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Uma observação, para fins didáticos nós deixamos para ele sempre retornar sucesso, por sabermos que se trata de um falso positivo, mas em um cenário produtivo eu recomendo tratar o erro em específico (exitCode == 3) e pensando em outros erros para retornar algum aviso/ação.&lt;/p&gt;




&lt;p&gt;Bom, é isso pessoal! Espero que esse tutorial ajude alguém 💙&lt;/p&gt;

</description>
      <category>aws</category>
      <category>opensource</category>
      <category>devops</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
