<?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: Brett Curtis</title>
    <description>The latest articles on DEV Community by Brett Curtis (@brettcurtis).</description>
    <link>https://dev.to/brettcurtis</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%2F456733%2Fe562e8cf-3a6e-490c-b609-e0c9165c73a9.jpeg</url>
      <title>DEV Community: Brett Curtis</title>
      <link>https://dev.to/brettcurtis</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/brettcurtis"/>
    <language>en</language>
    <item>
      <title>Using GitHub to Manage GitHub!</title>
      <dc:creator>Brett Curtis</dc:creator>
      <pubDate>Sat, 21 Jan 2023 16:13:17 +0000</pubDate>
      <link>https://dev.to/osinfra-io/using-github-to-manage-github-2kkm</link>
      <guid>https://dev.to/osinfra-io/using-github-to-manage-github-2kkm</guid>
      <description>&lt;h1&gt;
  
  
  GitHub Organization Management Platform
&lt;/h1&gt;

&lt;p&gt;Updated version here: &lt;a href="https://www.osinfra.io/github-organization-management-platform"&gt;https://www.osinfra.io/github-organization-management-platform&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Managing thousands of repositories across hundreds of users in GitHub can become very complex and tedious. You'll want basic naming conventions on repositories and teams, ways to manage users in those teams, roles, and security settings enforced as a minimum. The &lt;a href="https://registry.terraform.io/providers/integrations/github/latest/docs"&gt;Terraform provider for GitHub&lt;/a&gt; allows us to manage our GitHub organization as a platform, just like any other infrastructure. Doing this will reduce technical debt when onboarding, provide ongoing supportability and give a defined &lt;a href="https://teamtopologies.com/key-concepts"&gt;team interaction mode of GitHub-as-a-Service&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This open-source &lt;a href="https://github.com/osinfra-io/github-organization-management"&gt;repository&lt;/a&gt; is an example of Infrastructure as Code (IaC) for managing a GitHub organization using &lt;a href="https://www.terraform.io/"&gt;Terraform&lt;/a&gt;, concepts from &lt;a href="https://teamtopologies.com/"&gt;Team Topologies&lt;/a&gt;, and sensible default practices.&lt;/p&gt;

&lt;p&gt;Currently, we have the following service interfaces defined by the beta &lt;a href="https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms"&gt;GitHub Issue Forms&lt;/a&gt; that you can see in the &lt;a href="https://github.com/osinfra-io/github-organization-management#service-interfaces"&gt;README.md&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;github_membership service interface: &lt;a href="https://github.com/osinfra-io/github-organization-management/issues/new?assignees=&amp;amp;labels=enhancement%2Cgood+first+issue&amp;amp;template=github-membership.yml&amp;amp;title=Add+member"&gt;GitHub Issue&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;github_repository service interface: &lt;a href="https://github.com/osinfra-io/github-organization-management/issues/new?assignees=&amp;amp;labels=enhancement%2Cgood+first+issue&amp;amp;template=github-repository.yml&amp;amp;title=Add+repository"&gt;GitHub Issue&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1r-9aXJX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qlq2gnkytqdapo87c3f9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1r-9aXJX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qlq2gnkytqdapo87c3f9.png" alt="Image description" width="880" height="868"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Any issue created by an exposed service interface in any platform we build is labeled as a &lt;a href="https://github.com/orgs/osinfra-io/projects/1"&gt;good first issue&lt;/a&gt; and documented to make completion of the work possible within the individual author's cognitive load. These issues align with one of our key concepts of cultivating and developing a strong pool of talented individuals ready to take on work and grow within the organization. They are helping new Infrastructure as Code engineers learn the &lt;a href="https://docs.github.com/en/get-started/quickstart/github-flow"&gt;GitHub flow&lt;/a&gt; through muscle memory. Large organizations will fail at Infrastructure as Code if they expect "traditional" infrastructure engineers to take on the cognitive load of learning and treating infrastructure like code while learning cloud platforms. They are left with, at best, poor automation practices, not Infrastructure as Code.&lt;/p&gt;

