<?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>DEV Community: driftctl</title>
    <description>The latest articles on DEV Community by driftctl (@driftctl).</description>
    <link>https://dev.to/driftctl</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%2F523783%2Fd5ef8523-691a-4a11-82b1-f735f53b0910.png</url>
      <title>DEV Community: driftctl</title>
      <link>https://dev.to/driftctl</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/driftctl"/>
    <language>en</language>
    <item>
      <title>Security Group Rules : small changes, bitter consequences</title>
      <dc:creator>driftctl</dc:creator>
      <pubDate>Wed, 05 May 2021 07:26:40 +0000</pubDate>
      <link>https://dev.to/driftctl/security-group-rules-small-changes-bitter-consequences-4h59</link>
      <guid>https://dev.to/driftctl/security-group-rules-small-changes-bitter-consequences-4h59</guid>
      <description>&lt;h2&gt;
  
  
  How a simple manual change in an AWS Security Group using the AWS Web Console can have bitter security consequences
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0GIOoui3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/5002/1%2AASPBhrkU3gNrEtT6mcXyUg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0GIOoui3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/5002/1%2AASPBhrkU3gNrEtT6mcXyUg.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this article, we’ll show how a simple manual change in an AWS Security Group using the AWS Web Console can have bitter security consequences. This one is based on many first-hand experiences and user feedback, in a production context with infrastructure-as-code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Allowing PgSQL (with Terraform)
&lt;/h2&gt;

&lt;p&gt;For this article, we’ll take the example recently experienced by a team we know. They secured access to their PgSQL instances with this simple Terraform configuration, allowing only the web servers subnet:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Secure the PgSQL RDS cluster using a dedicated SG
resource "aws_security_group" "pgsql" {
  name        = "PgSQL Security Group"
  description = "PgSQL Security Group"

  tags = {
    Name = "PgSQL Security Group"
  }
}

