<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Seiji]]></title><description><![CDATA[Seiji]]></description><link>https://blog.seiji.com.br</link><generator>RSS for Node</generator><lastBuildDate>Sat, 18 Apr 2026 03:40:16 GMT</lastBuildDate><atom:link href="https://blog.seiji.com.br/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Mais segurança no Atlantis]]></title><description><![CDATA[TL;DR

O foco desse pequeno artigo é enfatizar os pontos de execução de comandos arbitrários dos quais o Atlantis está sujeito pelo Terraform. Ou seja, RCE. Não temos intenção de abordar as mais variadas ferramentas de análise SAST ou algo do tipo. M...]]></description><link>https://blog.seiji.com.br/mais-seguranca-no-atlantis</link><guid isPermaLink="true">https://blog.seiji.com.br/mais-seguranca-no-atlantis</guid><category><![CDATA[Terraform]]></category><category><![CDATA[atlantis]]></category><category><![CDATA[conftest]]></category><category><![CDATA[Cloud]]></category><category><![CDATA[Security]]></category><dc:creator><![CDATA[Seiji Manoan Seo]]></dc:creator><pubDate>Thu, 28 Mar 2024 01:15:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/9SoCnyQmkzI/upload/72b783eedb9348063612aa5c08647ba1.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-tldr">TL;DR</h1>
<blockquote>
<p>O foco desse pequeno artigo é enfatizar os pontos de execução de comandos arbitrários dos quais o Atlantis está sujeito pelo Terraform. Ou seja, RCE. Não temos intenção de abordar as mais variadas ferramentas de análise SAST ou algo do tipo. Mas, aproveitar o recurso presente nas imagens Atlantis: o Conftest.</p>
</blockquote>
<h1 id="heading-intro">Intro</h1>
<p>O Atlantis possui suporte a Conftest por padrão.</p>
<p>O Conftest suporta o arquivo de mudanças (plan) gerado pelo Terraform. Assim como também suporta os códigos HCL do Terraform, mas o padrão tem sido o arquivo de mudanças.</p>
<p>Esse arquivo de mudanças pode ser gerado como demonstrado abaixo:</p>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">As variáveis de ambiente <code>$PLANFILE</code> e <code>$SHOWFILE</code> apenas definem os caminhos de arquivo. Você deve definir antes.</div>
</div>

<pre><code class="lang-bash">terraform init -upgrade
terraform plan -input=<span class="hljs-literal">false</span> -refresh -out <span class="hljs-variable">$PLANFILE</span>
terraform show -json <span class="hljs-variable">$PLANFILE</span> &gt; <span class="hljs-variable">$SHOWFILE</span>
</code></pre>
<p>Feito! O primeiro subsídio está disponível. O arquivo <code>$SHOWFILE</code> será bastante útil.</p>
<h1 id="heading-conftest">Conftest</h1>
<p>O comando Conftest segue no formato abaixo:</p>
<pre><code class="lang-bash">conftest <span class="hljs-built_in">test</span> <span class="hljs-variable">$SHOWFILE</span> --policy policy/ --all-namespaces
</code></pre>
<p>Assim, você pode fazer testes localmente se precisar. Se houver dúvidas, você pode consultar por <code>conftest test --help</code> ou a própria documentação oficial.</p>
<p>No Atlantis, segue no modelo similar:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">policy_check:</span>
  <span class="hljs-attr">steps:</span>
    <span class="hljs-comment"># ...</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">policy_check:</span>
        <span class="hljs-attr">extra_args:</span> [<span class="hljs-string">"--policy /home/atlantis/policy"</span>, <span class="hljs-string">"--all-namespaces"</span>]
</code></pre>
<p>Confira mais sobre na <a target="_blank" href="https://www.runatlantis.io/docs/policy-checking.html">documentação oficial do Atlantis</a>.</p>
<h2 id="heading-policies">Policies</h2>
<p>Mas, qual <em>policy</em> usar?</p>
<p>O Conftest utiliza OPA com <em>policies</em> escritas em REGO (pronuncia-se <em>ray-go</em>).</p>
<p>Atualmente, existem bibliotecas que empoderam a confecção de <em>policies</em>. A síntaxe pode ser bastante distinta. Então, dependendo do grau de profundidade, alguns recursos auxiliares e/ou complementares podem contribuir no seu desenvolvimento.</p>
<p>Um outro ponto muito importante sobre segurança é: o <code>terraform plan</code> não está imune a algumas ações mesmo com a presença das <em>policies</em>. No Atlantis, as <em>policies</em> acontecem posteriormente ao plano de mudanças. Então, pode ser necessário controlar o plano de mudança ou personalizar a <em>step</em> do plano de mudança.</p>
<h3 id="heading-blocklist-de-providers">Blocklist de providers</h3>
<p>Útil para especificar <em>providers</em> Terraform não permitidos.</p>
<pre><code class="lang-rego"><span class="hljs-keyword">package</span> main

blocked_providers = <span class="hljs-punctuation">{"</span><span class="hljs-variable">registry</span>.<span class="hljs-variable">terraform</span>.io/hashicorp/external<span class="hljs-string">"}

caught_providers[provider] = all {
    some provider
    blocked_providers[provider]
    all := [module |
        module := input.configuration.provider_config[_]
        module.full_name == provider
    ]
}

deny[msg] {
    num_resources := caught_providers[provider]
    num_resources &gt; 0
    msg := sprintf("</span>Provider %s detected in Terraform plan <span class="hljs-variable">file</span>.<span class="hljs-string">", [provider])
}</span>
</code></pre>
<h3 id="heading-allowlist-de-providers">Allowlist de providers</h3>
<p>Pode ser uma alternativa melhor. Assim, apenas <em>providers</em> Terraform autorizados passam. Evitando o risco de <em>providers</em> desconhecidos.</p>
<pre><code class="lang-rego"><span class="hljs-keyword">package</span> main