&lt;p&gt;After we merge a pull request, we use GitHub &lt;a href="https://github.com/osinfra-io/github-terraform-gcp-called-workflows"&gt;reusable workflows&lt;/a&gt; with &lt;a href="https://github.com/osinfra-io/google-cloud-workload-identity"&gt;OIDC&lt;/a&gt; to our &lt;a href="https://github.com/osinfra-io/google-cloud-terraform-backend"&gt;Google Cloud Terraform backend Platform&lt;/a&gt; to run the terraform plan and use GitHub environments with a &lt;a href="https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment#required-reviewers"&gt;required reviewers&lt;/a&gt; protection rule before the &lt;a href="https://github.com/osinfra-io/github-organization-management/actions/runs/3954032932"&gt;apply job&lt;/a&gt; runs. Giving the pull request author a chance to look over the Terraform plan in detail and validate the changes are what they expect.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MYOIs9PH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fa4g1r8pynm202fjord9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MYOIs9PH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fa4g1r8pynm202fjord9.png" alt="Image description" width="880" height="581"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We also use &lt;a href="https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/about-dependabot-version-updates"&gt;Dependabot&lt;/a&gt; and &lt;a href="https://github.com/osinfra-io/github-misc-called-workflows"&gt;reusable workflows&lt;/a&gt; to keep all our actions and terraform provider dependencies up to date. Along with &lt;a href="https://github.com/osinfra-io/github-organization-management/blob/main/.github/CODEOWNERS"&gt;CODEOWNERS&lt;/a&gt; to ensure the correct platform team is requested to review. The notifications are a bit noisy right now, but we hope to see an option to make a pull request draft by default so code reviewers will only receive notification once the pull request is ready for review.&lt;/p&gt;

&lt;p&gt;In conclusion, &lt;a href="https://github.com"&gt;GitHub&lt;/a&gt; is an extremely powerful tool that, hands down, enables collaboration and learning across engineers. GitHub powers Infrastructure as Code engineers and software engineers by creating a common language and skill set across the platform and stream-aligned teams with a comprehensive, end-to-end infrastructure and software development solution. With that and organizational design like &lt;a href="https://teamtopologies.com/"&gt;Team Topologies&lt;/a&gt; in place, we see increased success in individuals, teams, organizations, and the software built for their customers.&lt;/p&gt;

&lt;p&gt;Technical Documentation (WIP): &lt;a href="https://docs.osinfra.io/github/organization-management"&gt;docs.osinfra.io&lt;/a&gt;&lt;/p&gt;

</description>
      <category>github</category>
      <category>iac</category>
      <category>devops</category>
      <category>platform</category>
    </item>
    <item>
      <title>GitHub Actions for Kitchen-Terraform Testing</title>
      <dc:creator>Brett Curtis</dc:creator>
      <pubDate>Sat, 19 Sep 2020 18:07:29 +0000</pubDate>
      <link>https://dev.to/brettcurtis/github-actions-for-kitchen-terraform-testing-4a9p</link>
      <guid>https://dev.to/brettcurtis/github-actions-for-kitchen-terraform-testing-4a9p</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8HTrX0Dz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/nu76ifdpv6t49cw36vvu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8HTrX0Dz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/nu76ifdpv6t49cw36vvu.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the last &lt;a href="https://dev.to/brettcurtis/gcp-cis-benchmark-terraform-module-testing-with-chef-inspec-kitchen-terraform-github-actions-1227"&gt;post&lt;/a&gt;, we worked on &lt;a href="https://github.com/newcontext-oss/kitchen-terraform"&gt;Kitchen-Terraform&lt;/a&gt; running locally, and now we want to run it from &lt;a href="https://github.com/features/actions"&gt;GitHub Actions&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7sk1Ac3T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/wpk2l5my9areo8twe6i6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7sk1Ac3T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/wpk2l5my9areo8twe6i6.png" alt="GitHub Action"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First, we can talk at a high level about the GitHub flow in use. I'll probably write up a different post with more details around this because I find folks with a core operational background haven't used GitHub or understand the "whys" around doing some of the things developers do.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create an &lt;a href="https://github.com/lzysh/terraform-google-project/issues/1"&gt;issue&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;Create a branch to work on 

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;NOTE: Branches are deleted after a successful merge into mainline. Also, in the spirit of continuous delivery, these are not long-lived branches and should be integrated frequently&lt;/em&gt; &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Create a &lt;a href="https://github.com/lzysh/terraform-google-project/pull/2"&gt;pull request&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;NOTE: Once the pull request is created, it will (based on our action configuration) run the &lt;a href="https://github.com/lzysh/terraform-google-project/runs/1121079032#step:4:212"&gt;GitHub Action&lt;/a&gt;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Add someone to for review after successful GitHub Action run&lt;/li&gt;
&lt;li&gt;Squash and merge your &lt;a href="https://github.com/lzysh/terraform-google-project/commit/ce6eb7b48f2df32d50930ce363a5fed84ffd9f8e"&gt;commit&lt;/a&gt; after code review&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To get your GitHub Action setup, the first thing we will need to do is create a &lt;a href="https://docs.github.com/en/actions/hosting-your-own-runners/about-self-hosted-runners"&gt;self-hosted runner&lt;/a&gt;. For this example, I ended up using a small compute instance in Google Cloud Platform. You can pick any cloud provider you want or even a machine in your datacenter if needed. It just needs to have the tools installed to do whatever you're asking your action to run. In our case, all the bits to run Kitchen-Terraform. &lt;/p&gt;