// PgSQL can only be accessed from the WWW network (10.0.0.0/8)
resource "aws_security_group_rule" "pgsql" {
  type              = "ingress"
  from_port         = 5432
  to_port           = 5432
  protocol          = "tcp"
  cidr_blocks       = ["10.0.0.0/8"]
  security_group_id = aws_security_group.pgsql.id
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;They had a scheduled terraform plan as a GitHub Action for the whole infrastructure, so if something changed, it was reported right away. The “GitOps” workflow also included some linters, a terraform plan, followed by a terraform apply after a merge on the main branch.&lt;/p&gt;

&lt;p&gt;It worked well and satisfied the initial basic security requirements. Good job!&lt;/p&gt;

&lt;h2&gt;
  
  
  That one Security Group temporary change
&lt;/h2&gt;

&lt;p&gt;A couple of years later, to win a new major customer, they agreed to allow a pentesting audit. Long story short, one auditor was pentesting from the internet, while the other worked from different internal networks of the company.&lt;/p&gt;

&lt;p&gt;Oddly enough, they didn’t come back with the same results: the external audit came clean, while the internal one basically opposed a strict “no-go” to the commercial deal. Reason: the auditor reported he gained access to every customer database in a matter of minutes. With proof.&lt;/p&gt;

&lt;p&gt;How could it happen?&lt;/p&gt;

&lt;p&gt;One day, someone from the team needed to quickly test something on a customer database who experienced a bug. A single value to change. Going through the hassle of switching to the secure network, then connecting to the corporate VPN, then going through the Bastion using a smartcard for authentication, probably also having to explain soon to the security team why he connected and what he did…this was definitely too much. Especially when he could simply allow the company’s office outgoing IPv4 on the “PgSQL” security group! And remove it after the change. Moreover, he would &lt;em&gt;necessarily&lt;/em&gt; remember about it, as all the Security Groups were 100% managed by Terraform on CI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SvejnXJW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2AvCF8_i3Mm2YUzH-F" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SvejnXJW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2AvCF8_i3Mm2YUzH-F" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And it worked well! That team member fixed the customer issue in the database quickly.&lt;/p&gt;

&lt;p&gt;And forgot to remove the security group rule, until it was discovered by the auditor, so that he could:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;connect painlessly to the customer databases from the office&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;then easily find passwords using a tool like &lt;a href="https://tools.kali.org/password-attacks/hydra"&gt;hydra&lt;/a&gt; against PostgreSQL.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;profit.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  How we ended up there?
&lt;/h2&gt;

&lt;p&gt;Here’s the context in which this team worked:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;a team member had AWS Web Console credentials large enough to make Security Group changes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;they assumed Security Group Rules were represented similarly on AWS and Terraform&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;they wrote their Security Groups rules a certain way using Terraform&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can’t do much about the first issue: it’s the harsh reality of most companies today. Surely enough they need to adopt a proper full GitOps workflow, but most aren’t there yet (and won’t be for a while).&lt;/p&gt;

&lt;h2&gt;
  
  
  The lists are not what they seem
&lt;/h2&gt;

&lt;p&gt;The second assumption is confusing because of what can the UI lead you to believe. As developers, we know that cidr_blocks = ["10.0.0.0/8"] is a list and that adding an element to it will make it different.&lt;/p&gt;

&lt;p&gt;As a developer, I can also easily believe that such a design in the AWS Console would also generate a list, both IPs are listed under the same line, exactly as if I read ["10.0.0.0/8", "96.202.220.106/32"]:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yBqGY-a6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2ADUQRua9yNyn3ncYg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yBqGY-a6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2ADUQRua9yNyn3ncYg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The thing is, in the end, on the AWS side, they really are two elements of a list, but in the Terraform model, they end up being two distinct resources and not two elements. This difference in models between the cloud provider and Terraform can sometimes be misleading for users and can have major consequences.&lt;/p&gt;

&lt;h2&gt;
  
  
  The way you write your Terraform matters
&lt;/h2&gt;

&lt;p&gt;The third and final situation here is the way the Terraform configuration was written.&lt;/p&gt;

&lt;p&gt;Can you guess what happened in CI for months after the manual change wasn’t reverted? Nothing.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ terraform apply
aws_security_group.pgsql: Refreshing state... [id=sg-0b6af725ba7e7691b]
aws_security_group_rule.pgsql: Refreshing state... [id=sgrule-3696232291]

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;To be more precise, something happened. The manual Security Group rule change was added without anyone being notified about it in the terraform.tfstate right when the next terraform apply ran in CI:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"ingress": [
              {
                "cidr_blocks": [
                  "10.0.0.0/8"
                ],
                "description": "",
                "from_port": 5432,
                "ipv6_cidr_blocks": [],
                "prefix_list_ids": [],
                "protocol": "tcp",
                "security_groups": [],
                "self": false,
                "to_port": 5432
              },
              {
                "cidr_blocks": [
                  "96.202.220.106/32"
                ],
                "description": "",
                "from_port": 5432,
                "ipv6_cidr_blocks": [],
                "prefix_list_ids": [],
                "protocol": "tcp",
                "security_groups": [],
                "self": false,
                "to_port": 5432
              }
            ], 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Yes, you will end up with a Terraform state with way more information and resources than you intended from the code, as the Terraform state job is not to represent your intention, but to &lt;a href="https://www.terraform.io/docs/language/state/purpose.html"&gt;map the real world with your config&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The way Security Group Rules were written couldn’t help discovering the change (not to mention notifying anyone). You could add a billion rules and it would be the same.&lt;/p&gt;

&lt;p&gt;Fortunately, in this case, if you read Terraform’s documentation for the AWS provider (currently v3.36), you’ll find 2 options to configure Security Groups:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Use the &lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group"&gt;aws_security_group&lt;/a&gt; resource with inline egress {} and ingress {} blocks for the rules.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use the &lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group"&gt;aws_security_group&lt;/a&gt; resource with additional &lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule"&gt;aws_security_group_rule&lt;/a&gt; resources.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In this case, using the first option would have been better for this team, from a more DevSecOps point of view. See how the next terraform apply in CI would have had the expected effect:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ terraform apply
aws_security_group.pgsql: Refreshing state... [id=sg-03a12201c68c38d92]

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  # aws_security_group.pgsql will be updated in-place
  ~ resource "aws_security_group" "pgsql" {
        id                     = "sg-03a12201c68c38d92"
      ~ ingress                = [
          - {
              - cidr_blocks      = [
                  - "96.202.220.106/32",
                ]
              - description      = "Allow PgSQL from WWW"
              - from_port        = 5432
              - ipv6_cidr_blocks = []
              - prefix_list_ids  = []
              - protocol         = "tcp"
              - security_groups  = []
              - self             = false
              - to_port          = 5432
            },
            # (1 unchanged element hidden)
        ]
        name                   = "PgSQL Security Group"
        tags                   = {
            "Name" = "PgSQL Security Group"
        }
        # (6 unchanged attributes hidden)
    }

Plan: 0 to add, 1 to change, 0 to destroy.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Unfortunately, it’s often too late when you realize it, and this kind of option doesn’t exist for every resource out there. What was a DevOps discussion (&lt;em&gt;“let’s automate those deployments and ship that on CI!”&lt;/em&gt;) can quickly become a DevSecOps discussion now (&lt;em&gt;“how should we write our Terraform configuration according to our goals?”&lt;/em&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  The driftctl option
&lt;/h2&gt;

&lt;p&gt;That’s why using driftctl is always a good option. As the tool compares your Terraform state to the reality of your AWS account, you can deploy the tool at 2 important places of your workflow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;as a scheduled run (like an hourly cronjob), so you get reports when something changes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;as a pre-condition to a terraform apply step in CI: so you ensure you’re working with an unmodified Terraform state (as by design the refresh part of the apply can modify it). You may also want to parallelize this driftctl step with a terraform plan.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here’s a driftctl run when the activity is as expected on the AWS account:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ driftctl scan
Scanned resources:    (54)
Found 2 resource(s)
 - 100% coverage
Congrats! Your infrastructure is fully in sync.
$ echo $?
0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here’s a driftctl run with the above manual change:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ driftctl scan
Scanned resources:    (55)
Found resources not covered by IaC:
  aws_security_group_rule:
    - Type: ingress, SecurityGroup: sg-0ce251e7ce328547d, Protocol: tcp, Ports: 5432, Source: 96.202.220.106/32
Found 3 resource(s)
 - 66% coverage
 - 2 covered by IaC
 - 1 not covered by IaC
 - 0 missing on cloud provider
 - 0/2 changed outside of IaC
$  echo $?
1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This output clearly shows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;a resource NOT on the Terraform state, of type aws_security_group_rule, for the Security Group sg-0ce251e7ce328547d, that allows TCP/5432 for 96.202.220.106/32. This should trigger an alarm!&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;some metrics for your own reference.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This output can be exported as JSON too, so you can easily manipulate it and integrated it into your other tools and notification systems. There’s a ton of other options and integrations you can use with driftctl, but that will be for another article!&lt;/p&gt;

&lt;p&gt;Reference:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://driftctl.com/"&gt;driftctl.com&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/cloudskiff/driftctl"&gt;driftctl GitHub&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.driftctl.com/"&gt;driftctl Documentation&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Terraform AWS Provider resources documentation: &lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group_rule"&gt;aws_security_group_rule&lt;/a&gt; and &lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/security_group"&gt;aws_security_group&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devops</category>
      <category>devsecops</category>
      <category>terraform</category>
      <category>infrastructureascode</category>
    </item>
    <item>
      <title>Codecov bash uploader security issue</title>
      <dc:creator>driftctl</dc:creator>
      <pubDate>Tue, 04 May 2021 15:42:34 +0000</pubDate>
      <link>https://dev.to/driftctl/codecov-bash-uploader-security-issue-2b7e</link>
      <guid>https://dev.to/driftctl/codecov-bash-uploader-security-issue-2b7e</guid>
      <description>&lt;h2&gt;
  
  
  Codecov bash uploader security issue
&lt;/h2&gt;

&lt;h4&gt;
  
  
  How minimizing our attack surface with CircleCI Contexts helped us pass the Codecov bash uploader security issue unharmed
&lt;/h4&gt;

&lt;h2&gt;
  
  
  What is Codecov
&lt;/h2&gt;

&lt;p&gt;For those who don’t know Codecov, it is an online platform for hosted code coverage reports and statistics founded in 2014. According to their website, over 29,000 organizations and more than 1 million developers use their tools. The list includes Google, Atlassian, The Washington Post, RBC, and Procter &amp;amp; Gamble Co.&lt;/p&gt;

&lt;p&gt;Its main tool, the Bash Uploader, is used to send code coverage reports to the platform. Those reports help developers measure how well their source code is covered by tests. This is the main reason why it is widely used among developers and organizations.&lt;/p&gt;

&lt;h2&gt;
  
  
  What about the breach?
&lt;/h2&gt;

&lt;p&gt;On April 15th, 2021, Codecov reported in a press release that someone had gained unauthorized access to its script and modified it without its permission.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“Our investigation has determined that beginning Jan. 31, 2021, there were periodic, unauthorized alterations of our Bash Uploader script by a third party, which enabled them to potentially export information stored in our users’ continuous integration environments. This information was then sent to a third-party server outside of Codecov’s infrastructure”&lt;/em&gt; the company said.&lt;/p&gt;

&lt;p&gt;According to Codecov, the hacker gained access to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Any credential, token, or key that customers passed through their continuous integration runner that would be accessible when the Bash Uploader script was executed;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Any service, datastore, and application code that could be accessed with these credentials, tokens, or keys;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The git remote information (URL of the origin repository) of repositories using the Bash Uploader to upload coverage to Codecov in their continuous integration.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For those potential threats, Codecov is strongly encouraging developers to immediately re-roll all of their credentials, tokens, or keys located in the environment variables in their CI process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why are we safe from that at CloudSkiff?
&lt;/h2&gt;

&lt;p&gt;We use CircleCI to continuously build, test and deploy our open-source drift detection CLI, &lt;a href="https://github.com/cloudskiff/driftctl"&gt;driftctl&lt;/a&gt;. Like most projects, we need to manipulate sensitive environment variables which could mean that this event could impact us.&lt;/p&gt;

&lt;p&gt;But, &lt;a href="https://circleci.com/"&gt;CircleCI&lt;/a&gt; provides a simple and secure way to store and share those sensitive environment variables across projects and jobs (or pipelines, or steps in other CI), it is called &lt;a href="https://circleci.com/docs/2.0/contexts/"&gt;a context&lt;/a&gt;. As an Organization in CircleCI, you can, in your settings, create and manage contexts.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--D_PwXNiO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2AqGttjueM5xdLQgnG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--D_PwXNiO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2AqGttjueM5xdLQgnG" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can use the context key in the workflows section of a project config.yml file to give any jobs access to the environment variables associated with the context.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: 2.1

# Jobs declaration for build, test and deploy not displayed

workflows:
  build-test-deploy:
    jobs:
      - build
      - test
      - deploy:
          context: restricted-context
          requires:
            - build
            - test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In the example above, only the deploy job has access to the environment variables created in the restricted-context context. On the other hand, the build and test jobs don’t have any access to the sensitive variables in their execution.&lt;/p&gt;

&lt;p&gt;That’s basically what we do as of today in our CircleCI config.yml file. Every time we need to call our test job to execute the Codecov Bash Uploader script (e.g. every push, pull request, and release workflows), since we don’t attach any context to it, the hacker has no access to our secret variables.&lt;/p&gt;

&lt;p&gt;We try to keep our jobs as small as possible to reduce the attack surface by separating concerns, and CircleCI context is well suited to assist in this good practice.&lt;/p&gt;

&lt;h2&gt;
  
  
  We could have avoided that threat
&lt;/h2&gt;

&lt;p&gt;One way we could have avoided that is the same way Codecov started investigating the attack. The company reported on the morning of April 1, 2021, that one customer was using the shasum that is available on its Bash Uploader to confirm the integrity of the uploader fetched from &lt;a href="https://codecov.io/bash"&gt;https://codecov.io/bash&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Indeed, as stated on its documentation website, “it can be validated for correctness by calculating the shasum on download and comparing to the result we store in the GitHub repository”.&lt;/p&gt;

&lt;p&gt;An example could be:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ curl -s -o codecov https://codecov.io/bash \
&amp;amp;&amp;amp; VERSION=$(grep 'VERSION=\".*\"' codecov | cut -d'"' -f2) \
&amp;amp;&amp;amp; shasum -a 512 -c --ignore-missing &amp;lt;(curl -s [https://raw.githubusercontent.com/codecov/codecov-bash/${VERSION}/SHA512SUM)](https://raw.githubusercontent.com/codecov/codecov-bash/${VERSION}/SHA512SUM))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This simple script could be run on each test job before running the Bash Uploader. If we were doing it that way we could have seen sooner the hack, and we could have reported it sooner to Codecov.&lt;/p&gt;

&lt;p&gt;Our final test job looks like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test:
docker:
  - image: golang:1.16
steps:
  - checkout
  - run: make install-tools
  - run: make test
  - run:
      name: Check Codecov
      command: |
        curl -s -o codecov https://codecov.io/bash \
          &amp;amp;&amp;amp; VERSION=$(grep 'VERSION=\".*\"' codecov | cut -d'"' -f2) \
          &amp;amp;&amp;amp; shasum -a 512 -c --ignore-missing &amp;lt;(curl -s https://raw.githubusercontent.com/codecov/codecov-bash/${VERSION}/SHA512SUM)
  - run:
      name: Codecov upload
      command: |
        chmod +x codecov
        ./codecov
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Driftctl is a &lt;strong&gt;free and open-source&lt;/strong&gt; CLI that &lt;strong&gt;tracks, analyzes, prioritizes, and warns of infrastructure drift&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://driftctl.com/?utm_source=medium&amp;amp;utm_medium=medium&amp;amp;utm_campaign=medium"&gt;More info about us&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Reference:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://about.codecov.io/security-update/"&gt;Codecov Press Release&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://circleci.com/docs/2.0/contexts/"&gt;CircleCI Context&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devops</category>
    </item>
    <item>
      <title>Our commitments to the community</title>
      <dc:creator>driftctl</dc:creator>
      <pubDate>Thu, 18 Mar 2021 13:28:50 +0000</pubDate>
      <link>https://dev.to/driftctl/our-commitments-to-the-community-mh2</link>
      <guid>https://dev.to/driftctl/our-commitments-to-the-community-mh2</guid>
      <description>&lt;h2&gt;
  
  
  Here’s why we bring a new open source DevOps tool
&lt;/h2&gt;

&lt;p&gt;As we celebrated the initial release of &lt;a href="https://github.com/cloudskiff/driftctl"&gt;driftctl&lt;/a&gt; 3 months ago, we certainly hoped for some sort of acknowledgement or favorable opinion from those who would use it, but we were not prepared for such a warm welcome.&lt;/p&gt;

&lt;p&gt;Reflecting on the first steps of the project, the fast moving star history and the contributions and interactions we have benefited from, we are both grateful and humbled by the support we receive from the open source community.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--atiHSgwE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2ACfVgh9gT2m0KXlf7" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--atiHSgwE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2ACfVgh9gT2m0KXlf7" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why we launched this DevOps tool in the first place
&lt;/h2&gt;

&lt;p&gt;At CloudSkiff, we are all fans of GitOps. We are big believers in the power of Infrastructure as Code and all its benefits.&lt;/p&gt;

&lt;p&gt;We like it so much that we decided to build a tool to help DevOps, SREs, infrastructure teams and all cloud practitioners, collaborate over Infrastructure as Code. As a team, we’re a bunch of seasoned people and we all gathered a lot of experience on cloud infrastructures automation. But we wanted to know more. We wanted to make sure that what we were building was truly helping.&lt;/p&gt;

&lt;p&gt;So we decided to talk to as many people as possible. We interviewed dozens of IaC practitioners across several geographies: teams of various sizes, levels of expertise, and cloud automation progress status. They all had one thing in common: because Ops life is what it is, and despite their best efforts and process, they had a hard time reconciling their infrastructure code with the reality of their IaaS accounts. They were facing issues with drift.&lt;/p&gt;

&lt;p&gt;Drift can be driven by human input, poor configuration, applications making unwanted changes, etc. It has consequences on toil and efficiency, forces teams to put in place strict controls that decrease flexibility, and can have security and compliance impacts. Even as an experienced Terraform user, as your infrastructure team and codebase grows, it often becomes harder to track drift.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2U6Jf9zL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2A6xDhFlag-yyUEXr6" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2U6Jf9zL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2A6xDhFlag-yyUEXr6" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Of course, we knew about drift, having oftentimes faced it ourselves, but we were not aware that it was such a widespread issue. So we decided to try and bring a solution to this problem with &lt;a href="https://driftctl.com/product"&gt;driftctl, a free and open-source CLI&lt;/a&gt; that tracks, analyzes, prioritizes, and warns of infrastructure drift.&lt;/p&gt;

&lt;h2&gt;
  
  
  What OSS means to us and why we went open source in the first place.
&lt;/h2&gt;

&lt;p&gt;Being part of the DevOps ecosystem, we are very close to a community of tools situated within the &lt;a href="https://www.cncf.io/"&gt;Cloud Native Computing Foundation&lt;/a&gt;’s orbit. Those of you who had a glimpse at its landscape know that the CNCF drives a thriving ecosystem of tools in its wake, some of them open source.&lt;/p&gt;

&lt;p&gt;Major open source projects such as Kubernetes, OPA (Open Policy Agent), Chef, Puppet, Ansible, Istio… paved the way for us and it was only natural to be in keeping with this trend and give back to the community.&lt;/p&gt;

&lt;p&gt;But beyond that, it is our firm belief that an open source first approach is key not only to the widest diffusion of a solution to an issue, but more importantly to the best and most comprehensive elaboration of this solution.&lt;/p&gt;

&lt;p&gt;Being only 3 month old, driftctl already benefits from contributions from all over the world with major commits, issues and discussions from Asia, Europe, North America… Only truly open projects can federate such goodwill and efficiency.&lt;/p&gt;

&lt;p&gt;This is why we released driftctl under the &lt;a href="https://github.com/cloudskiff/driftctl/blob/main/LICENSE.md"&gt;Apache 2.0&lt;/a&gt; license, and we already gathered the best retributions out of it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Z_IDNu0R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2ANRNa-DQXPbBYJaR7" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Z_IDNu0R--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2ANRNa-DQXPbBYJaR7" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mCJYFFrW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2Ai5jyRBtvPob897Jq" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mCJYFFrW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2Ai5jyRBtvPob897Jq" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Our commitments to the open source community.
&lt;/h2&gt;

&lt;p&gt;In concrete terms, what does it mean for us to be an open source project? Well, being OSS means first and foremost transparency and sharing:&lt;/p&gt;

&lt;h3&gt;
  
  
  1) Full transparency from master to release
&lt;/h3&gt;

&lt;p&gt;Obviously, our code is open source. But it is important to us that the on-going developments are also made publicly available. Anyone who wants to know what’s cooking can &lt;a href="https://github.com/cloudskiff/driftctl/pulls?q=is%3Aopen"&gt;access master, and see real “work in progress” on our code&lt;/a&gt; and not some copy/paste of a finished version waiting to be released from a private repo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fIvTj3iA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2A__YHo1HjqsZRuFvg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fIvTj3iA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2A__YHo1HjqsZRuFvg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2) Live coding sessions
&lt;/h3&gt;

&lt;p&gt;Because we like coding and sharing, we open live coding sessions on a regular basis. Almost daily, anyone on our &lt;a href="https://discord.gg/NMCBxtD7Nd"&gt;community discord server&lt;/a&gt; and/or &lt;a href="https://www.twitch.tv/driftctl"&gt;on Twitch&lt;/a&gt; can see someone from the engineering team live coding and sharing his screen. Feel free to come say “Hi!”.&lt;/p&gt;

&lt;h3&gt;
  
  
  3) Live release demos
&lt;/h3&gt;

&lt;p&gt;Transparency also means showing and discussing what we do, which is why each major release comes with a live release demo where we showcase new features, discuss the most interesting issues we had, and talk about what is coming next on the roadmap. Those releases happen on Twitch and &lt;a href="https://www.youtube.com/channel/UCqUCM6vQKkq08amsqf_vKzg"&gt;YouTube live&lt;/a&gt; and are available on replay.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4WF9Wxyy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2Afzgfm3SwB0k2Kbxm" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4WF9Wxyy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2Afzgfm3SwB0k2Kbxm" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4) Live chats within the engineering team
&lt;/h3&gt;

&lt;p&gt;Being a remote first (and remote only) organization, we do not have any offices or headquarters, which means that any member from the Engineering team can work from any place of his/her liking and that sync and async communication is paramount.&lt;/p&gt;

&lt;p&gt;While most of the asynchronous communication within the team goes through our GitHub repositories where we store and share all of our resources, we found that a simple engineering chat does the trick to ensure live exchanges within the team whenever we need to work together on something, or even often do some pair programming. Those chats are also publicly accessible to all on our community discord server.&lt;/p&gt;

&lt;h3&gt;
  
  
  5) Open issues and roadmap discussions