allowed_providers = <span class="hljs-punctuation">{"</span><span class="hljs-variable">registry</span>.<span class="hljs-variable">terraform</span>.io/hashicorp/aws<span class="hljs-string">"}

deny[msg] {
    filtered := [f | f = input.configuration.provider_config[_].full_name; not allowed_providers[f]]
    count(filtered) &gt; 0
    msg := sprintf("</span>Got %d unauthorized provider<span class="hljs-punctuation">(s)</span> like %<span class="hljs-variable">v</span>.<span class="hljs-string">", [count(filtered), filtered[0]])
}</span>
</code></pre>
<h3 id="heading-entre-outras-infinidades-de-policies">Entre outras infinidades de policies</h3>
<p>Acima, são exemplos reais. Você também pode incluir policies para <code>null_resources</code>.</p>
<p>É importante entender a diferença entre policies que conduzem adoção de boas práticas e aquelas que tratam questões pontuais.</p>
<p>Você pode utilizar algumas bibliotecas/frameworks de <em>policies</em> prontas. A Regula é um exemplo. Consulte a <a target="_blank" href="https://regula.dev/integrations/conftest.html">documentação sobre Regula e Conftest</a> para saber mais. Também há opção para integrar com GitHub Actions diretamente.</p>
<h2 id="heading-policy-para-hcl">Policy para HCL</h2>
<p>Como visto anteriormente, pode ser muito útil verificar o manifesto HCL do Terraform. Aqui vai um exemplo simples:</p>
<pre><code class="lang-rego"><span class="hljs-keyword">package</span> main

deny<span class="hljs-punctuation">[msg]</span> <span class="hljs-punctuation">{
</span>  proto := <span class="hljs-variable">input</span>.<span class="hljs-variable">data</span>.external<span class="hljs-punctuation">[name]</span>
  count<span class="hljs-punctuation">(proto)</span> &gt; <span class="hljs-number">0</span>
  msg = sprintf<span class="hljs-punctuation">("</span>External '%v' detected in <span class="hljs-variable">HCL</span>.<span class="hljs-string">", [name])
}</span>
</code></pre>
<p>Detecção de HCL para fontes de módulos antes do plano? É possível:</p>
<pre><code class="lang-rego"><span class="hljs-keyword">package</span> main

allowed_sources = <span class="hljs-punctuation">{
</span>    <span class="hljs-string">"git@github.com:business/business.git//modules/"</span>
<span class="hljs-punctuation">}
</span>
deny<span class="hljs-punctuation">[msg]</span> <span class="hljs-punctuation">{
</span>    module := <span class="hljs-variable">input</span>.module<span class="hljs-punctuation">[name]</span><span class="hljs-punctuation">.source
</span>    finding := <span class="hljs-punctuation">[trusted </span>| trusted := allowed_sources<span class="hljs-punctuation">[_]</span><span class="hljs-punctuation">; </span><span class="hljs-keyword">not</span> startswith<span class="hljs-punctuation">(module,</span> trusted<span class="hljs-punctuation">)]</span>
    count<span class="hljs-punctuation">(finding)</span> &gt; <span class="hljs-number">0</span>
    msg = sprintf<span class="hljs-punctuation">("</span>Unauthorized <span class="hljs-variable">module</span>.%s <span class="hljs-variable">source</span>.<span class="hljs-string">", [name])
}</span>
</code></pre>
<p>O conceito de <em>allowlist</em> aplica-se perfeitamente aqui.</p>
<p>O plano de mudança está sujeito a execução de comandos arbitrários. Portanto, é interessante a ideia de executar a verificação antes do plano de mudança.</p>
<p>E como funcionaria o comando para Conftest nessa estratégia?</p>
<pre><code class="lang-bash">conftest <span class="hljs-built_in">test</span> *.tf --policy policy/ --all-namespaces
</code></pre>
<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">O Conftest pode combinar arquivos HCL e <code>$SHOWFILE</code>.</div>
</div>

<p>Portanto, antes de efetivar o plano de mudança no Terraform, execute o teste.</p>
<pre><code class="lang-bash">$ conftest <span class="hljs-built_in">test</span> <span class="hljs-variable">$SHOWFILE</span> *.tf --policy /home/atlantis/policy -n main --output table

+---------+--------------+-----------+--------------------------------+
| RESULT  |     FILE     | NAMESPACE |            MESSAGE             |
+---------+--------------+-----------+--------------------------------+
| success | outputs.tf   | main      | SUCCESS                        |
| success | outputs.tf   | main      | SUCCESS                        |
| success | tests.tf     | main      | SUCCESS                        |
| failure | tests.tf     | main      | External <span class="hljs-string">'example'</span> detected <span class="hljs-keyword">in</span> |
|         |              |           | HCL.                           |
| success | variables.tf | main      | SUCCESS                        |
| success | variables.tf | main      | SUCCESS                        |
| success | showfile     | main      | SUCCESS                        |
| failure | showfile     | main      | Resource <span class="hljs-string">'null_resource'</span>       |
|         |              |           | detected <span class="hljs-keyword">in</span> Terraform plan     |
|         |              |           | file. Denied.                  |
| success | main.tf      | main      | SUCCESS                        |
| success | main.tf      | main      | SUCCESS                        |
+---------+--------------+-----------+--------------------------------+
</code></pre>
<p>Também é possível utilizar o arquivo <code>.terraform.lock.hcl</code> gerado durante <code>terrraform init</code> para verificar <em>providers</em> antes do <code>terraform plan</code>.</p>
<pre><code class="lang-bash">conftest <span class="hljs-built_in">test</span> .terraform.lock.hcl -p /home/atlantis/policy
</code></pre>
<pre><code class="lang-rego"><span class="hljs-keyword">package</span> main