&lt;p&gt;Adding a GitHub self-hosted runner has to be the most accessible CI/CD tool "agent-based" install ever, so I don't think we need to go into the details here. I did try to create my own &lt;a href="https://docs.github.com/en/actions/creating-actions/creating-a-docker-container-action"&gt;packaged Docker container action&lt;/a&gt; for Kitchen-Terraform &lt;a href="https://github.com/lzysh/github-kitchen-terraform-action"&gt;here&lt;/a&gt;, but I wouldn't say I liked how it had to build the image each run.&lt;/p&gt;

&lt;p&gt;Once your runner is up and running, you will need to tell GitHub what you want to do and where to do it. We do this using a &lt;a href="https://github.com/lzysh/terraform-google-project/blob/master/.github/workflows/main.yml"&gt;workflow file&lt;/a&gt;. The workflow file is written in YAML and lives inside your GitHub repository in the &lt;code&gt;.github/workflows&lt;/code&gt; directory. You can take a look at the &lt;a href="https://resources.github.com/whitepapers/GitHub-Actions-Cheat-sheet"&gt;GitHub Actions Cheat Sheet&lt;/a&gt;, it describes the contents of a workflow file. Ours is simple, one Job with three steps. First, we tell GitHub the name of the action and when to run it. In our case, on commit to master and pull requests as I talked about earlier. Next, where to run the action:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7qSocHBo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/vm546x4gllaewitgt0db.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7qSocHBo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/vm546x4gllaewitgt0db.png" alt="GitHub Action Workflow File Job"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;runs-on&lt;/code&gt; has the self-hosted runner labels:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bZwMRnm5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/l9q8576cwifrtw79q7d3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bZwMRnm5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/l9q8576cwifrtw79q7d3.png" alt="Self Hosted Runner Labels"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As mentioned in the previous post, we are passing BILLING_ID to terraform as a &lt;a href="https://docs.github.com/en/actions/reference/encrypted-secrets"&gt;secret&lt;/a&gt; from GitHub. You can set secrets and an organizational level or a repository level.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--w5OwfOKA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hija7a3qbpivrzhznb02.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--w5OwfOKA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hija7a3qbpivrzhznb02.png" alt="GitHub Secrets"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we define a default shell to use and the steps to run:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--g6Qzd9sq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/iea66xolz1388yixxxo5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--g6Qzd9sq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/iea66xolz1388yixxxo5.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first step is to use the &lt;a href="https://github.com/marketplace/actions/checkout"&gt;GitHub Checkout Action&lt;/a&gt; to checkout the repository on the runner. The second is to use the &lt;a href="https://github.com/marketplace/actions/setup-gcloud-environment"&gt;Google Cloud Platform Setup gcloud Environment Action&lt;/a&gt; to configure our Google credentials. This action also allows us to set up &lt;a href="https://cloud.google.com/docs/authentication/production"&gt;Google Application Default Credentials (ADC)&lt;/a&gt; by setting &lt;code&gt;export_default_credentials: true&lt;/code&gt;. This is slick because Terraform can use these by default without setting anything up! Finally, we end up at the last step, which runs &lt;code&gt;bundle exec kitchen test&lt;/code&gt; on our self-hosted runner:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0ldWBX8n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ikkmffxylrh7av5adbow.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0ldWBX8n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ikkmffxylrh7av5adbow.png" alt="GitHub Actions Run Terraform-Kitchen Tests"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There we have it! You have yourself a nice little Terraform module you can continue to improve upon over time in a supportable way just like I quoted in another &lt;a href="https://dev.to/brettcurtis/infrastructure-as-code-iac-5cbg"&gt;post&lt;/a&gt; about using some of the good practices we've learned in the software world like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Using source control, adhering to the DRY principle, modularization, maintainability, and using automated testing and deployment.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the next post, we can talk about putting multiple Terraform modules together with the &lt;a href="https://github.com/GoogleCloudPlatform/inspec-gcp-cis-benchmark"&gt;inspec-gcp-cis-benchmark&lt;/a&gt; profile running across all the Google Cloud Platform resources created.&lt;/p&gt;