&lt;/h3&gt;

&lt;p&gt;Our foreseeable roadmap is accessible to all in the ROADMAP.md file on GitHub. All issues (internal and external) are also listed and accessible on this account. Anyone can join in a discussion to propose or upvote a feature.&lt;/p&gt;

&lt;p&gt;Indeed, we also try to prioritize items on the roadmap according to the feedback we get. Typically, so far driftctl supports both the AWS and the GitHub providers and we see a lot of discussions around which provider should come next (Azure or GCP). You are welcome to &lt;a href="https://github.com/cloudskiff/driftctl/discussions"&gt;take part to the vote here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  6) Extended support time frame
&lt;/h3&gt;

&lt;p&gt;In this early phase of the project, it is critical that we clearly understand what people expect from the tool, how they use it and what kind of issues they face (not to mention the usual early phase debugging period…). This is why &lt;strong&gt;we are extremely grateful for any feedback, any question, any suggestion&lt;/strong&gt; from our users.&lt;/p&gt;

&lt;p&gt;Being still a young organization with limited geographical outreach we decided to set up support on call rotation within the team to cover as many time zones across the globe as possible, and make sure we make the most out of each interaction we can get on our community discord server. This is why you are sure to have someone answering your questions from 7:00 am to 11:00 pm CET.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s coming next?
&lt;/h2&gt;

&lt;p&gt;While we know that there are a lot more actions to take, so far we’ve sincerely tried to do our best to share our project with the open source community.&lt;/p&gt;

&lt;p&gt;Raising awareness on the issue is one of our very strong focuses. Over the last months, we were lucky enough to be invited to talk about drift issues at some major conferences, such as Fosdem, Hashitalks or the CNCF London meetup and it was really great to share our views and experience on this topic. For those who would like to catch up, &lt;a href="https://driftctl.com/replays"&gt;most of the talks are accessible on replay&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As we move forward in the process of building driftctl, we frequently discover new potential security threats due to forgotten or unnoticed changes on infrastructures. This is why our next efforts will be centered on demonstrating how teams need to complement their DevSecOps Day 2 toolbox and how ensuring the parity of their code and their infras is a prerequisite to shifting security to the left.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>terraform</category>
      <category>infrastructureascode</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Infrastructure drifts aren’t like Pokemons…
…You can’t catch ’em all</title>
      <dc:creator>driftctl</dc:creator>
      <pubDate>Wed, 03 Mar 2021 10:01:15 +0000</pubDate>
      <link>https://dev.to/driftctl/infrastructure-drifts-aren-t-like-pokemons-you-can-t-catch-em-all-ei6</link>
      <guid>https://dev.to/driftctl/infrastructure-drifts-aren-t-like-pokemons-you-can-t-catch-em-all-ei6</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--H6t1-ZSG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/1%2ATQHSjLOzeZoR8ULN2UxNNA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--H6t1-ZSG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/1%2ATQHSjLOzeZoR8ULN2UxNNA.png" alt="This blog post is a written transcript of the FOSDEM Talk: “Infrastructure drifts aren’t like Pokemon, you can’t catch ’em all”, by Stephane Jourdan — CTO and founder"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This talk covers three major topics:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Infrastructure as Code: all the good intentions and the ideal world each of us expected when we started using it, and how it’s actually going in everyday’s Ops life. We will see that how it started is probably different from how it is going and from what we expected.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We will then “drift” together, using Terraform and AWS and share some war stories that we heard from infrastructure teams, and how things sometimes went really wrong for them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We will finally present driftctl, our open source answer to infrastructure drift problems.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Infrastructure drift: definition
&lt;/h2&gt;

&lt;p&gt;Let’s first agree on what is infrastructure drift: infrastructure drift is what happens when the reality of your infrastructure doesn’t match your expectations. This phenomenon is also known as &lt;em&gt;**“Oh my god” *&lt;/em&gt;*in production when things unexpectedly go wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  Infrastructure as code: an ideal world
&lt;/h2&gt;