allowed_providers = <span class="hljs-punctuation">{
</span>    <span class="hljs-string">"registry.terraform.io/hashicorp/aws"</span><span class="hljs-punctuation">,
</span>    <span class="hljs-string">"registry.terraform.io/hashicorp/random"</span><span class="hljs-punctuation">,
</span>    <span class="hljs-string">"registry.terraform.io/hashicorp/null"</span>
<span class="hljs-punctuation">}
</span>
deny<span class="hljs-punctuation">[msg]</span> <span class="hljs-punctuation">{
</span>    <span class="hljs-variable">input</span>.provider<span class="hljs-punctuation">[name]</span>
    <span class="hljs-keyword">not</span> allowed_providers<span class="hljs-punctuation">[name]</span>
    msg = sprintf<span class="hljs-punctuation">("</span>Provider '%s' <span class="hljs-variable">caught</span>.<span class="hljs-string">", [name])
}</span>
</code></pre>
<p>Veja que é possível combinar os arquivos com as <em>policies</em> de maneiras variadas.</p>
<p>Dessa forma, o plano de mudança não vai acontecer. Pois, com os exemplos acima, retornará um código de saída <code>1</code> quando qualquer <em>provider</em> não autorizado for detectado.</p>
<blockquote>
<p>If a workflow step returns a non-zero exit code, the workflow will stop.</p>
</blockquote>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711587358294/4e1f0db9-3f12-4e16-8048-4c9577115275.png" alt class="image--center mx-auto" /></p>
<p>Esse tipo de medida estabelece uma melhor prevenção.</p>
<p>Ou seja, se o teste ocorrer bem, o plano será executado como esperado. Caso contrário, o risco será mitigado.</p>
<p>Assim, não tem problema ter testes antes do <em>plan</em> e a <strong>policy check</strong> que acontecerá depois do <em>plan</em> normalmente. As <em>custom workflows</em> de Atlantis são personalizáveis.</p>
<h3 id="heading-recurso-terraformdata">Recurso terraform_data</h3>
<p>Em poucas palavras, a HashiCorp inseriu o sucessor de <code>null_resource</code>. Esse recurso tem a missão de auxiliar no ciclo de vida de outros recursos. Ele não depende de outros <em>providers</em>, pois vem no embutido.</p>
<p>Na <a target="_blank" href="https://developer.hashicorp.com/terraform/language/resources/terraform-data">documentação</a>, há duas formas de explorar isso:</p>
<ul>
<li><p>Usando o recurso <code>terraform_data</code> ;</p>
</li>
<li><p>Usando <code>replace_triggered_by</code> no argumento de <em>lifecycle</em> de outro recurso.</p>
</li>
</ul>
<p>No primeiro caso, fica sujeito ao uso de <em>provisioner</em> como <code>local-exec</code>. O que merece muita atenção. Concorda?</p>
<h2 id="heading-confeccionando-policies">Confeccionando policies</h2>
<p>Eu utilizei o <a target="_blank" href="https://play.openpolicyagent.org/">The Rego Playground</a> para confeccionar algumas <em>policies</em> REGO.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1711580610683/11613cce-d598-4dd2-88ce-8c13c5810769.png" alt class="image--center mx-auto" /></p>
<p>Na imagem acima, o campo esquerdo é reservado para a <em>policy</em> REGO. No campo <strong>Input</strong> você cola o conteúdo de <code>$SHOWFILE</code> gerado anteriormente. Lembra-se? E o sucesso da <em>policy</em> pode ser acompanhado nos campos <strong>Data</strong> e <strong>Output</strong> sempre que <strong>Evaluate</strong> for chamado. Acredite, isso pode facilitar a sua vida!</p>
<h1 id="heading-e-agora">E agora?</h1>
<p>É importante fazer um refinamento para chegar em um número maior de itens a serem verificados.</p>
<p>Mas, não seja limitado aos testes em si. É importante abranger a segurança para as outras camadas de infraestrutura.</p>
<p>Uma tendência é o uso de <em>registry</em> Terraform privado para módulos e/ou <em>providers</em>. Há opções como <a target="_blank" href="https://github.com/outsideris/citizen">Citizen</a>, <a target="_blank" href="https://github.com/MatthewJohn/terrareg">Terrareg</a> etc.</p>
<p>Conhece mais dicas para evitar instruções arbitrárias?</p>
<p>Enfim, espero que tenham gostado e mantenham-se sempre vigilantes.</p>
<p><img src="https://media2.giphy.com/media/v1.Y2lkPTc5MGI3NjExNTVnczFvbnZhYmIyd3g0Y2pscDYzeDAwazM2eWkzdnJncDllc213MCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/sCBGZzD1DssidYHGOe/giphy.gif" alt class="image--center mx-auto" /></p>
<h1 id="heading-referencias">Referências</h1>
<ul>
<li><p>Atlantis - <a target="_blank" href="https://www.runatlantis.io/">https://www.runatlantis.io/</a></p>
</li>
<li><p>Conftest - <a target="_blank" href="https://www.conftest.dev/">https://www.conftest.dev/</a></p>
</li>
<li><p>OPA - <a target="_blank" href="https://www.openpolicyagent.org/docs/latest/terraform/">https://www.openpolicyagent.org/docs/latest/terraform/</a></p>
</li>
<li><p>go-getter - <a target="_blank" href="https://pkg.go.dev/github.com/hashicorp/go-getter">https://pkg.go.dev/github.com/hashicorp/go-getter</a></p>
</li>
<li><p>The Rego Playground - <a target="_blank" href="https://play.openpolicyagent.org/">https://play.openpolicyagent.org/</a></p>
</li>
<li><p>Terraform Plan RCE - <a target="_blank" href="https://alex.kaskaso.li/post/terraform-plan-rce">https://alex.kaskaso.li/post/terraform-plan-rce</a></p>
</li>
<li><p>Regula - <a target="_blank" href="https://regula.dev/">https://regula.dev/</a></p>
</li>
<li><p>HackTricks Cloud - <a target="_blank" href="https://cloud.hacktricks.xyz/pentesting-ci-cd/terraform-security#terraform-apply">https://cloud.hacktricks.xyz/pentesting-ci-cd/terraform-security#terraform-apply</a></p>
</li>
<li><p>Atlantis Hardening and Review Fatigue - <a target="_blank" href="https://doordash.engineering/2023/12/05/atlantis-hardening-and-review-fatigue/">https://doordash.engineering/2023/12/05/atlantis-hardening-and-review-fatigue/</a></p>
</li>
<li><p>Use Conftest to Audit IaC - <a target="_blank" href="https://www.fairwinds.com/blog/how-to-kubernetes-use-conftest-to-audit-infrastructure-as-code">https://www.fairwinds.com/blog/how-to-kubernetes-use-conftest-to-audit-infrastructure-as-code</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Volume com NFS no Kubernetes]]></title><description><![CDATA[Primeiramente, o assunto dessa publicação não é definir qual é a melhor opção. Portanto, aos comentaristas com ânsia em apontar a melhor ou a pior alternativa, estejam cientes desde já.
O assunto dessa publicação é, simplesmente, contribuir para quem...]]></description><link>https://blog.seiji.com.br/volume-com-nfs-no-kubernetes</link><guid isPermaLink="true">https://blog.seiji.com.br/volume-com-nfs-no-kubernetes</guid><category><![CDATA[Kubernetes]]></category><category><![CDATA[Docker]]></category><category><![CDATA[google cloud]]></category><category><![CDATA[kubernetes-volume]]></category><category><![CDATA[Devops]]></category><dc:creator><![CDATA[Seiji Manoan Seo]]></dc:creator><pubDate>Sat, 25 Feb 2023 02:29:31 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/yx20mpDyr2I/upload/c7937847a0feb2aae9ad84eb56f58800.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Primeiramente, o assunto dessa publicação não é definir qual é a melhor opção. Portanto, aos comentaristas com ânsia em apontar a melhor ou a pior alternativa, estejam cientes desde já.</p>
<p>O assunto dessa publicação é, simplesmente, contribuir para quem precisa de provisionar um volume Kubernetes usando um serviço Network File System (NFS) como <em>backend</em>.</p>
<p>Vamos lá?</p>
<p>A priori, a Google Cloud (GCP) não disponibiliza Persistent Volume com <code>ReadWriteMany</code> de maneira nativa. Atualmente, é necessário contratar uma solução gerenciada chamada Filestore.</p>
<blockquote>
<p>O <strong>ReadWriteMany</strong> é útil quando mais de um workload precisa ler e escrever num mesmo volume, mesmo estando em nós diferentes. Por exemplo, se você tem um Deployment com cinco réplicas e cada Pod precisa de escrever no mesmo volume.</p>
</blockquote>
<p>Dito isso, a criação de um serviço NFS para disponibilizar um share é um meio disponível. Na prática, o custo de uma VM e um disco persistente. Ou até mesmo um serviço no próprio cluster.</p>
<p>Nessa publicação, espera-se que você já tenha um <em>share</em> de NFS pronto e disponível.</p>
<p>Crie os seguintes objetos Kubernetes:</p>
<p><strong>PersistentVolume (PV)</strong></p>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">PersistentVolume</span>
<span class="hljs-attr">metadata:</span>
  <span class="hljs-attr">name:</span> <span class="hljs-string">share</span>