</description>
      <category>github</category>
      <category>terraform</category>
      <category>devops</category>
      <category>googlecloud</category>
    </item>
    <item>
      <title>Using  Kitchen-Terraform with the GCP CIS Benchmark Profile </title>
      <dc:creator>Brett Curtis</dc:creator>
      <pubDate>Sat, 05 Sep 2020 19:27:13 +0000</pubDate>
      <link>https://dev.to/brettcurtis/gcp-cis-benchmark-terraform-module-testing-with-chef-inspec-kitchen-terraform-github-actions-1227</link>
      <guid>https://dev.to/brettcurtis/gcp-cis-benchmark-terraform-module-testing-with-chef-inspec-kitchen-terraform-github-actions-1227</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8HTrX0Dz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/nu76ifdpv6t49cw36vvu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8HTrX0Dz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/nu76ifdpv6t49cw36vvu.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the last &lt;a href="https://dev.to/brettcurtis/gcp-cis-benchmark-terraform-module-testing-with-chef-inspec-kitchen-terraform-github-actions-4gpl"&gt;post&lt;/a&gt; we covered "local" development. In the spirit of &lt;a href="https://martinfowler.com/articles/continuousIntegration.html"&gt;continuous integration&lt;/a&gt;, we want to be able to have team members integrate their work. If you remember, the violations we had from running the &lt;a href="https://github.com/GoogleCloudPlatform/inspec-gcp-cis-benchmark"&gt;inspec-gcp-cis-benchmark&lt;/a&gt; profile, we've got some work to do! We will do that using &lt;a href="https://github.com/newcontext-oss/kitchen-terraform"&gt;Kitchen-Terraform&lt;/a&gt; and run the workflow in &lt;a href="https://github.com/learn/devops"&gt;GitHub Actions&lt;/a&gt;. In this post, we will cover Kitchen-Terraform.&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Setup
&lt;/h2&gt;

&lt;p&gt;The directory structure is essential when using Kitchen-Terraform. My current structure looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KzdNXVz7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/z2bpkcd5fl99zv60gshx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KzdNXVz7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/z2bpkcd5fl99zv60gshx.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Fixtures
&lt;/h3&gt;

&lt;p&gt;You'll need to have a &lt;a href="https://github.com/lzysh/terraform-google-project/tree/master/test/fixtures"&gt;&lt;code&gt;fixtures&lt;/code&gt;&lt;/a&gt; directory. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mNUSBhR5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gjbbr5o5c3pssiq8v498.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mNUSBhR5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gjbbr5o5c3pssiq8v498.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This directory is where your Terraform root modules will live or in Kitchen-Terraform language, "test fixtures." It will call the child module, the module we are developing. That language aligns with the &lt;a href="https://www.terraform.io/docs/configuration/modules.html"&gt;module documentation&lt;/a&gt;, so in our case, the child module is in the root of the &lt;a href="https://github.com/lzysh/terraform-google-project"&gt;repository&lt;/a&gt;, and it's the module we are publishing through GitHub for reuse. In this example, we only have &lt;a href="https://github.com/lzysh/terraform-google-project/tree/master/test/fixtures/default-project"&gt;one root module&lt;/a&gt; or test fixture we are testing against. There could and most likely will be more if we can't cover multiple test scenarios in a single fixture. I also have a shared directory for common code across numerous test fixtures if needed. &lt;/p&gt;