&lt;h4&gt;
  
  
  How it all started
&lt;/h4&gt;

&lt;p&gt;When it all started, we had this vision of an ideal world, and a bright future that Infrastructure as Code was to offer us, like Plato’s Republic was for society a while ago.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FiJd6uJ4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2AIQkK_hV-TuN3QPaq" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FiJd6uJ4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2AIQkK_hV-TuN3QPaq" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With Infrastructure as code, we were supposed to have one single source of truth (the state file in the case of Terraform).&lt;/p&gt;

&lt;p&gt;We were supposed to have versioning of the code with git. The code was to be so great that it would be self-documenting.&lt;/p&gt;

&lt;p&gt;In this ideal world, we would have testing everywhere: on the pipelines before and after tdd and bdd etc, like the rest of engineering. Collaboration would be a bliss between teams. Infrastructure would be immutable: we could scale it up and down and throw the rest away.&lt;/p&gt;

&lt;p&gt;GitOps would be everywhere: CI/CD for infrastructure, no more locally running things. And basically all the credentials would be under control and multi-cloud would solve all our problems because you know what they say: “API everywhere”… and we would have the skills to handle all those APIs, and the time to do this greatly.&lt;/p&gt;

&lt;h4&gt;
  
  
  How it is actually going
&lt;/h4&gt;

&lt;p&gt;Marcus Aurelius, the roman emperor a few centuries after Plato wrote to himself: &lt;strong&gt;“Do not expect Plato’s ideal Republic”&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;As it happens we are not Roman emperors but our ideal Republic is not to be expected either. How it started is not exactly how we see it going.&lt;/p&gt;

&lt;p&gt;In our team, many of us were quite experienced but we wanted more feedback on what we were building. So we just asked hundreds of infrastructure teams, SREs… etc around the world where they were standing in their Infrastructure as Code journey.&lt;/p&gt;

&lt;p&gt;Basically what they told us was that changes were still happening outside of their Infrastructure as Code: mainly manual changes and scripts that are changing tags, or lambdas updating things after deployment, etc… &lt;/p&gt;

&lt;p&gt;A lot of changes are still happening outside of their Infrastructure as Code scope, be it Terraform or Pulumi or whatever infrastructure tool they use, it doesn’t matter.&lt;/p&gt;

&lt;blockquote&gt;
&lt;h1&gt;
  
  
  &lt;em&gt;Do not expect Plato’s ideal Republic&lt;/em&gt;
&lt;/h1&gt;
&lt;h1&gt;
  
  
  &lt;em&gt;Marcus Aurelius&lt;/em&gt;
&lt;/h1&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  A bunch of other things go wrong for them as well.
&lt;/h4&gt;

&lt;p&gt;The scope of their changes is not very often fully committed because of broken processes.&lt;/p&gt;

&lt;p&gt;People are still changing things manually on their AWS web console and then backporting the changes in Terraform until Terraform starts “screaming”, which means that people are still running Terraform locally with the right access keys on their own laptop. Terrible processes… and everybody knows that once you click everywhere on your console, a lot of other things are deployed on the background and so your Terraform code doesn’t reflect exactly what’s actually deployed online.&lt;/p&gt;

&lt;p&gt;Many people we talked to were aware of the good practices about testing requirements. They knew frameworks like Terratest, etc… but most of them never had the time to either learn or write those tests. Sometimes they were just too costly to run for them.&lt;/p&gt;

&lt;p&gt;The lack of communication obviously makes things worse: even in these Covid19 times, “Async” communication is still a major issue between teams.&lt;/p&gt;

&lt;p&gt;Immutable infrastructure also is still a great struggle to achieve. A lot of the new projects are running more or less around this principle, but people also still have legacy to deal with, like thousands of VMs running every day.&lt;/p&gt;

&lt;p&gt;Lots of people are still gaining console access. And guess what ? &lt;strong&gt;&lt;em&gt;People with AWS console access tend to change things&lt;/em&gt;&lt;/strong&gt; unless you lock them down completely, which is sometimes just not possible because they are your boss or your customer, or because they are “this very special co-worker” who needs to do “that special thing” manually on the web console… That’s where problems happen.&lt;/p&gt;

&lt;p&gt;Many people are also facing skill issues. For example, if a full team very skilled on GCP has a new project that for some reason needs to run on Azure, as all the specifics of this provider are not immediately mastered, they often end up with bad practices in their Infrastructure as Code deployments.&lt;/p&gt;

&lt;p&gt;And basically for lots of them, everything that has an API is still not under infrastructure code: we heard terrible stories about GitHub accesses, or DNS records or anything that can be used with Terraform that wasn’t yet by far deployed with it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--L9XiNgoG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2Aj1nAyzurCB2za3PJ" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--L9XiNgoG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2Aj1nAyzurCB2za3PJ" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Drift happens
&lt;/h2&gt;

&lt;p&gt;All those behaviors have something in common: they generate drift. While drift is pretty cool for cars, the discrepancy between intention and reality can lead to major issues, disasters, or security misconfiguration.&lt;/p&gt;

&lt;p&gt;Drift can be a real major pain. To deal with it, most of the people that we met put something in place like terraform plan and apply in a cron tab or in CI/CD somewhere before and after some commits, but were still missing things.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ terraform apply
Apply complete! Resources: 0 added, 0 changed, 0 destroyed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;We love Terraform and all Hashicorp products.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Terraform is an excellent provisioner but it’s not fair to use it for something it’s not meant to do. If anything is outside its scope, it’s just normal that Terraform doesn’t catch it. There are a lot of changes that cannot be seen by Terraform.&lt;/p&gt;

&lt;p&gt;Many of us expected terraform plan in cron tabs or in CI/CD to report changes because some of the resources were managed by it, but unfortunately as we are going to see, it is not always the case.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stories from the trenches
&lt;/h2&gt;

&lt;p&gt;The following stories are based on real stories that we heard while interviewing infrastructure teams. We simplified them to make them easy to understand with some code.&lt;/p&gt;

&lt;h4&gt;
  
  
  How an intern with read-only access ended up with rogue administrative access and keys (without anyone noticing)
&lt;/h4&gt;

&lt;p&gt;The first story is about an intern with read-only access, ending up with access keys controlled by no one. Those keys were linked to an administrative policy, which nobody noticed.&lt;/p&gt;

&lt;p&gt;To gain a better understanding of this story, let’s look at this very simple Terraform configuration file:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--opXrJBlO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2AuaiUDSAsswlVeCZm" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--opXrJBlO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2AuaiUDSAsswlVeCZm" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have a user with a key and a policy attachment for read-only.&lt;br&gt;
Let’s apply this configuration:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ terraform apply
Apply complete! Resources: 9 added, 0 changed, 0 destroyed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now let’s move to the AWS console: here we can see again this intern user and the key that was created by our own code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fl4GrWpO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2A5RID3gTlHu9JUluv" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fl4GrWpO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2A5RID3gTlHu9JUluv" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The story goes like this:&lt;/p&gt;

&lt;p&gt;This intern went to the DevOps folks and complained that he couldn’t use his key for whatever reason. The team was in a rush, so they quickly logged in to the management console, they deactivated the first key and created a new one, perfectly sure they were going to remember it and add it to Terraform in just a few moments.&lt;/p&gt;

&lt;p&gt;On top of that, Terraform was to notify them if they forgot anyway.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--v7mOmApq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2AKXXSJiKuu8arjpl0" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--v7mOmApq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2AKXXSJiKuu8arjpl0" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What do you think happened? Let’s check with a terraform apply on this user.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ terraform apply
Apply complete! Resources: 0 added, 0 changed, 0 destroyed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Basically nothing…&lt;/p&gt;

&lt;p&gt;While this very simple use case may have led you to think that this specific key and user would be noticed and reported it was not the case.&lt;/p&gt;

&lt;p&gt;So the story continues with this intern:&lt;/p&gt;

&lt;p&gt;The intern comes back one hour later complaining that he still couldn’t do what he needed to do. As the infrastructure team did not have the time to look into it, they just gave him administrative access so that he could change whatever he needed to, thinking they would revert through his permissions quickly after.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9E1KBFmo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2AVOCuUcNjx_CWDq3N" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9E1KBFmo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2AVOCuUcNjx_CWDq3N" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What do you think Terraform found in this case with a terraform apply , as we have a policy attached to the IAM user and everything is managed by terraform?&lt;/p&gt;

&lt;p&gt;This team was sure that this was to be reported in terraform plan or terraform apply. But it wasn’t the case because basically it’s out of the control of Terraform. It’s just an attached resource, it doesn’t work like that.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ terraform apply
Apply complete! Resources: 0 added, 0 changed, 0 destroyed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;So the team forgot about it, they went on with the day and it was only weeks after that they realized they had an intern with an administrative key out there in the wild, uncontrolled by anyone, not even mentioned as “deactivated” on the code.&lt;/p&gt;

&lt;h4&gt;
  
  
  How an intern with rogue Administrative access opened everything to anyone on IPv4 and IPv6 (still without anyone noticing)
&lt;/h4&gt;

&lt;p&gt;The next story starts with a process: as you know, you can have lambdas, scripts etcetera that have administrative access to some resources on a very limited scope.&lt;/p&gt;

&lt;p&gt;In this case someone with an administrative access just opened everything to anyone on IPv4 and IPv6 and no one noticed anything. So how did it go?&lt;/p&gt;