<span class="hljs-attr">spec:</span>
  <span class="hljs-attr">capacity:</span>
    <span class="hljs-attr">storage:</span> <span class="hljs-string">10Gi</span>
  <span class="hljs-attr">accessModes:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">ReadWriteMany</span>
  <span class="hljs-attr">persistentVolumeReclaimPolicy:</span> <span class="hljs-string">Retain</span>
  <span class="hljs-attr">storageClassName:</span> <span class="hljs-string">""</span>
  <span class="hljs-attr">mountOptions:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">nfsvers=4.2</span>
  <span class="hljs-attr">nfs:</span>
    <span class="hljs-attr">server:</span> <span class="hljs-string">"nfs.domain.tld"</span>
    <span class="hljs-attr">path:</span> <span class="hljs-string">"/my-share"</span>
    <span class="hljs-attr">readOnly:</span> <span class="hljs-literal">false</span>
  <span class="hljs-comment"># Se você quiser tornar esse PV exclusivo ao PVC</span>
  <span class="hljs-comment"># claimRef:</span>
  <span class="hljs-comment">#   name: </span>
  <span class="hljs-comment">#   namespace:</span>
</code></pre>
<p><strong>PersistentVolumeClaim (PVC)</strong></p>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">PersistentVolumeClaim</span>
<span class="hljs-attr">metadata:</span>
  <span class="hljs-attr">name:</span> <span class="hljs-string">share</span>
  <span class="hljs-attr">namespace:</span> <span class="hljs-string">default</span>
<span class="hljs-attr">spec:</span>
  <span class="hljs-attr">accessModes:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">ReadWriteMany</span>
  <span class="hljs-attr">resources:</span>
    <span class="hljs-attr">requests:</span>
      <span class="hljs-attr">storage:</span> <span class="hljs-string">10Gi</span>
  <span class="hljs-attr">storageClassName:</span> <span class="hljs-string">""</span>
  <span class="hljs-attr">volumeName:</span> <span class="hljs-string">share</span>