&lt;h3&gt;
  
  
  Integration
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://github.com/lzysh/terraform-google-project/tree/master/test/integration"&gt;&lt;code&gt;integration&lt;/code&gt;&lt;/a&gt; directory will hold your &lt;a href="https://docs.chef.io/inspec/profiles/"&gt;profile&lt;/a&gt; with the &lt;a href="https://docs.chef.io/inspec/dsl_inspec/"&gt;Chef Inspec DSL controls&lt;/a&gt; you want to run against a test fixture. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UrGiIxI3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hedmaizkn2136k8xf6cb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UrGiIxI3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/hedmaizkn2136k8xf6cb.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For this post, we will focus only on the &lt;a href="https://github.com/lzysh/terraform-google-project/blob/master/test/integration/default-project/controls/cis_benchmark.rb"&gt;&lt;code&gt;cis_benchmark.rb&lt;/code&gt;&lt;/a&gt; and the &lt;a href="https://github.com/lzysh/terraform-google-project/blob/master/test/integration/default-project/inspec.yml"&gt;&lt;code&gt;inspec.yml&lt;/code&gt;&lt;/a&gt; files. Since Google did all the heavy lifting for us by writing the controls for the specific benchmarks we are testing for, &lt;a href="https://github.com/GoogleCloudPlatform/inspec-gcp-cis-benchmark/blob/master/controls/3.01-networking.rb"&gt;3.1 Networking&lt;/a&gt; and &lt;a href="https://github.com/GoogleCloudPlatform/inspec-gcp-cis-benchmark/blob/master/controls/4.04-vms.rb"&gt;4.4 VMS&lt;/a&gt;, we can add them very quickly. First, you add the repository you depend on: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--q3QVi6d4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/y053ldnd71azo4tes8r9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--q3QVi6d4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/y053ldnd71azo4tes8r9.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;NOTE: The input &lt;code&gt;gcp_project_id&lt;/code&gt; is what the inspec-gcp-cis-benchmark profile expects in order to know what project to run the tests against. Kitchen-Terraform can do attribute and Terraform output mapping. I'll touch on why that's important when we look at the &lt;code&gt;kitchen.yml&lt;/code&gt; file.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Then to call a specific control, we add it into the &lt;a href="https://github.com/lzysh/terraform-google-project/blob/master/test/integration/default-project/controls/cis_benchmark.rb"&gt;&lt;code&gt;cis_benchmark.rb&lt;/code&gt;&lt;/a&gt; like so:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--C-FP_XV5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/qyk4ju7sqx82qf0h83o0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--C-FP_XV5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/qyk4ju7sqx82qf0h83o0.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  kitchen.yml
&lt;/h3&gt;

&lt;p&gt;The last thing we need to do is tell Kitchen-Terraform what to do! We do this by creating a &lt;a href="https://github.com/lzysh/terraform-google-project/blob/master/.kitchen.yml"&gt;&lt;code&gt;kitchen.yml&lt;/code&gt;&lt;/a&gt; file:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kNfyNXrj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/vfl61d3j005bmw78bsm6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kNfyNXrj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/vfl61d3j005bmw78bsm6.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can read the documentation about the &lt;a href="https://docs.chef.io/workstation/config_yml_kitchen/"&gt;kitchen.yml&lt;/a&gt; if you want to know more. However, I do want to touch on a couple of things. &lt;/p&gt;

&lt;p&gt;Lines three and four are a way you can pass &lt;code&gt;-var="foo=bar"&lt;/code&gt; to Terraform from inside Kitchen-Terraform. In this example, I'm using the billing ID as a &lt;a href="https://docs.github.com/en/actions/configuring-and-managing-workflows/creating-and-storing-encrypted-secrets"&gt;secret in GitHub&lt;/a&gt;. We can talk about that a bit more when we set up the workflow in GitHub Actions. &lt;/p&gt;

&lt;p&gt;The other thing is the lines twenty-four and twenty-five. This has to do with the attribute and Terraform output mapping I talked about earlier. I took me a bit of &lt;a href="https://github.com/GoogleCloudPlatform/inspec-gcp-cis-benchmark/issues/44"&gt;learning out loud&lt;/a&gt; to get this squared away, but with some help, I was able to get it. To make a long story short, this is how I mapped my Terraform output of &lt;code&gt;project_id&lt;/code&gt; to the attribute needed to run the inspec-gcp-cis-benchmark profile.&lt;/p&gt;

&lt;h3&gt;
  
  
  Running Kitchen-Terraform
&lt;/h3&gt;