&lt;p&gt;Let’s go into the console &amp;gt; VPC &amp;gt; us-east-1 &amp;gt; Security groups&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--P9k-UthP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2AOloKxWinyVi6Ixpb" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--P9k-UthP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2AOloKxWinyVi6Ixpb" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So we have our super secure security group that we created using Terraform, with a rule that is attached to it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lCR6GQEi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2AbNkcF49HgrqfTkCn" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lCR6GQEi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2AbNkcF49HgrqfTkCn" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--n-P2j2Uq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2ASZ0qdPakqps-mY45" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--n-P2j2Uq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2ASZ0qdPakqps-mY45" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we can see in the AWS console, we have our “super secure security group” and we have our ssh rule for allowing ssh to this local network&lt;/p&gt;

&lt;p&gt;For the sake of simplicity we are doing this demo manually here, but someone or something could change this specific super secure security group and could allow anything anywhere on any kind of networks on IPv4 etc… and name it very, very carefully “temp” &lt;em&gt;(you know, like those temporary rules that we’ll remember soon to change…)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DOUoYyO0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2Ae3mq8I0r9EuUxIO1" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DOUoYyO0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2Ae3mq8I0r9EuUxIO1" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So what happened here is that something, with the correct access rights allowed anything to anywhere on this network behind this security group.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OQgJvM78--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2A5vENU5A36ezxS8dH" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OQgJvM78--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2A5vENU5A36ezxS8dH" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This team expected any kind of rules that was added or modified to be reported on terraform and &lt;strong&gt;while it is true for a rule it is not true for a new rule&lt;/strong&gt; and basically the support team went weeks or months with such a rule live on their system without any notification.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ terraform apply
Apply complete! Resources: 9 added, 0 changed, 0 destroyed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h4&gt;
  
  
  How a scripting issue created a billing nightmare
&lt;/h4&gt;

&lt;p&gt;Our last story is about a team that was building a lot of stuff on S3. They were putting a lot of their binaries there and removing them. So obviously they removed the versioning.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PXvHTB_f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2Arhfg9KdWoSpggmvR" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PXvHTB_f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2Arhfg9KdWoSpggmvR" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For some reason (long story short) someone activated versioning on all the buckets for the company including this one but they were pretty sure that it wasn’t going to be an issue because it’s the default on Terraform to not be versioned. But the code didn’t explicitly say it so.&lt;/p&gt;

&lt;p&gt;Let log in on the AWS console and go to S3&amp;gt; bucket&lt;/p&gt;

&lt;p&gt;Now we are on this bucket that we created using the terraform code above, and basically we are going do manually what they did through script: we are just going to enable bucket versioning.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kfwNEWuw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2A38DpPkyYevXkaRoo" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kfwNEWuw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2A38DpPkyYevXkaRoo" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So now Bucket versioning is enabled. Let’s check with a terraform apply what was reported:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ terraform apply
Apply complete! Resources: 9 added, 0 changed, 0 destroyed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Nothing. So this poor team versioned for weeks hundreds and hundreds of terabytes a day of binaries until they received the bill…&lt;/p&gt;

&lt;h2&gt;
  
  
  Solutions at hand
&lt;/h2&gt;

&lt;p&gt;There are a lot of solutions in our ecosystem to work around the kind of things that we just saw:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;CI/CD Integration (Jenkins, Terraform Cloud, Atlantis, env0…)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Static Analysis (Checkov, TFLint, TFSec,…) are there to help you analyze your code before you actually push to your CI system (or if they are deploying the CI/CD systems, they are there to prevent you to push things like “allow anything to anyone” directly on the code)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Testing &amp;amp; Verification like Terratest (written in Go), InSpec (for the “older” of us, it’s written in Ruby and comes from the Chef days).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Policy &amp;amp; Compliance (Sentinel…) They are a very different set of tools, very cool and very protective.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Enters driftctl
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LZR9_UL4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/12426/1%2ANwAgdgAATX6-qMz5VvHBRQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LZR9_UL4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/12426/1%2ANwAgdgAATX6-qMz5VvHBRQ.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That’s where drift control enters: we built driftctl to manage this drift and be alerted on all the discrepancies between the state and the reality on the AWS accounts.&lt;/p&gt;

&lt;p&gt;Let’s just use the same terminal and the same session that we had previously. drift control will basically report you all the changes that you could not see with terraform plan or a terraform apply .&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ driftctl scan --from tfstate://./s3/terraform.tfstate --from tfstate://./vpc/terraform.tfstate --from tfstate://./iam/terraform.tfstate
Terraform provider initialized (name=aws, alias=us-east-1)
Terraform provider initialized (name=aws, alias=eu-west-3)
Terraform provider initialized (name=aws, alias=eu-north-1)