</code></pre>
<p>Perceba que ambos possuem <code>storageClassName</code> com uma <em>string</em> vazia. Isso acontece para evitar que ele adote por um armazenamento diferente do que estamos buscando.</p>
<p>E, além disso, o PVC buscará pelo PV através de <code>volumeName</code>. Sendo parte da técnica de <em>binding</em>.</p>
<p>Por sua vez, o PV também pode fazer <em>binding</em> ao PVC através de <code>claimRef</code>. Isso seria a técnica completa. Se preferir, pode definir o <code>claimRef</code> para o nome e <em>namespace</em> do PVC. Nesse exemplo, não foi necessário.</p>
<p>O PV precisa do bloco <code>nfs</code> configurado com <code>server</code> e <code>path</code> com o serviço NFS disponível. Ou seja, defina o endereço IP ou nome DNS no campo <code>spec.nfs.server</code> e defina o caminho do share no campo <code>spec.nfs.path</code>.</p>
<p>Essa é a configuração de utilizar um serviço NFS por trás de um PV.</p>
<p>Assim, é possível você definir o volume no seu Deployment por exemplo:</p>
<pre><code class="lang-yaml">  <span class="hljs-string">...</span>
  <span class="hljs-attr">containers:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-attr">image:</span> <span class="hljs-string">busybox</span>
    <span class="hljs-attr">name:</span> <span class="hljs-string">teste</span>
    <span class="hljs-attr">volumeMounts:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">mountPath:</span> <span class="hljs-string">/opt/teste</span>
      <span class="hljs-attr">name:</span> <span class="hljs-string">volume-compartilhado</span>
  <span class="hljs-attr">volumes:</span>
  <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">volume-compartilhado</span>
    <span class="hljs-attr">persistentVolumeClaim:</span>
      <span class="hljs-attr">claimName:</span> <span class="hljs-string">share</span>
</code></pre>
<p>Simples?</p>
<p>Em caso de problemas, verifique se o serviço NFS tem regras de firewall permitindo a rede do nó, ou se há alguma restrição com permissão de usuários sobre o diretório utilizado no servidor.</p>
]]></content:encoded></item><item><title><![CDATA[Which US region to run with BR one at GCP]]></title><description><![CDATA[Hey, South America user running Google Cloud. Can you run all your workloads on your region?
Usually, you need to run some services in cheaper regions like USA and keep some others in southamerica-east1.
via GIPHY
So, what's the point?
We can distrib...]]></description><link>https://blog.seiji.com.br/which-us-region-to-run-with-br-one-at-gcp</link><guid isPermaLink="true">https://blog.seiji.com.br/which-us-region-to-run-with-br-one-at-gcp</guid><category><![CDATA[finops]]></category><category><![CDATA[GCP]]></category><category><![CDATA[Devops]]></category><dc:creator><![CDATA[Seiji Manoan Seo]]></dc:creator><pubDate>Sun, 21 Aug 2022 02:13:43 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/pElSkGRA2NU/upload/v1661038760960/vQ-zUTzP_.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Hey, South America user running Google Cloud. Can you run all your workloads on your region?</p>
<p>Usually, you need to run some services in cheaper regions like USA and keep some others in <code>southamerica-east1</code>.</p>
<p><iframe src="https://giphy.com/embed/1GT5PZLjMwYBW" width="480" height="327" class="giphy-embed"></iframe></p><p><a href="https://giphy.com/gifs/1GT5PZLjMwYBW">via GIPHY</a></p><p></p>
<p>So, what's the point?</p>
<p>We can distribute some workloads on cheaper regions at GCP. The South Carolina region is the best option for.</p>
<p>Especially, if you need to run <strong>Cloud Interconnect</strong> as quoted below:</p>
<blockquote>
<p>South Carolina (us-east1) enables customers in South America to receive an SLA of 99.99% for their Cloud Interconnect configurations, since it is the closest North American region to South America.</p>
</blockquote>
<p>Source <a target="_blank" href="https://cloud.google.com/network-connectivity/docs/interconnect/concepts/choosing-colocation-facilities#locations-table">at here</a>.</p>
<p>So, don't choose random regions anymore.</p>
<p>Aren't you convinced? Check it out on <a target="_blank" href="https://cloud.google.com/products/calculator/">Google Cloud Pricing Calculator</a> and do some math.</p>
<h3 id="heading-extra">Extra</h3>
<p>Verify the network latency closest to you at https://gcping.com/</p>
]]></content:encoded></item><item><title><![CDATA[Begin with Falco deployment on GKE]]></title><description><![CDATA[Background

What about a HIDS tool for your managed Kubernetes cluster? It has an easy way to do that by using Falco with eBPF probe. One out of three available options. Also, it is a GKE recommendation:

We suggest using the eBPF driver for running ...]]></description><link>https://blog.seiji.com.br/begin-with-falco-deployment-on-gke</link><guid isPermaLink="true">https://blog.seiji.com.br/begin-with-falco-deployment-on-gke</guid><category><![CDATA[Kubernetes]]></category><category><![CDATA[Open Source]]></category><category><![CDATA[Cloud Computing]]></category><category><![CDATA[Google]]></category><category><![CDATA[google cloud]]></category><dc:creator><![CDATA[Seiji Manoan Seo]]></dc:creator><pubDate>Tue, 10 May 2022 23:38:45 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/z1uDmJx3ZEQ/upload/v1652226068375/_8Gw1UTSo.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-background">Background</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651870739036/XZ2lMZxPw.png" alt="image.png" /></p>
<p>What about a HIDS tool for your managed Kubernetes cluster? It has an easy way to do that by using Falco with eBPF probe. One out of three available options. Also, it is a GKE recommendation:</p>
<blockquote>
<p>We suggest using the eBPF driver for running Falco on GKE.</p>
</blockquote>
<p>Falco is a CNCF solution and you can check it on: https://falco.org/</p>
<h2 id="heading-requirements">Requirements</h2>
<p>In official documentation, the requirements to use <em>eBPF probe</em> are:</p>
<ol>
<li><code>CONFIG_BPF_JIT</code> enabled</li>
<li><code>FALCO_BPF_PROBE</code> environment variable value set to empty</li>
<li><code>net.core.bpf_jit_enable</code> set to "1"</li>
</ol>
<p>Before, let's look at current <em>kernel</em> version:</p>
<pre><code class="lang-bash">$ uname -r
5.4.170+
</code></pre>
<p>✅ Great! It supports.</p>
<p>Checking <code>CONFIG_BPF_JIT</code>:</p>
<pre><code class="lang-bash">$ grep CONFIG_BPF_JIT /boot/config-$(uname -r)
CONFIG_BPF_JIT_ALWAYS_ON=y
CONFIG_BPF_JIT=y
</code></pre>
<p>✅ Okay, it's enabled.</p>
<p>Checking <code>FALCO_BPF_PROBE</code>:</p>
<pre><code class="lang-yaml">{{<span class="hljs-bullet">-</span> <span class="hljs-string">if</span> <span class="hljs-string">.Values.ebpf.enabled</span> }}
  <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">FALCO_BPF_PROBE</span>
    <span class="hljs-attr">value:</span> {{ <span class="hljs-string">.Values.ebpf.path</span> }}
{{<span class="hljs-bullet">-</span> <span class="hljs-string">end</span> }}
</code></pre>
<p>✅ Okay, the <em>template</em> solves that by default.</p>
<p>Checking <code>net.core.bpf_jit_enable</code>:</p>
<pre><code class="lang-bash">$ sudo sysctl net.core.bpf_jit_enable
net.core.bpf_jit_enable = 1
</code></pre>
<p>✅ Okay, it's enabled.</p>
<h2 id="heading-setup">Setup</h2>
<p>The following Helm Chart command will do the needed setup:</p>
<pre><code class="lang-bash">helm repo add falcosecurity https://falcosecurity.github.io/charts
helm repo update
helm install falco falcosecurity/falco --<span class="hljs-built_in">set</span> ebpf.enabled=<span class="hljs-literal">true</span>
</code></pre>
<p>Wherein you can put other parameters to enable <strong>Falcosidekick</strong> with <strong>WebUI</strong> on the same Helm Chart:</p>
<pre><code class="lang-bash">  ...
  --<span class="hljs-built_in">set</span> falcosidekick.enabled=<span class="hljs-literal">true</span> \
  --<span class="hljs-built_in">set</span> falcosidekick.webui.enabled=<span class="hljs-literal">true</span>