&lt;p&gt;Now we can run kitchen &lt;a href="https://docs.chef.io/workstation/ctl_kitchen/#kitchen-converge"&gt;converge&lt;/a&gt; and see what we have:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--L5WAjhMp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/68ewfzu8aovl6ox18wav.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--L5WAjhMp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/68ewfzu8aovl6ox18wav.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is going to do all kinds of work for you. It will verify the Terraform client version, &lt;a href="https://www.terraform.io/docs/commands/init.html"&gt;initialize&lt;/a&gt; the Terraform working directory as well as create and switch to a &lt;a href="https://www.terraform.io/docs/commands/workspace/index.html"&gt;workspace&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rE87H142--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/phgjq6zwsjlxgp6akvzx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rE87H142--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/phgjq6zwsjlxgp6akvzx.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It will also &lt;a href="https://www.terraform.io/docs/commands/validate.html"&gt;validate&lt;/a&gt; the Terraform configuration files and finally run the Terraform &lt;a href="https://www.terraform.io/docs/commands/apply.html"&gt;apply&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Gi4Sn_rE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/m0nkfebqvmyh5st04jmd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Gi4Sn_rE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/m0nkfebqvmyh5st04jmd.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, we can run the tests using kitchen &lt;a href="https://docs.chef.io/workstation/ctl_kitchen/#kitchen-verify"&gt;verify&lt;/a&gt; and see the results:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gqIID6QT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/n5dtam1k5kwoffhticty.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gqIID6QT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/n5dtam1k5kwoffhticty.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, we can destroy the infrastructure using kitchen &lt;a href="https://docs.chef.io/workstation/ctl_kitchen/#kitchen-destroy"&gt;destroy&lt;/a&gt;. You could also do all of the above in one command by running kitchen &lt;a href="https://docs.chef.io/workstation/ctl_kitchen/#kitchen-test"&gt;test&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In the next post, I will talk about running the testing workflow through &lt;a href="https://github.com/lzysh/terraform-google-project/runs/1059655434?check_suite_focus=true#step:4:1"&gt;GitHub Actions&lt;/a&gt;! &lt;/p&gt;

</description>
      <category>devops</category>
      <category>googlecloud</category>
      <category>terraform</category>
      <category>security</category>
    </item>
    <item>
      <title>Terraform Development &amp; Testing Introduction</title>
      <dc:creator>Brett Curtis</dc:creator>
      <pubDate>Fri, 04 Sep 2020 21:49:14 +0000</pubDate>
      <link>https://dev.to/brettcurtis/gcp-cis-benchmark-terraform-module-testing-with-chef-inspec-kitchen-terraform-github-actions-4gpl</link>
      <guid>https://dev.to/brettcurtis/gcp-cis-benchmark-terraform-module-testing-with-chef-inspec-kitchen-terraform-github-actions-4gpl</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fnu76ifdpv6t49cw36vvu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fnu76ifdpv6t49cw36vvu.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm starting to play around with &lt;a href="https://github.com/newcontext-oss/kitchen-terraform" rel="noopener noreferrer"&gt;kitchen-terraform&lt;/a&gt; for testing and compliance of Terraform modules. I'm currently using the &lt;a href="https://github.com/inspec/inspec-gcp" rel="noopener noreferrer"&gt;inspec-gcp&lt;/a&gt; resource pack and the &lt;a href="https://github.com/GoogleCloudPlatform/inspec-gcp-cis-benchmark" rel="noopener noreferrer"&gt;inspec-gcp-cis-benchmark&lt;/a&gt; profile. This post will focus on the latter. The drivers for doing this are testing code's self-evident benefits and shifting some reasonable base security standards left. &lt;/p&gt;

&lt;p&gt;To keep things simple, I wanted to start from what you might do first when you begin building cloud infrastructure out in Google. The base of any Google Cloud Platform service is a &lt;a href="https://cloud.google.com/resource-manager/docs/creating-managing-projects" rel="noopener noreferrer"&gt;project&lt;/a&gt;. The module I will be talking about is &lt;a href="https://github.com/lzysh/terraform-google-project" rel="noopener noreferrer"&gt;here&lt;/a&gt; for reference and covers building a project. It's a reasonably opinionated terraform module to fit some use cases I had; however, I think it shows the example of what I'm trying to do without being too complex and confusing. Because honestly, this stuff is hard for non-developer, ex-operational mindset people like me. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE: I'm not going into the basics of setting up Terraform, Ruby, Kitchen-Terraform, Chef Inspec, etc. If that's interesting, let me know, and maybe I can do another post. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  "Local" Development
&lt;/h2&gt;