Found deleted resources:
 - Table: rtb-0c5a9bb483ee6eaaf, Destination: [10.0.1.0/24](https://www.google.com/url?q=http://10.0.1.0/24&amp;amp;sa=D&amp;amp;source=editors&amp;amp;ust=1614683869756000&amp;amp;usg=AOvVaw3mt8mKEET3obX8AAtRPp5D)

Found unmanaged resources:
  aws_security_group_rule:
  - Type: ingress, SecurityGroup: sg-0746ca93f95fcc338, Protocol: All, Ports: All, Source: ::/0
  - Type: ingress, SecurityGroup: sg-0746ca93f95fcc338, Protocol: All, Ports: All, Source: [0.0.0.0/0](https://www.google.com/url?q=http://0.0.0.0/0&amp;amp;sa=D&amp;amp;source=editors&amp;amp;ust=1614683869756000&amp;amp;usg=AOvVaw2umDoMvApX_SsgfP22bUtn)
  aws_iam_access_key:
  - AKIASBXWQ3AYRSNQN5EY (User: INTERN-8mszmf)

Found drifted resources:
  - AKIASBXWQ3AYWWYX72GX (User: INTERN-8mszmf) (aws_iam_access_key):
     ~ Status: "Active" =&amp;gt; "Inactive" (computed)

Found 26 resource(s)
- 84% coverage
- 22 covered by IaC
- 3 not covered by IaC
- 1 deleted on cloud provider
- 1/22 drifted from IaC
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now, we can see the rules that allowed “anything to anywhere” on IPv4 and IPv6 and we know that there are rules that were not expected. &lt;br&gt;
We also have the policy attachment of that intern we talked about.&lt;/p&gt;

&lt;p&gt;So probably with your eyes of administrative people, DevOps, whatever you are, it doesn’t match. It should ring a bell that something is wrong here actually: what about this new access key? Even if you’re not a security person, if you have a new access key created out of nowhere, reported to you, this should ring a bell.&lt;/p&gt;

&lt;p&gt;Let’s go ahead and create a new bucket and call it “Fosdem 2031”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CSuU9H60--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2Aij6dA0duDjHPGFUi" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CSuU9H60--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2Aij6dA0duDjHPGFUi" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Obviously this bucket is not in Terraform because we just created live on the console. It’s perfectly normal for Terraform not to report you that this specific bucket was created right now. But this is the job of driftctl to report that you have &lt;strong&gt;both unmanaged resources that were created and deltas from managed resources&lt;/strong&gt;.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ driftctl scan --from tfstate://./s3/terraform.tfstate --from tfstate://./vpc/terraform.tfstate --from tfstate://./iam/terraform.tfstate
Terraform provider initialized (name=aws, alias=us-east-1)
Terraform provider initialized (name=aws, alias=eu-west-3)
Terraform provider initialized (name=aws, alias=eu-north-1)

Found deleted resources:
  aws_route:
  - Table: rtb-0c5a9bb483ee6eaaf, Destination: [10.0.1.0/24](https://www.google.com/url?q=http://10.0.1.0/24&amp;amp;sa=D&amp;amp;source=editors&amp;amp;ust=1614674194048000&amp;amp;usg=AOvVaw3D80Zc5czyA8iDpAvb61zo)

Found unmanaged resources:
  aws_s3_bucket:
  - fosdem2031
  aws_security_group_rule:
  - Type: ingress, SecurityGroup: sg-0746ca93f95fcc338, Protocol: All, Ports: All, Source: ::/0
  - Type: ingress, SecurityGroup: sg-0746ca93f95fcc338, Protocol: All, Ports: All, Source: [0.0.0.0/0](https://www.google.com/url?q=http://0.0.0.0/0&amp;amp;sa=D&amp;amp;source=editors&amp;amp;ust=1614674194048000&amp;amp;usg=AOvVaw00rswNHGCuK2ZVSP4oVZAl) 
  aws_iam_access_key:
  - AKIASBXWQ3AYRSNQN5EY (User: INTERN-8mszmf)

Found drifted resources:
  - AKIASBXWQ3AYWWYX72GX (User: INTERN-8mszmf) (aws_iam_access_key):
    ~ Status: "Active" =&amp;gt; "Inactive" (computed)

Found 27 resource(s)
  - 81% coverage
  - 22 covered by IaC
  - 4 not covered by IaC
  - 1 deleted on cloud provider
  - 1/22 drifted from IaC
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Let’s focus on the VPC here: if we change an existing rule…&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7qt-ETlR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2Axw2hTIo_tIXse2KV" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7qt-ETlR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2Axw2hTIo_tIXse2KV" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;… we can see it in the diffs in driftctl&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ driftctl scan --from tfstate://./s3/terraform.tfstate --from tfstate://./vpc/terraform.tfstate --from tfstate://./iam/terraform.tfstate

Terraform provider initialized (name=aws, alias=us-east-1) 
Terraform provider initialized (name=aws, alias=eu-west-3) 
Terraform provider initialized (name=aws, alias=eu-north-1)

Found deleted resources:
  aws_route: 
  - Table: rtb-0c5a9bb483ee6eaaf, Destination: 10.0.1.0/24

Found unmanaged resources: 
  aws_s3_bucket: 
  - fosdem2031
  aws_security_group_rule: 
  - Type: ingress, SecurityGroup: sg-0746ca93f95fcc338, Protocol: All, Ports: All, Source: ::/0 
  - Type: ingress, SecurityGroup: sg-0746ca93f95fcc338, Protocol: All, Ports: All, Source: 0.0.0.0/0
  aws_iam_access_key: 
  - AKIASBXWQ3AYRSNQN5EY (User: INTERN-8mszmf)

Found drifted resources:
  - AKIASBXWQ3AYWWYX72GX (User: INTERN-8mszmf) (aws_iam_access_key): 
    ~ Status: "Active" =&amp;gt; "Inactive" (computed)
  aws_S3_bucket: 
    -fosdem2031

Found 14 resource(s)
- 50% coverage
- 7 covered by IaC 
- 4 not covered by IaC 
- 1 deleted on cloud provider 
- 1/14 drifted from IaC
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The other things we can do with drift control is ignore some resources that you do not want to see reported for whatever reason you have.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--z2bgh8t7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2ASxZ0PKLSoL-XTP3F" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--z2bgh8t7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2ASxZ0PKLSoL-XTP3F" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So you can also filter using the same system as AWS CLI. For example, you can filter just for S3 buckets if you are not interested in the rest.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ driftctl scan --filter "Type=='aws_s3_bucket'"

$ driftctl scan --from tfstate://./s3/terraform.tfstate --from tfstate://./vpc/terraform.tfstate --from tfstate://./iam/terraform.tfstate --filter "Type=='aws_s3_bucket'"
Terraform provider initialized (name=aws, alias=us-east-1)
Terraform provider initialized (name=aws, alias=eu-west-3)
Terraform provider initialized (name=aws, alias=eu-north-1)

Found unmanaged resources:
  aws_s3_bucket:
   — fosdem2031

Found 2 resource(s)
– 50% coverage
– 1 covered by IaC
– 1 not covered by IaC
– 0 deleted on cloud provider
– 0/1 drifted from IaC
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;It’s pretty cool for auditing purposes, for monitoring purposes etc…&lt;/p&gt;

&lt;h2&gt;
  
  
  And that’s a wrap!
&lt;/h2&gt;

&lt;p&gt;Thank you very much for reading through all this talk transcript.&lt;br&gt;
If you wish to gain a better understanding of driftctl, please visit our &lt;a href="https://driftctl.com/product"&gt;product page&lt;/a&gt; or our &lt;a href="https://driftctl.com/advanced-tutorial"&gt;advanced tutorial&lt;/a&gt;. We also have a series of short &lt;a href="https://driftctl.com/product/demo-videos/"&gt;demo videos&lt;/a&gt; that you can watch to get started in minutes.&lt;/p&gt;

&lt;p&gt;For any questions, feel free to open a discussion on GitHub or visit us &lt;a href="https://driftctl.com/d"&gt;discord&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Driftctl is a &lt;strong&gt;free and open-source&lt;/strong&gt; CLI that &lt;strong&gt;tracks, analyzes, prioritizes, and warns of infrastructure drift&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://driftctl.com/?utm_source=devto&amp;amp;utm_devto=devto&amp;amp;utm_campaign=devto"&gt;More info about us&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>terraform</category>
      <category>infrastructureascode</category>
      <category>devsecops</category>
    </item>
    <item>
      <title>How to catch your infrastructure drift in minutes using driftctl.</title>
      <dc:creator>driftctl</dc:creator>
      <pubDate>Mon, 08 Feb 2021 17:43:22 +0000</pubDate>
      <link>https://dev.to/driftctl/how-to-catch-your-infrastructure-drift-in-minutes-using-driftctl-5fkp</link>
      <guid>https://dev.to/driftctl/how-to-catch-your-infrastructure-drift-in-minutes-using-driftctl-5fkp</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;How to catch your infrastructure drift in minutes using driftctl.&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Learn how to use driftctl in a real-life environment, with multiple Terraform states and output filtering.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Whether it’s a script gone wild, a bad API call from a trusted Lambda, or just the daily SNAFU, you want to know about the situation.&lt;br&gt;
Driftctl will do just that. In this guide, you will learn how to use &lt;a href="https://github.com/cloudskiff/driftctl"&gt;driftctl&lt;/a&gt; an open source tool that tracks and warns of infrastructure drift, in a realistic real-life environment, with multiple Terraform states and output filtering. We will demonstrate how manual changes can impact drift detection and how driftctl complements Terraform plan!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--obaCHMTD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/NaN/0%2AteDmTHYfb67b7lSL" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--obaCHMTD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/NaN/0%2AteDmTHYfb67b7lSL" alt=""&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;p&gt;We recommend using an AWS account dedicated to testing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;An AWS account with IAM keys (&lt;a href="https://aws.amazon.com/"&gt;AWS Homepage&lt;/a&gt;). See &lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html"&gt;this AWS CLI documentation&lt;/a&gt; for a quick start.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Terraform 0.14.x (&lt;a href="https://www.terraform.io/downloads.html"&gt;download link&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Driftctl (&lt;a href="https://github.com/cloudskiff/driftctl"&gt;github&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Example Terraform code for this lab (&lt;a href="https://github.com/cloudskiff/driftctl-advanced-aws-tutorial"&gt;here&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Create a test AWS environment
&lt;/h2&gt;

&lt;p&gt;Clone the example Terraform code and execute it with Terraform. This Terraform configuration will simply create a VPC and a basically locked down security group.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclaimer: we used simple Terraform resources using the AWS provider: we did not try to create the most advanced, useful or complete Terraform configuration.&lt;/em&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ git clone 
git@github.com:cloudskiff/driftctl-advanced-aws-tutorial.git
$ cd driftctl-advanced-aws-tutorial
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-envvars.html"&gt;Export your AWS variables&lt;/a&gt; (or &lt;code&gt;AWS_ACCESS_KEY_ID&lt;/code&gt; / &lt;code&gt;AWS_SECRET_KEY&lt;/code&gt; pair):&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ export AWS_PROFILE="your-profile"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Initialize both Terraform environments : app_env_1 &amp;amp; app_env_2&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cd app_env_1
$ terraform init
[...]
Terraform has been successfully initialized!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Run Terraform:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ terraform apply
[...]
Apply complete! Resources: 4 added, 0 changed, 0 destroyed.
$ cd ..
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Do the same for the second environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    $ cd app_env_2

    $ terraform init
    [...]
    Terraform has been successfully initialized!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    $ terraform apply
    [...]
    Apply complete! Resources: 4 added, 0 changed, 0 destroyed.
    $ cd ..
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Congrats, your AWS account now includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A VPC with a random name (from app_env_1)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A security group with a single rule (from app_env_2)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  An overview of driftctl scanning options
&lt;/h2&gt;

&lt;p&gt;As of this writing, driftctl can scan for AWS resources and complement Terraform in drift detection. More providers are on their way!&lt;/p&gt;

&lt;p&gt;Using driftctl, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Select one or multiple Terraform states, locally or on S3 (with &lt;code&gt;--from &amp;lt;statefiles&amp;gt;&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ignore some resources or fields by design (filling the &lt;code&gt;.driftignore&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Filter the output to choose only some resources or tags (with &lt;code&gt;--filter &amp;lt;expression&amp;gt;&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Format the output for readability or further processing (with &lt;code&gt;--output &amp;lt;format&amp;gt;&lt;/code&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Driftctl with multiple local Terraform states
&lt;/h2&gt;

&lt;p&gt;The small lab we created above is simulating 2 different “environments” (in real life it can be different applications, environments, or teams), with distinct Terraform states.&lt;/p&gt;

&lt;p&gt;If we run driftctl with a single state, resources from the other state will be detected as drifts, or more precisely, unmanaged resources, which is not true and not what we want.&lt;/p&gt;

&lt;p&gt;Here’s how to use driftctl with multiple states:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ driftctl scan **--from** tfstate://./app_env_1/terraform.tfstate **--from** tfstate://./app_env_2/terraform.tfstate
Scanning AWS on region: us-east-1
Found 3 resource(s)
- 100% coverage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Create a Security Group drift and catch it
&lt;/h2&gt;

&lt;p&gt;Let’s manually add a rule to the security group we created, so we can detect it using driftctl:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Go to the &lt;a href="https://console.aws.amazon.com/vpc/home?#securityGroups:"&gt;VPC Security Group&lt;/a&gt; in the AWS console.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select the security group named “Super Secure Security Group”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click on “Edit inbound rules” in the “Inbound rules” tab&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click on “Add Rule”&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Select “All Traffic”, from “Anywhere”, add a random description&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click on “Save Rules”&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FV524Pxc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2Acz3Vxg_PRK3g6e_M" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FV524Pxc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2Acz3Vxg_PRK3g6e_M" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Run Terraform from the folder where the security group is managed and confirm it doesn’t catch the manual change:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cd env_app_2
$ terraform apply
aws_security_group.supersecure: Refreshing state... [id=sg-0d04a4ce8ff6a74d3]
aws_security_group_rule.supersecure_sg_rule_1: Refreshing state... [id=sgrule-1254751605]
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now run driftctl again:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cd ..
$ driftctl scan --from tfstate://./app_env_1/terraform.tfstate --from tfstate://./app_env_2/terraform.tfstate
Scanning AWS on region: us-east-1
**Found unmanaged resources:
aws_security_group_rule:
- sgrule-619247160 (Type: ingress, SecurityGroup: sg-0d04a4ce8ff6a74d3, Protocol: All, Ports: All, Source: ::/0)
- sgrule-1309243877 (Type: ingress, SecurityGroup: sg-0d04a4ce8ff6a74d3, Protocol: All, Ports: All, Source: 0.0.0.0/0)
**Found 5 resource(s)
- 60% coverage
- 3 covered by IaC
- **2 not covered by IaC
**- 0 deleted on cloud provider
- 0/3 drifted from IaC
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Holy cow, driftctl caught the drift!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DQs47rqO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2AteDmTHYfb67b7lSL" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DQs47rqO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/2000/0%2AteDmTHYfb67b7lSL" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Ignore resources with .driftignore
&lt;/h2&gt;

&lt;p&gt;In many cases, you’ll want driftctl to ignore some resources forever, to stop being notified about their existence, and also stop lowering the coverage score. Those reasons can include the very IAM key you use to run this lab (by definition it can’t be in this Terraform repo), resources that can’t or won’t be managed by Terraform, resources managed from teams sharing the same AWS account but not using Terraform, some legacy resources, or simply manual tests running a bit longer than expected. This is exactly the same approach as the usual &lt;code&gt;.gitignore&lt;/code&gt; : you simply add to this file all the resources you want to be ignored.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create an unmanaged S3 bucket, catch it, ignore it.
&lt;/h2&gt;

&lt;p&gt;To proceed with this step:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Go to the &lt;a href="https://console.aws.amazon.com/s3"&gt;S3 dashboard&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Manually create an S3 bucket that you’ll name however you like&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Obviously, as this is completely done outside of its control, this bucket can’t be detected as a drift by Terraform, so we’re in the dark, as expected.&lt;/p&gt;

&lt;p&gt;Confirm driftctl detects the manually created bucket:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ driftctl scan --from tfstate://./app_env_1/terraform.tfstate --from tfstate://./app_env_2/terraform.tfstate
Scanning AWS on region: us-east-1
Found unmanaged resources:
[...]
aws_s3_bucket:
- randomBucket514
[...]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Open the &lt;code&gt;.gitignore&lt;/code&gt; file at the root of the repository, where we execute driftctl and add a line like &lt;code&gt;aws_s3_bucket&lt;/code&gt; (in my case: &lt;code&gt;aws_s3_bucket.randomBucket514&lt;/code&gt;) Now run driftctl again:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ driftctl scan --from tfstate://./app_env_1/terraform.tfstate --from tfstate://./app_env_2/terraform.tfstate
[...]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now the manually created S3 bucket is ignored forever!&lt;/p&gt;

&lt;h2&gt;
  
  
  Output filters for better accuracy
&lt;/h2&gt;

&lt;p&gt;It’s often helpful to be able to filter the output dynamically, to see results only for one type of resource (like only IAM users) or a specific tag (like only a specific environment).&lt;/p&gt;

&lt;p&gt;Filtering in driftctl is implemented as in the AWS CLI: you won’t be lost! (hint: it’s JMESPath).&lt;/p&gt;

&lt;p&gt;Let’s filter only VPC resources:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ driftctl scan --from tfstate://./app_env_1/terraform.tfstate --from tfstate://./app_env_2/terraform.tfstate **--filter "Type=='aws_vpc'"
**Scanning AWS on region: us-east-1
Found 1 resource(s)
- 100% coverage
Congrats! Your infrastructure is fully in sync.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Let’s now filter only for anything matching the “app_env_1” &lt;em&gt;“Environment”&lt;/em&gt; tag on EC2:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ driftctl scan --from tfstate://./app_env_1/terraform.tfstate --from tfstate://./app_env_2/terraform.tfstate **--filter "Attr.Tags.Environment == 'app_env_1'"
**Scanning AWS on region: us-east-1
Found 1 resource(s)
- 100% coverage
Congrats! Your infrastructure is fully in sync.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;You now can collect data only for the exact setup you want! Perfect for those reports&lt;/p&gt;

&lt;h2&gt;
  
  
  JSON output manipulation
&lt;/h2&gt;

&lt;p&gt;We’ve covered driftctl human-readable output, but it’s also often useful to process it further. That’s why driftctl can output to JSON!&lt;/p&gt;

&lt;p&gt;Here’s how to generate a JSON file directly:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ driftctl scan --from tfstate://./app_env_1/terraform.tfstate --from tfstate://./app_env_2/terraform.tfstate **--output json://driftctl.json**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Take a look at the generated JSON file:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cat output.json
{
  "summary": {
  "total_resources": 5,
  "total_drifted": 0,
  "total_unmanaged": 2,
  "total_deleted": 0,
  "total_managed": 3
  },
[...]
$
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now you can process this file using a processor like jq, for example, to catch only the coverage percentage and maybe send it to a database, from which a graph can be generated:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ jq '.coverage' **&amp;lt; driftctl.json
**60
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The possibilities are now endless!&lt;/p&gt;

&lt;h2&gt;
  
  
  Shutting down the lab
&lt;/h2&gt;

&lt;p&gt;Don’t forget to destroy the resources we created for this lab:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cd app_env_2; terraform destroy
$ cd ../app_env_1; terraform destroy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Delete the S3 bucket you randomly created and your AWS account is now as clean as before.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recap
&lt;/h2&gt;

&lt;p&gt;We covered a lot in this advanced tutorial:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;We used driftctl in combination with multiple Terraform state files.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We detected manual drifts from Terraform-managed resources as well as entirely unmanaged resources.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We manipulated driftctl output to ignore and filter resources based on type or tags.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We used and processed driftctl JSON output.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devops</category>
      <category>terraform</category>
      <category>infrastructureascode</category>
      <category>devsecops</category>
    </item>
    <item>
      <title>Announcing Driftctl
because drift matters</title>
      <dc:creator>driftctl</dc:creator>
      <pubDate>Thu, 21 Jan 2021 14:21:39 +0000</pubDate>
      <link>https://dev.to/driftctl/announcing-driftctl-because-drift-matters-4fl0</link>
      <guid>https://dev.to/driftctl/announcing-driftctl-because-drift-matters-4fl0</guid>
      <description>&lt;p&gt;We recently released the first versions of driftctl, a new open-source project for infrastructure developers, DevOps, SRE, and cloud practitioners, with the goal of helping manage all kinds of drifts. &lt;br&gt;
&lt;em&gt;Stephane Jourdan – CTO and founder&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Why? Because infrastructure is a living thing and changes are risky.
&lt;/h3&gt;

&lt;p&gt;In the team, we all managed cloud infrastructures at some level at our previous jobs, as developers with serverless function needs or DevOps managing large production systems. And we all knew that sometimes an emergency required a manual change, a customer tweaked a setting on the console, the boss activated something that had an impact later…or put more simply, that the whole infrastructure was just not totally under control by Terraform (or similar tool), just because ops life in production is rarely perfect and ideal. &lt;/p&gt;

&lt;p&gt;And all those tiny changes sometimes got forgotten about, or partially implemented in infrastructure-as-code later on, unfortunately leading to security issues, unstable environments, failed deployments, unexpectedly important bills. And thus this makes us lose the advantages of IaC.&lt;/p&gt;
&lt;h2&gt;
  
  
  Keeping infrastructures secure &amp;amp; in sync with code.
&lt;/h2&gt;

&lt;p&gt;Like many of you, we use and love infrastructure-as-code, and especially Terraform, and for years we relied on its features to ensure the coherence of our infrastructures (most of us ended up with terraform plan in crontabs or in CI, expecting that return code 0 would ensure a fully synchronized infrastructure!). &lt;/p&gt;

&lt;p&gt;While Terraform is excellent at provisioning cloud infrastructures, telling you about changes in your AWS account is not where it shines, mainly because it’s simply not its job.&lt;/p&gt;

&lt;p&gt;Until now, to be sure that no change happened in your infrastructure, it implied an excellent level of trust in your tools and dependencies, a very stable IaaS provider, every single resource in every region carefully described in Terraform, then the revocation of all admin credentials of your team (and we really think this is as bad for developers’ sense of ownership and empowerment as it is deeply against DevOps culture), most of the time strong CI/CD pipelines and processes, usage of compliance and policy tools, regular auditing, and probably more great ideas to slow down teams velocity. &lt;/p&gt;

&lt;p&gt;But that was clearly not the reality we experienced daily out there! That was often either the goal to reach someday, or a naive belief from management when the team knew very well how to work their way around. But most of the time, credentials were passed around in the team, many resources were still not in Terraform, processes were not perfect, people sometimes forgot to push their locally applied changes, changes happened outside of Terraform, emergencies had to be dealt with quickly (and usually not in Terraform!), consultants came and went, projects were still handed over to customers and no one had time or money to implement complex policies (not to mention that not everyone requires the hassle of PCI/DSS compliance).&lt;/p&gt;

&lt;p&gt;And yet, absolutely no one had a good overview of how good or bad things were, easily, so as to take action at some point.&lt;/p&gt;

&lt;p&gt;Hope is not a strategy and…that’s why we built driftctl. Driftctl is like your IaC security belt!&lt;/p&gt;
&lt;h2&gt;
  
  
  Driftctl -  a new open-source project to help you monitor IaC changes.
&lt;/h2&gt;

&lt;p&gt;We built driftctl to help developers know when things change on their IaaS, whatever reason it does, and give them a good overview of their infrastructure-as-code coverage. &lt;/p&gt;

&lt;p&gt;This tool is open-source at its core (Apache-2.0 license) and we decided to release driftctl very early, so we can gather feedback sooner than later and prioritize accordingly. Also, by building this tool publicly from the beginning, we hope that many users will contribute ideas, suggestions, and maybe some code early on. &lt;/p&gt;

&lt;p&gt;The initial releases are focusing on detecting drift on AWS and on Terraform support. Future releases will add support for a lot more, but we didn’t want to wait to release this early. Those releases support what we thought were the most common services on AWS, and this was also backed with hours of interviews with DevOps practitioners around the world those last months. So we started with EC2, S3, IAM, RDS and Lambda, and we’re already working on supporting VPC, CloudFront, Aurora, DynamoDB, API Gateway, SNS/SQS, ECS/EKS/ECR, or KMS. The coming weeks will be exciting!&lt;/p&gt;

&lt;p&gt;We also included in the first release a view of your cloud / IaC coverage, so you can quickly know with simple data if your IaaS account is more or less under control with Terraform. Also, if that percentage decreases, it means something changed outside of Terraform! The human-readable output can be switched to JSON if you want to process it. &lt;/p&gt;

&lt;p&gt;Early on, we realized that for our own usage, this wasn’t enough: our own AWS accounts were filled with temporary tests, IAM roles, etc., and even our pretty much ideally locked down and mostly automated production account had a few manual resources (like the initial IAM user!). The output was deceptive as it included a lot of garbage we knew of but couldn’t do anything about. So we also added to the first release two different ways to ignore drifted resources, so you can start fresh with a clean output and start from there. &lt;/p&gt;

&lt;p&gt;This is a community project, and this is the first step in our mission to build an open-source suite of tools to protect codified infrastructures, so definitely feel free to give us a shout to prioritize another service or resource: open a &lt;a href="https://github.com/cloudskiff/driftctl"&gt;GitHub issue or discussion&lt;/a&gt;, and we’d love to chat with you on our Discord. Come say Hi!&lt;/p&gt;
&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;Let me show you how to quickly get started with driftctl, once downloaded from &lt;a href="https://github.com/cloudskiff/driftctl/releases"&gt;https://github.com/cloudskiff/driftctl/releases&lt;/a&gt; . We’ll start with the most simple case where you have the Terraform state locally available (beware, usually not a good practice!). &lt;/p&gt;

&lt;p&gt;First, export your AWS environment variables as usual:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ export AWS_PROFILE=”my-aws-profile” 
$ export AWS_REGION=”us-east-1”
$ driftctl scan 
Scanning AWS on region: us-east-1
Found unmanaged resources:
  aws_iam_access_key:
    - AKIASBXWQ5ATWVVI7REW
[...]
Found 18 resource(s)
 - 22% coverage
 - 4 covered by IaC
 - 14 not covered by IaC
 - 0 deleted on cloud provider
 - 0/4 drifted from IaC
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, you probably follow good practices and don’t store your state locally or on git but on S3. Here’s how it would work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ driftctl scan --from tfstate+s3://acmecorp/states/terraform.tfstate
[...]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Maybe, also as a good practice, you used tags extensively on your AWS resources, so you’d like driftctl to scan only for the &lt;code&gt;Environment: Production&lt;/code&gt; key and value?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ driftctl scan --filter "Attr.Tags.Environment == 'Production'"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternatively, you can exclude some resources directly in the &lt;code&gt;.driftignore&lt;/code&gt; file (if you want to ignore the “terraform” IAM user, simply add a line containing &lt;code&gt;aws_iam_user.terraform&lt;/code&gt;). Obviously, at any time, you can check the help by executing driftctl scan help.&lt;/p&gt;

&lt;p&gt;This is only a quick introduction, a lot more details are included in the &lt;a href="https://github.com/cloudskiff/driftctl/tree/main/doc"&gt;Github documentation.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>terraform</category>
      <category>cloudnative</category>
      <category>aws</category>
    </item>
    <item>
      <title>Why you should take care of infrastructure drift</title>
      <dc:creator>driftctl</dc:creator>
      <pubDate>Tue, 01 Dec 2020 16:34:24 +0000</pubDate>
      <link>https://dev.to/driftctl/why-you-should-take-care-of-infrastructure-drift-a13</link>
      <guid>https://dev.to/driftctl/why-you-should-take-care-of-infrastructure-drift-a13</guid>
      <description>&lt;p&gt;When talking about infrastructure drift, you often get knowing glances and heated answers. Recording gaps in your infra between what you expected to be and the reality of what is, is a well known and wide spread issue bothering hundreds of DevOps teams around the globe. Interesting to note though, is that depending on their context, the exact definition they will give of drift will vary.&lt;/p&gt;

&lt;p&gt;Facing impacts and consequences ranging from intensive toil to dangerous security threats, many DevOps team are keenly aware of the issue and actively looking for solutions.&lt;/p&gt;

&lt;p&gt;We decided to look more closely into how they deal with it and conducted a study that will be released in the coming weeks. Here is a foretaste of this study, outlining some of the key facts we recorded.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How infrastructure drift is becoming a major issue : a combination of growing volume and automation&lt;/strong&gt;&lt;br&gt;
The ever growing amount of workloads running in the cloud has gone hand in hand with a similarly growing number of people interacting with infras, themselves working with several environments.&lt;/p&gt;

&lt;p&gt;In this context, as Infrastructure as Code becomes widely adopted by users with heterogenous skillsets, the IaC codebases become larger, mechanically fueling daily occasions to create drift and making it harder to track.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The various definitions and core causes of infrastructure drift&lt;/strong&gt;&lt;br&gt;
Drift is a multi-faceted problem, let’s agree on a definition.&lt;/p&gt;

&lt;p&gt;Indeed, depending on their context and process (or lack thereof) people will tend to stress one specific aspect of drift or another when prompted on a definition. Typically, some people will tend to relate drift to the lack of consistency between, say &lt;code&gt;staging&lt;/code&gt; and &lt;code&gt;production&lt;/code&gt; environments, which might be true, but incomplete.&lt;/p&gt;

&lt;p&gt;Still, most of the people we talked to define infrastructure drift as an “unwanted delta” recorded between their Infrastructure code base and the actual state of their infras.&lt;/p&gt;

&lt;p&gt;Drift can be driven by human input, poor configuration, applications making unwanted changes, etc. It has consequences on toil and efficiency, forces teams to put in place strict controls that decrease flexibility, and can have a security impact.&lt;/p&gt;

&lt;p&gt;Two of the most common causes of drift are linked with process or workflow issues, like manual changes in a cloud console not being transposed as code, or changes applied to some environment but not propagated to others. Obviously those issues becomes more and more complex as the number of environments and team members grows. Some teams have dozens of environments that they need to keep updated.&lt;/p&gt;

&lt;p&gt;Much more surprising though is the fact that what we call API-driven drift is a widespread issue. API-driven drift happens when an update from an application or a script calling a cloud provider API (or a Terraform provider), autonomously and directly impacts your actual &lt;code&gt;state&lt;/code&gt;. In this case, you’ve just lost consistency with your codebase, and you won’t be aware of it until some random &lt;code&gt;apply&lt;/code&gt; reveals a problem that might end up taking a couple of hours to fix. This happens even on the cloud provider’s side. One of the people we talked to told us of the time he suddenly got locked out of Azure because of a default machine authentication parameter updated from &lt;code&gt;true&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The impacts of infrastructure drift&lt;/strong&gt;&lt;br&gt;
Maintaining a solid and reliable source of knowledge of how your cloud ressources are organized certainly is important, but at the end of the day you might simply think of infrastructure drift as a mere annoyance not worth the effort.&lt;/p&gt;

&lt;p&gt;While drift mostly causes additional work, it also triggers severe security issues too. In one of our interviews, a DevOps lead analyzed the problem quite clearly: “every drift event causes uncertainty, a resolution time, and a potential security issue”. Willingly or not, a developer can do a lot with IAM keys and a SDK. Especially a junior one. Being able to catch bad decisions quickly and reverse your situation back to normal is crucial.&lt;/p&gt;

&lt;p&gt;There are also more subtle effects of drift, especially on efficiency. To avoid excessive drift, some teams make significant adjustments to their workflows. In some teams, only the DevOps team lead is allowed access to production. In others where developers are not skilled at IaC, getting a small change to environments done goes through a painful and long ticketing system. In other words, drift causes issues, which leads to rigid / counterproductive processes, which leads to a decrease in speed and flexibility.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How teams solve drift so far&lt;/strong&gt;&lt;br&gt;
Whatever the maturity level of a team and the degree of automation of their cloud infrastructures, maintaining reliability and security while moving at developers speed implies tracking down inconsistencies, like infrastructure drift.&lt;/p&gt;

&lt;p&gt;The faster it is detected, the easier it is to remediate drift, which is why many DevOps we interviewed had a &lt;code&gt;terraform plan&lt;/code&gt; in a cron job.&lt;/p&gt;

&lt;p&gt;Most teams will explain that to tackle drift, the first thing they did was restrict access to production to a few team members. That certainly contains the problem, but does not solve staging environments drift, as only a smaller part of teams restrict access to staging environments. Following through with that, deploying a full GitOps workflow will prevent some of the drift, but not all of it (not the API-driven events for example) and is still pretty hard to do by the book in practice when there is an urgent issue to solve on the production environment and MTTR is key for the business.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why we think infrastructure drift should be addressed with a better solution&lt;/strong&gt;&lt;br&gt;
We recently caught an excellent twitter thread about the various impacts of fast and slow moving broken stuff. Infrastructure drift might not be considered a fast moving broken thing. This is maybe all the more dangerous as sometimes you just can’t get anyone to pay attention to slow-moving broken things because what harm could that iceberg do?”*&lt;/p&gt;

&lt;p&gt;Analyzing what solutions are deployed against drift in over 100 teams led us to discover how poorly the topic is addressed. Stay tuned if you’d like to see how we intend to bring an open source solution to this issue.&lt;/p&gt;

&lt;p&gt;*borrowed from &lt;a href="https://twitter.com/yvonnezlam/status/1325818366976667649?s=12"&gt;@yvonnezlam&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>terraform</category>
      <category>aws</category>
    </item>
  </channel>
</rss>