</code></pre>
<p>Check out the <a target="_blank" href="https://github.com/falcosecurity/charts/tree/master/falco">available parameters at here</a>.</p>
<p>Ps.: you could load the Yaml manifest with parameter <code>-f values.yaml</code> instead of.</p>
<p>And a Falcosidekick <a target="_blank" href="https://github.com/falcosecurity/charts/tree/master/falcosidekick">output list at here</a> like Google Cloud Storage, Slack, webhooks etc.</p>
<p>You can look at the created objects with:</p>
<pre><code class="lang-bash">$ kubectl get all -n falco
</code></pre>
<h3 id="heading-ready">Ready</h3>
<p>What's happening right now?</p>
<p>Run a Port Forward to access the UI:</p>
<pre><code class="lang-bash">kubectl port-forward svc/falco-falcosidekick-ui 2802:2802 -n falco
</code></pre>
<p>Done! Go to the browser: http://localhost:2802/ui</p>
<p>Then, you`ll see a page like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652134626283/I0wsTuHWs.png" alt="image.png" /></p>
<p>The default ruleset is applied on. You can custom your settings as you prefer.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652137773902/dk6a7XFjz.gif" alt="ezgif-4-57978f90bc.gif" /></p>
<p>Enjoy! Thanks.</p>
<h2 id="heading-extras">EXTRAS</h2>
<p>If you need to send events to outside through PubSub (log sink), then it's useful.</p>
<p>Parameters for Falcosidekick</p>
<pre><code class="lang-yaml"><span class="hljs-attr">falcosidekick:</span>
  <span class="hljs-attr">enabled:</span> <span class="hljs-string">"true"</span>
  <span class="hljs-attr">gcp:</span>
    <span class="hljs-attr">pubsub:</span>
      <span class="hljs-attr">minimumpriority:</span> <span class="hljs-string">"error"</span>
</code></pre>
<p>Terraform for Google PubSub</p>
<pre><code class="lang-yaml"><span class="hljs-string">module</span> <span class="hljs-string">"falcosidekick_pubsub_output"</span> {
  <span class="hljs-string">source</span>  <span class="hljs-string">=</span> <span class="hljs-string">"terraform-google-modules/pubsub/google"</span>
  <span class="hljs-string">version</span> <span class="hljs-string">=</span> <span class="hljs-string">"~&gt; 3.2.0"</span>

  <span class="hljs-string">topic</span>      <span class="hljs-string">=</span> <span class="hljs-string">"falco-topic"</span>
  <span class="hljs-string">project_id</span> <span class="hljs-string">=</span> <span class="hljs-string">"projeto-id"</span>
  <span class="hljs-string">push_subscriptions</span> <span class="hljs-string">=</span> [
    {
      <span class="hljs-string">name</span>                 <span class="hljs-string">=</span> <span class="hljs-string">"falco-subscription"</span>
      <span class="hljs-string">push_endpoint</span>        <span class="hljs-string">=</span> <span class="hljs-string">"https://gcp-intake.logs.datadoghq.com/api/v2/logs?dd-api-key=${local.falco_api_key}&amp;dd-protocol=gcp"</span>
      <span class="hljs-string">ack_deadline_seconds</span> <span class="hljs-string">=</span> <span class="hljs-number">20</span>
      <span class="hljs-string">x-goog-version</span>       <span class="hljs-string">=</span> <span class="hljs-string">"v1beta1"</span>
    }
  ]
}
</code></pre>
]]></content:encoded></item><item><title><![CDATA[Implantando Falco no GKE]]></title><description><![CDATA[Contexto

Já pensou em uma ferramenta HIDS para o seu Kubernetes gerenciado? Há uma maneira pouco dramática para implantá-la utilizando Falco com suporte a eBPF. É uma das três alternativas disponibilizadas. Além disso, é uma recomendação para GKE:

...]]></description><link>https://blog.seiji.com.br/falco-deployment-on-gke</link><guid isPermaLink="true">https://blog.seiji.com.br/falco-deployment-on-gke</guid><category><![CDATA[Kubernetes]]></category><category><![CDATA[Security]]></category><category><![CDATA[Open Source]]></category><dc:creator><![CDATA[Seiji Manoan Seo]]></dc:creator><pubDate>Mon, 09 May 2022 22:28:02 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/unsplash/z1uDmJx3ZEQ/upload/v1652135209657/qN9YHRbCD.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-contexto">Contexto</h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1651870739036/XZ2lMZxPw.png" alt="image.png" /></p>
<p>Já pensou em uma ferramenta HIDS para o seu Kubernetes gerenciado? Há uma maneira pouco dramática para implantá-la utilizando Falco com suporte a eBPF. É uma das três alternativas disponibilizadas. Além disso, é uma recomendação para GKE:</p>
<blockquote>
<p>We suggest using the eBPF driver for running Falco on GKE.</p>
</blockquote>
<p>Falco é uma solução CNCF e você pode conhecer mais no site: https://falco.org/</p>
<h2 id="heading-requisitos">Requisitos</h2>
<p>Na documentação oficial, os requisitos para utilizar <em>eBPF probe</em> são:</p>
<ol>
<li><code>CONFIG_BPF_JIT</code> habilitado</li>
<li>valor da variável de ambiente <code>FALCO_BPF_PROBE</code> para vazio</li>
<li><code>net.core.bpf_jit_enable</code> definida para 1 (habilita BPF JIT Compiler)</li>
</ol>
<p>Antes, vamos verificar a versão de <em>kernel</em> atual:</p>
<pre><code class="lang-bash">$ uname -r
5.4.170+
</code></pre>
<p>✅ Bom! É uma versão com suporte.</p>
<p>Verificando <code>CONFIG_BPF_JIT</code>:</p>
<pre><code class="lang-bash">$ grep CONFIG_BPF_JIT /boot/config-$(uname -r)
CONFIG_BPF_JIT_ALWAYS_ON=y
CONFIG_BPF_JIT=y
</code></pre>
<p>✅ Sim, está habilitado.</p>
<p>Verificando <code>FALCO_BPF_PROBE</code>:</p>
<pre><code class="lang-yaml">{{<span class="hljs-bullet">-</span> <span class="hljs-string">if</span> <span class="hljs-string">.Values.ebpf.enabled</span> }}
  <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">FALCO_BPF_PROBE</span>
    <span class="hljs-attr">value:</span> {{ <span class="hljs-string">.Values.ebpf.path</span> }}
{{<span class="hljs-bullet">-</span> <span class="hljs-string">end</span> }}
</code></pre>
<p>✅ Sim, o <em>template</em> se encarrega disso.</p>
<p>Verificando <code>net.core.bpf_jit_enable</code>:</p>
<pre><code class="lang-bash">$ sudo sysctl net.core.bpf_jit_enable
net.core.bpf_jit_enable = 1
</code></pre>
<p>✅ Sim, está habilitado.</p>
<h2 id="heading-instalacao">Instalação</h2>
<p>O comando abaixo utilizando Helm Chart fará a instalação necessária:</p>
<pre><code class="lang-bash">helm repo add falcosecurity https://falcosecurity.github.io/charts
helm repo update
helm install falco falcosecurity/falco --<span class="hljs-built_in">set</span> ebpf.enabled=<span class="hljs-literal">true</span>
</code></pre>
<p>Você pode conferir os objetos criados com:</p>
<pre><code class="lang-bash">$ kubectl get all -n falco
</code></pre>
<p>Onde você pode incrementar outros parâmetros para habilitar <strong>Falcosidekick</strong> com <strong>WebUI</strong> no mesmo Helm Chart:</p>
<pre><code class="lang-bash">  ...
  --<span class="hljs-built_in">set</span> falcosidekick.enabled=<span class="hljs-literal">true</span> \
  --<span class="hljs-built_in">set</span> falcosidekick.webui.enabled=<span class="hljs-literal">true</span>
</code></pre>
<p>Confira <a target="_blank" href="https://github.com/falcosecurity/charts/tree/master/falco">os parâmetros disponíveis aqui</a>.</p>
<p>E uma lista de outputs disponíveis <a target="_blank" href="https://github.com/falcosecurity/charts/tree/master/falcosidekick">para Falcosidekick aqui</a> como Google Cloud Storage, Slack, webhooks etc.</p>
<p>Obs.: você pode usar um manifesto Yaml com parâmetro <code>-f values.yaml</code> se preferir.</p>
<h3 id="heading-pronto">Pronto</h3>
<p>O que está acontecendo agora?</p>
<p>Você pode fazer um Port Forward para a UI:</p>
<pre><code class="lang-bash">kubectl port-forward svc/falco-falcosidekick-ui 2802:2802 -n falco
</code></pre>
<p>Feito! Vá ao nevegador: http://localhost:2802/ui</p>
<p>Então, você verá uma página como essa:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652134626283/I0wsTuHWs.png" alt="image.png" /></p>
<p>O conjunto de regras padrão é aplicado. Você pode evoluir a sua configuração como necessário.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1652137773902/dk6a7XFjz.gif" alt="ezgif-4-57978f90bc.gif" /></p>
<p>Se divirta! Obrigado.</p>
]]></content:encoded></item><item><title><![CDATA[Got stuck in ArgoCD sync fail]]></title><description><![CDATA[Are you an ArgoCD user? It may help you someday...
I tried to sync a new Redis version and just.
But I ended up with an error like this:

Sync operation to failed: ComparisonError: rpc error: code = Unknown desc = helm pull --destination /tmp/helm875...]]></description><link>https://blog.seiji.com.br/got-stuck-in-argocd-sync-fail</link><guid isPermaLink="true">https://blog.seiji.com.br/got-stuck-in-argocd-sync-fail</guid><category><![CDATA[Kubernetes]]></category><category><![CDATA[Devops]]></category><category><![CDATA[Cloud Computing]]></category><category><![CDATA[continuous deployment]]></category><dc:creator><![CDATA[Seiji Manoan Seo]]></dc:creator><pubDate>Wed, 27 Oct 2021 22:38:30 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1635374513858/3A9CaLVtA.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Are you an ArgoCD user? It may help you someday...</p>
<p>I tried to sync a new Redis version and just.</p>
<p>But I ended up with an error like this:</p>
<blockquote>
<p>Sync operation to failed: ComparisonError: rpc error: code = Unknown desc = <code>helm pull --destination /tmp/helm875598576 --version 15.5.2 --repo https://charts.bitnami.com/bitnami redis</code> failed signal: killed</p>
</blockquote>
<p>Yes. I've already had others. But, it doesn't go on at this time.</p>
<p>Why?</p>
<p>Look, we're aimed to follow the Kubernetes best practices and apply some rules. Say so 😅</p>
<p>The ArgoCD pods have not restarted in each and every sync error. It led me to believe it couldn't be any out of memory...</p>
<p>My bad! It's OOM issue.</p>
<p><strong>Of course, I solved this OOM issue by increasing the RAM limit.</strong></p>
<p>If you have it managed by Helm Chart, change this value to fit your needs: </p>
<pre><code class="lang-yaml"><span class="hljs-attr">repoServer:</span>
  <span class="hljs-attr">resources:</span>
    <span class="hljs-attr">limits:</span>
      <span class="hljs-attr">memory:</span> <span class="hljs-string">1Gi</span> <span class="hljs-comment"># look at here</span>
</code></pre>
<p>Apply with some <code>helm upgrade --install</code>...</p>
<p>Done. The ArgoCD settings are improved and the wanted app is ready to be synced one more time right now.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1635373866349/qfjEgB7W3.webp" alt="giphy.webp" /></p>
<p>All right. Thanks!</p>
]]></content:encoded></item><item><title><![CDATA[Alibaba Cloud: treinamentos e certificações]]></title><description><![CDATA[Você provavelmente já escutou em algum momento da sua vida que mandarim é o novo inglês? Pois, algo parecido acontece na indústria de computação na nuvem. Claro, ambos ainda produzem conteúdo em inglês. A questão dessa analogia é um surgimento e cres...]]></description><link>https://blog.seiji.com.br/alibaba-cloud-treinamentos-e-certificacoes</link><guid isPermaLink="true">https://blog.seiji.com.br/alibaba-cloud-treinamentos-e-certificacoes</guid><category><![CDATA[Cloud]]></category><category><![CDATA[Cloud Computing]]></category><category><![CDATA[Certification]]></category><dc:creator><![CDATA[Seiji Manoan Seo]]></dc:creator><pubDate>Sun, 12 Sep 2021 01:02:44 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1631407952104/NDdB4Ykv6.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Você provavelmente já escutou em algum momento da sua vida que mandarim é o novo inglês? Pois, algo parecido acontece na indústria de computação na nuvem. Claro, ambos ainda produzem conteúdo em inglês. A questão dessa analogia é um surgimento e crescimento desse provedor de nuvem pública que conquista espaço no Ocidente com uma forte contribuição e formação para a comunidade ao mesmo tempo.</p>
<p>Sabendo-se disso, fica o meu conselho: aproveitem a oportunidade para conhecer e se qualificar com esse provedor de nuvem pública sensacional!</p>
<p>Até 12/09, no horário de Beijing (GMT+8), você pode responder a uma enquete de como a Alibaba Cloud pode desenvolver a sua carreira. Assim, concorrer a um ano de acesso gratuito à plataforma <a target="_blank" href="https://edu.alibabacloud.com/">Academy</a>. <a target="_blank" href="https://survey.alibabacloud.com/apps/zhiliao/PjAJj7fvK">Clique aqui para responder ao formulário</a>.</p>
<p>Não para por aí. Você pode participar do desafio e ganhar um voucher para certificação "na faixa". Escolha uma das trilhas e complete os seus desafios. Terá duas rodadas:</p>
<ul>
<li>31 de agosto a 13 de setembro;</li>
<li>14 de setembro a 27 de setembro.</li>
</ul>
<p>A proposta é cumprir o desafio em 14 dias. Para mais informações, confira a página oficial e comece o quanto antes: https://edu.alibabacloud.com/certification/aca_cloud</p>
<blockquote>
<p>Toda informação foi disponibilizada publicamente pela Alibaba Cloud e é sob responsabilidade da mesma. Confira as regras oficiais nas páginas oficiais.</p>
</blockquote>
]]></content:encoded></item></channel></rss>