&lt;p&gt;Learning from the practices of software development, we need to be able to develop "locally." When I say locally here, we can consider it a sandboxed area in the Google Cloud Platform resource hierarchy where you can create and build infrastructure safely. When you start your Terraform module development, you will most likely end up with something like this in your &lt;code&gt;main.tf&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Project Resource&lt;/span&gt;
&lt;span class="c1"&gt;# https://www.terraform.io/docs/providers/google/r/google_project.html&lt;/span&gt;

&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"google_project"&lt;/span&gt; &lt;span class="s2"&gt;"this"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;                     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;project_id&lt;/span&gt;
  &lt;span class="nx"&gt;project_id&lt;/span&gt;               &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;project_id&lt;/span&gt;
  &lt;span class="nx"&gt;billing_account&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;billing_id&lt;/span&gt;
  &lt;span class="nx"&gt;folder_id&lt;/span&gt;                &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"folders/${var.folder_id}"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and a &lt;code&gt;variables.tf&lt;/code&gt; file like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"billing_id"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Billing ID for the project to use"&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"project_id"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Project ID (This will be used for the project name as well)"&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"folder_id"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Folder ID for the project to be created in."&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can now run the terraform and create our Google Cloud project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform init
&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 plan -out plan.out -var="billing_id=00000C-AZAZAZ-EFEFEF" \
-var="project_id=test-del-me-4876des" \
-var="folder_id=993877078800"
&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 plan.out
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you've got a project up and running, but you may be surprised that you have already violated a bunch of CIS Benchmarks! Thanks to Google and the work folks have done in the &lt;a href="https://github.com/GoogleCloudPlatform/inspec-gcp-cis-benchmark" rel="noopener noreferrer"&gt;inspec-gcp-cis-benchmark&lt;/a&gt; GitHub repository; we can test it! &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE: This is not an officially supported Google product, but hopefully, they maintain this repo with help from the community.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One thing I love about this GitHub project is that it runs directly against a specific Google Cloud project. For me, that's precisely the level at which I want to run the tests. I'll get into more details on that later, but for now, lets &lt;code&gt;inspec&lt;/code&gt; the project we just built to see what we need to do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;inspec exec https://github.com/GoogleCloudPlatform/inspec-gcp-cis-benchmark.git \
-t gcp:// --input gcp_project_id=test-del-me-4876des
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After running that command, you're going to see a list of violations. In the spirit of Test Driven Development (TDD), we have our failing test, and now we can code to fix it. We will integrate all this is the next post. For the sake of simplicity, let's focus on two of them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;×  cis-gcp-4.4-vms: [VMS] Ensure oslogin is enabled for a Project
×  cis-gcp-3.1-networking: [NETWORKING] Ensure the default network does not exist in a project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The idea here is that we address these issues as far left in the process as possible. I'm still developing "locally." If you deploy a bunch of stuff on default networks, and three years later, your security team says, we need to get everything CIS compliant; &lt;strong&gt;you will have an unruly amount of operational work!&lt;/strong&gt; Let's fix these compliance issues now. To do that we can add a few lines to the Terraform module code. Then, everyone in your organization that consumes it will meet the standard.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Project Resource&lt;/span&gt;
&lt;span class="c1"&gt;# https://www.terraform.io/docs/providers/google/r/google_project.html&lt;/span&gt;

&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"google_project"&lt;/span&gt; &lt;span class="s2"&gt;"this"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;                &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;project_id&lt;/span&gt;
  &lt;span class="nx"&gt;project_id&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;project_id&lt;/span&gt;
  &lt;span class="nx"&gt;billing_account&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;billing_id&lt;/span&gt;
  &lt;span class="nx"&gt;folder_id&lt;/span&gt;           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"folders/${var.folder_id}"&lt;/span&gt;
  &lt;span class="nx"&gt;auto_create_network&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="c1"&gt;# Project Metadata Resource&lt;/span&gt;
&lt;span class="c1"&gt;# https://www.terraform.io/docs/providers/google/r/compute_project_metadata.html&lt;/span&gt;

&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"google_compute_project_metadata"&lt;/span&gt; &lt;span class="s2"&gt;"this"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;project&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;google_project&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;project&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;project_id&lt;/span&gt;
  &lt;span class="nx"&gt;metadata&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;enable-oslogin&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, you can destroy your previous project and recreate it using this code, and you will see you've passed the tests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✔  cis-gcp-3.1-networking: [NETWORKING] Ensure the default network does not exist in a project
✔  cis-gcp-4.4-vms: [VMS] Ensure oslogin is enabled for a Project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not only that but we went from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Profile Summary: 4 successful controls, 16 control failures, 21 controls skipped
Test Summary: 12 successful, 40 failures, 79 skipped
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Profile Summary: 5 successful controls, 11 control failures, 22 controls skipped
Test Summary: 7 successful, 12 failures, 80 skipped
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I feel like the results speak for themselves. In the next post, we will focus on kitchen-terraform. &lt;/p&gt;

</description>
      <category>devops</category>
      <category>googlecloud</category>
      <category>terraform</category>
      <category>security</category>
    </item>
    <item>
      <title>Infrastructure as Code (IaC)</title>
      <dc:creator>Brett Curtis</dc:creator>
      <pubDate>Sat, 29 Aug 2020 22:30:01 +0000</pubDate>
      <link>https://dev.to/brettcurtis/infrastructure-as-code-iac-5cbg</link>
      <guid>https://dev.to/brettcurtis/infrastructure-as-code-iac-5cbg</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fUL5WniB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/q4m7likjrr498ql24tci.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fUL5WniB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/q4m7likjrr498ql24tci.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
With the cloud, we obviously can go fast, sometimes too fast. We can quickly stand things up via infrastructure automation; however, it can often lead to supportability problems. We have too many things and keep producing more and surprise, surprise no one is getting any less busy. Infrastructure automation is excellent in some cases, for example, short-lived projects, tossing up POC, or even services that are not business-critical. However, longer-lived projects and business-critical services need to support infrastructure as code (IaC). The monumental difference is the two words "&lt;strong&gt;as code&lt;/strong&gt;," meaning:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"All the good practices we've learned in the software world should be applied to infrastructure. Using source control, adhering to the DRY principle, modularization, maintainability, and using automated testing and deployment are all critical practices. Those of us with a deep software and infrastructure background need to empathize with and support colleagues who do not. Saying "treat infrastructure like code" isn't enough; we need to ensure the hard-won learnings from the software world are also applied consistently throughout the infrastructure realm." - &lt;a href="https://www.thoughtworks.com"&gt;ThoughtWorks&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The problem I see and hear across many organizations in this space is we are not dedicating resources to it, and often the pay now live later mentality that comes along with IaC gets shut down in favor of timelines. I also see that people are so embedded with their current work, done their way, using their tools that they are their own worst enemy, creating systems that only they can support. That could be from a complexity standpoint or even an access/control standpoint. That means they don't even have the time to learn something new like IaC and in some cases do not want to. Simply put, we are just stumbling over the existing cloud implementations and the comfort of doing things the same old way.&lt;/p&gt;

&lt;p&gt;Back when we were ordering and racking servers in the data center, you could see workloads, security issues, and problems add up. Now, with the speed, flexibility, and ease of cloud, these things are multiplied, and you can see it. I think Yevgeniy Brikman, Co-Founder of &lt;a href="https://www.gruntwork.io"&gt;Gruntworks&lt;/a&gt;, describes the problem well in the first 3 minutes of &lt;a href="https://www.youtube.com/watch?v=LVgP63BkhKQ"&gt;his story&lt;/a&gt; he tells back at HashiConf'17. The funny thing here is, he's only talking about one application on a single cloud provider, and it's overwhelming. Guess what, if you're in any organization larger than 500 people, I bet you have at least a few applications, if not hundreds, even across different cloud providers.&lt;/p&gt;

&lt;p&gt;I have some hope though, hope that treating infrastructure like code is a solution. With a dedicated cross-organizational team of development, operations, testing, and security with a focus of continuous improvement, the idea that our applications' infrastructure foundation can benefit from "&lt;em&gt;the hard-won learnings from the software world&lt;/em&gt;" can be realized! &lt;/p&gt;

&lt;p&gt;I recently started this adventure and would be interested in hearing if IaC has worked for your organization. What are some of the essential practices you've adopted from software development? I'd also be interested in learning about some of the challenges and issues (people or technology) you had to solve along the way.&lt;/p&gt;

</description>
      <category>iac</category>
      <category>infrastructure</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
