<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Rafaf Tahsin</title>
    <description>The latest articles on Forem by Rafaf Tahsin (@rafaftahsin).</description>
    <link>https://forem.com/rafaftahsin</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%2F1080402%2F4d73dfc5-34e4-43fb-a458-c57d36f95281.jpeg</url>
      <title>Forem: Rafaf Tahsin</title>
      <link>https://forem.com/rafaftahsin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/rafaftahsin"/>
    <language>en</language>
    <item>
      <title>bash conditions</title>
      <dc:creator>Rafaf Tahsin</dc:creator>
      <pubDate>Mon, 09 Oct 2023 04:25:55 +0000</pubDate>
      <link>https://forem.com/rafaftahsin/bash-conditions-pld</link>
      <guid>https://forem.com/rafaftahsin/bash-conditions-pld</guid>
      <description>&lt;ol&gt;
&lt;li&gt;If any command runs successfully inside if conditional expression then if treats it as true.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if print; then echo "foo"; else echo "bar"; fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2 There's a command called &lt;code&gt;test&lt;/code&gt; to evaluate conditional expression.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if test $a -ge $b; 
then 
    echo "a is bigger"; 
else 
    echo "b is bigger"; 
fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;see the &lt;code&gt;test&lt;/code&gt; command ? It evaluates the conditional expression and return true / false base on the evaluation.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;test&lt;/code&gt; is later replaced with &lt;code&gt;[&lt;/code&gt;.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if [ $a -ge $b ]; 
then 
    echo "a is big"; 
else 
    echo "b is big"; 
fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yes, the command is &lt;code&gt;[&lt;/code&gt; and it starts evaluating the expression until it gets &lt;code&gt;]&lt;/code&gt;. You can check it yourself with &lt;code&gt;which [&lt;/code&gt; or even &lt;code&gt;man [&lt;/code&gt;. &lt;code&gt;[&lt;/code&gt; is basically another representation of &lt;code&gt;test&lt;/code&gt; command.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;There's some limitations of using &lt;code&gt;[&lt;/code&gt; or &lt;code&gt;test&lt;/code&gt;. For example, it can't evaluate &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;, &lt;code&gt;||&lt;/code&gt;. So here comes &lt;code&gt;[[&lt;/code&gt; with improvements.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if [[ $a &amp;gt; $b || $a == $b ]]; then echo "a is big"; else echo "b is big"; fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also read more about the differences between &lt;code&gt;[&lt;/code&gt; and &lt;code&gt;[[&lt;/code&gt; from &lt;a href="https://stackoverflow.com/questions/3427872/whats-the-difference-between-and-in-bash"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;There's no ternary operator. But there's a hack ...
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[[ $a == $b ]] &amp;amp;&amp;amp; echo "Equal" || echo "Not equal"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>bash</category>
    </item>
    <item>
      <title>How to import existing dynamodb in terrafrom</title>
      <dc:creator>Rafaf Tahsin</dc:creator>
      <pubDate>Wed, 16 Aug 2023 11:28:44 +0000</pubDate>
      <link>https://forem.com/rafaftahsin/how-to-import-existing-dynamodb-in-terrafrom-3emj</link>
      <guid>https://forem.com/rafaftahsin/how-to-import-existing-dynamodb-in-terrafrom-3emj</guid>
      <description>&lt;p&gt;Well I was having difficult time importing dynamodb and trying with arn, but it was db name that needs to be mentioned while importing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terragrunt import aws_dynamodb_table.dynamodb_resource dynamodb_table_name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>How to restrict AWS access from office Ips only</title>
      <dc:creator>Rafaf Tahsin</dc:creator>
      <pubDate>Fri, 11 Aug 2023 17:24:10 +0000</pubDate>
      <link>https://forem.com/rafaftahsin/how-to-restrict-aws-access-from-office-ips-only-3akl</link>
      <guid>https://forem.com/rafaftahsin/how-to-restrict-aws-access-from-office-ips-only-3akl</guid>
      <description>&lt;p&gt;Use Source IP condition in IAM policy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Statement1",
            "Effect": "Allow",
            "Action": [
                "*"
            ],
            "Resource": [
                "*"
            ],
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": [
                        "202.74.246.XXX/32"
                    ]
                }
            }
        }
    ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Migrate an EC2 instance from one AWS account to another</title>
      <dc:creator>Rafaf Tahsin</dc:creator>
      <pubDate>Sun, 23 Jul 2023 05:45:50 +0000</pubDate>
      <link>https://forem.com/rafaftahsin/migrate-an-ec2-instance-from-one-aws-account-to-another-fjj</link>
      <guid>https://forem.com/rafaftahsin/migrate-an-ec2-instance-from-one-aws-account-to-another-fjj</guid>
      <description>&lt;h3&gt;
  
  
  Create an AMI  of the instance
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws ec2 create-image \
    --instance-id &amp;lt;i-0123456789abcdef&amp;gt; \
    --name "AMI-Image-Name" \
    --description "AMI Image of EC2 created from Source AWS Account to Destination AWS Account" \
    --region &amp;lt;region-id&amp;gt; \
    --profile &amp;lt;optional-profile&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Above command will output an Image ID. We will share this image with the destination AWS Account. Image creation might take some time. When the image is created run following command to give permission to destination AWS account.&lt;/p&gt;

&lt;h3&gt;
  
  
  Give AMI Permission to destination AWS Account
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws ec2 modify-image-attribute \
    --image-id &amp;lt;AMI-ID-retrieved-from-above-command&amp;gt; \
    --region &amp;lt;region-id&amp;gt; \
    --launch-permission "Add=[{UserId=&amp;lt;destination-aws-account-id&amp;gt;}]" \
    --profile infolytxdev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/cli/latest/reference/ec2/create-image.html"&gt;https://docs.aws.amazon.com/cli/latest/reference/ec2/create-image.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/sharingamis-explicit.html"&gt;https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/sharingamis-explicit.html&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
    </item>
    <item>
      <title>DRY your terraform code using dynamic block</title>
      <dc:creator>Rafaf Tahsin</dc:creator>
      <pubDate>Mon, 17 Jul 2023 05:49:19 +0000</pubDate>
      <link>https://forem.com/rafaftahsin/dry-your-terraform-code-using-dynamic-block-3e5</link>
      <guid>https://forem.com/rafaftahsin/dry-your-terraform-code-using-dynamic-block-3e5</guid>
      <description>&lt;p&gt;Without &lt;code&gt;dynamic&lt;/code&gt; block a security group resource looks like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_security_group" "instance_security_group" {
  ingress {
    # TLS (change to whatever ports you need)
    from_port   = 80
    to_port     = 80
    protocol    = "TCP"
    cidr_blocks = [ "0.0.0.0/0" ] # add a CIDR block here
  }

  ingress {
    # TLS (change to whatever ports you need)
    from_port   = 443
    to_port     = 443
    protocol    = "TCP"
    cidr_blocks = [ "0.0.0.0/0" ] # add a CIDR block here
  }

  ingress {
    # TLS (change to whatever ports you need)
    from_port   = 22
    to_port     = 22
    protocol    = "TCP"
    cidr_blocks = [ "${var.office_IP}/32" ]
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Above code can be dried with terraform &lt;code&gt;dynamic&lt;/code&gt; block to look like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;locals {
  ingress_rules = [
    { from_port = 80, to_port = 80, cidr_blocks = [ "0.0.0.0/0" ] },
    { from_port = 443, to_port = 443, cidr_blocks = [ "0.0.0.0/0" ] },
    { from_port = 22, to_port = 22, cidr_blocks = [ "${var.office_IP}/32" ] }
  ]
}

resource "aws_security_group" "instance_security_group" {
  dynamic "ingress" {
    for_each = local.ingress_rules
    iterator = i
    content {
      from_port   = i.value.from_port
      to_port     = i.value.to_port
      protocol    = "TCP"
      cidr_blocks = i.value.cidr_blocks
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;More about terraform dynamic block - &lt;a href="https://developer.hashicorp.com/terraform/language/expressions/dynamic-blocks"&gt;https://developer.hashicorp.com/terraform/language/expressions/dynamic-blocks&lt;/a&gt; &lt;/p&gt;

</description>
    </item>
    <item>
      <title>aws cred to env</title>
      <dc:creator>Rafaf Tahsin</dc:creator>
      <pubDate>Wed, 12 Jul 2023 06:17:38 +0000</pubDate>
      <link>https://forem.com/rafaftahsin/aws-cred-to-env-6kk</link>
      <guid>https://forem.com/rafaftahsin/aws-cred-to-env-6kk</guid>
      <description>&lt;p&gt;Sometimes it's tidy to export aws credentials manually. It can be done by the following script&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash

echo "# Environment for AWS profile '$1'"
export AWS_ACCESS_KEY_ID=$(aws configure get aws_access_key_id --profile $1)
export AWS_SECRET_ACCESS_KEY=$(aws configure get aws_secret_access_key --profile $1)
export AWS_DEFAULT_REGION=$(aws configure get region --profile $1)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;source the script and you are done.&lt;/p&gt;

&lt;p&gt;Note:&lt;/p&gt;

&lt;p&gt;Saving script as &lt;code&gt;script.sh&lt;/code&gt; and calling it with &lt;code&gt;./script.sh&lt;/code&gt; won't work. Need to source it like &lt;code&gt;source script.sh&lt;/code&gt; or &lt;code&gt;. script.sh&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Inspired by &lt;a href="https://gist.github.com/mjul/f93ee7d144c5090e6e3c463f5f312587"&gt;https://gist.github.com/mjul/f93ee7d144c5090e6e3c463f5f312587&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>bash</category>
      <category>devops</category>
      <category>terminal</category>
    </item>
    <item>
      <title>Any better way to calculate AWS CodeArtifact Usage?</title>
      <dc:creator>Rafaf Tahsin</dc:creator>
      <pubDate>Mon, 03 Jul 2023 09:44:29 +0000</pubDate>
      <link>https://forem.com/rafaftahsin/any-better-way-to-calculate-aws-codeartifact-usage-56el</link>
      <guid>https://forem.com/rafaftahsin/any-better-way-to-calculate-aws-codeartifact-usage-56el</guid>
      <description>&lt;p&gt;I needed to know consumed total storage in AWS CodeArtifact. I didn't get this from AWS Console or straight forward aws cli. So I came up with this dirty way ...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;AWS_PROFILE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;infolytxdev

&lt;span class="nv"&gt;domains&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws codeartifact list-domains | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s2"&gt;".domains[].name"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;total_artifactory_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0

&lt;span class="k"&gt;for &lt;/span&gt;d &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;$domains&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nv"&gt;repos&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws codeartifact list-repositories-in-domain &lt;span class="nt"&gt;--domain&lt;/span&gt; &lt;span class="nv"&gt;$d&lt;/span&gt; | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s2"&gt;".repositories[].name"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;r &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;$repos&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
    &lt;/span&gt;&lt;span class="nv"&gt;packages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws codeartifact list-packages &lt;span class="nt"&gt;--domain&lt;/span&gt; &lt;span class="nv"&gt;$d&lt;/span&gt; &lt;span class="nt"&gt;--repository&lt;/span&gt; &lt;span class="nv"&gt;$r&lt;/span&gt; | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s2"&gt;".packages[].package"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;p &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;$packages&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
      &lt;/span&gt;&lt;span class="nv"&gt;packageversions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws codeartifact list-package-versions &lt;span class="nt"&gt;--package&lt;/span&gt; &lt;span class="nv"&gt;$p&lt;/span&gt; &lt;span class="nt"&gt;--domain&lt;/span&gt; &lt;span class="nv"&gt;$d&lt;/span&gt; &lt;span class="nt"&gt;--repository&lt;/span&gt; &lt;span class="nv"&gt;$r&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt; pypi | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s2"&gt;".versions[].version"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

      &lt;span class="k"&gt;for &lt;/span&gt;pv &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;$packageversions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
        &lt;/span&gt;&lt;span class="nv"&gt;sizes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws codeartifact list-package-version-assets &lt;span class="nt"&gt;--domain&lt;/span&gt; &lt;span class="nv"&gt;$d&lt;/span&gt; &lt;span class="nt"&gt;--repo&lt;/span&gt; &lt;span class="nv"&gt;$r&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt; pypi &lt;span class="nt"&gt;--package&lt;/span&gt; &lt;span class="nv"&gt;$p&lt;/span&gt; &lt;span class="nt"&gt;--package-version&lt;/span&gt; &lt;span class="nv"&gt;$pv&lt;/span&gt; | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s2"&gt;".assets[].size"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
        &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$d&lt;/span&gt;&lt;span class="s2"&gt;" "&lt;/span&gt;&lt;span class="nv"&gt;$p&lt;/span&gt;&lt;span class="s2"&gt;" "&lt;/span&gt;&lt;span class="nv"&gt;$r&lt;/span&gt;&lt;span class="s2"&gt;" "&lt;/span&gt;&lt;span class="nv"&gt;$pv&lt;/span&gt;&lt;span class="s2"&gt;" "&lt;/span&gt;&lt;span class="nv"&gt;$sizes&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;size.tb

        &lt;span class="nv"&gt;total&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0

        &lt;span class="k"&gt;for &lt;/span&gt;size &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;$sizes&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
          &lt;/span&gt;&lt;span class="nb"&gt;sum&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;&lt;span class="nv"&gt;$total&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;$size&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;
        &lt;span class="k"&gt;done

        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Package Size: &lt;/span&gt;&lt;span class="nv"&gt;$sum&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;size.tb
        &lt;span class="nv"&gt;total_artifactory_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$((&lt;/span&gt;total_artifactory_size &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nv"&gt;$sum&lt;/span&gt;&lt;span class="k"&gt;))&lt;/span&gt;

      &lt;span class="k"&gt;done
    done
  done
done

&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Total Artifactory Size: &lt;/span&gt;&lt;span class="nv"&gt;$total_artifactory_size&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Any better way to accomplish this?&lt;/p&gt;

</description>
      <category>aws</category>
      <category>bash</category>
    </item>
    <item>
      <title>How to restrict a user to use single region in AWS</title>
      <dc:creator>Rafaf Tahsin</dc:creator>
      <pubDate>Tue, 20 Jun 2023 08:51:35 +0000</pubDate>
      <link>https://forem.com/rafaftahsin/how-to-restrict-a-user-to-use-single-region-in-aws-32fa</link>
      <guid>https://forem.com/rafaftahsin/how-to-restrict-a-user-to-use-single-region-in-aws-32fa</guid>
      <description>&lt;p&gt;IAM policy to restrict user to a single region&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Statement1",
            "Effect": "Allow",
            "Action": [
                "*"
            ],
            "Resource": [
                "*"
            ],
            "Condition": {
                "StringEquals": {
                    "aws:RequestedRegion": [
                        "us-west-1"
                    ]
                }
            }
        }
    ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>aws</category>
      <category>security</category>
    </item>
    <item>
      <title>How to enforce MFA in AWS - Part I - Create User, Role &amp; Policy</title>
      <dc:creator>Rafaf Tahsin</dc:creator>
      <pubDate>Tue, 20 Jun 2023 08:34:13 +0000</pubDate>
      <link>https://forem.com/rafaftahsin/how-to-enforce-mfa-in-aws-part-i-create-user-role-policy-1apo</link>
      <guid>https://forem.com/rafaftahsin/how-to-enforce-mfa-in-aws-part-i-create-user-role-policy-1apo</guid>
      <description>&lt;p&gt;In this tutorial I will demonstrate How to enfornce 2FA in both AWS CLI and AWS Console. Later in the tutorial I will share a script to quickly authenticate with MFA and use generated token.&lt;/p&gt;

&lt;p&gt;1. At first we will create a user who has only access to &lt;code&gt;sts:AssumeRole&lt;/code&gt; with MFA condition. We can create the user manually or with the following terraform script.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_iam_user" "mfa_user" {
  # path = "/user_path_if_necessary/"
  name = "aws_cli_user"
}

data "aws_iam_policy_document" "sts_assume_role_policy_docuement" {
  statement {
    actions   = ["sts:AssumeRole"]
    resources = ["*"]
    effect    = "Allow"
    condition {
      test     = "Bool"
      values   = ["true"]
      variable = "aws:MultiFactorAuthPresent"
    }
  }
}

resource "aws_iam_policy" "sts_assume_role_policy" {
  name   = "sts_assume_role_policy"
  policy = data.aws_iam_policy_document.sts_assume_role_policy_docuement.json
}

resource "aws_iam_policy_attachment" "sts_assume_role_policy_attachment" {
  name       = "sts_assume_role_policy_attachment"
  policy_arn = aws_iam_policy.sts_assume_role_policy.arn
  users      = [aws_iam_user.mfa_user.name]
}

resource "aws_iam_access_key" "mfa_user_keys" {
  user = aws_iam_user.mfa_user.name
}

resource "aws_iam_user_login_profile" "mfa_user_console_login_profile" {
  user = aws_iam_user.mfa_user.name
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2. You can get the credentials with the following &lt;code&gt;output.tf&lt;/code&gt; output file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;output "mfa_user_access_key" {
  value = aws_iam_access_key.mfa_user_keys.id
}

output "mfa_user_secret_key" {
  value     = aws_iam_access_key.mfa_user_keys.secret
  sensitive = true
}

output "mfa_user_console_password" {
  value = aws_iam_user_login_profile.mfa_user_console_login_profile.password
  sensitive = true
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;3. Now Create a Virtual device for &lt;code&gt;mfa_user&lt;/code&gt; from AWS Console.&lt;/p&gt;

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

&lt;p&gt;4. We will now create the role that will be assumed by the user. For the purpose of the tutorial I've attached an AWS managed Administrator policy with the role.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_iam_role" "iam_admin_role_with_mfa_restriction" {
  name               = "admin_mfa"
  assume_role_policy = jsonencode({
    "Version" : "2012-10-17",
    "Statement" : [
      {
        "Effect" : "Allow",
        "Principal" : {
          "AWS" : "arn:aws:iam::${var.aws_account_id}:root"
        },
        "Action" : "sts:AssumeRole",
        "Condition" : {
          "Bool" : {
            "aws:MultiFactorAuthPresent" : "true"
          }
        }
      }
    ]
  })
  managed_policy_arns = ["arn:aws:iam::aws:policy/AdministratorAccess"]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the user is ready, you can have a look at the full terraform code &lt;a href="https://gitlab.com/rt07/examples/terraform/terraform-examples/-/tree/master/iam_mfa_user"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lets jump into &lt;a href="https://dev.to/rafaftahsin/how-to-enforce-mfa-in-aws-cli-part-ii-using-aws-cli-and-terraform-with-mfa-e74"&gt;Part II of the tutorial&lt;/a&gt; where we will discuss about how to access aws using MFA.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>security</category>
      <category>tutorial</category>
      <category>bash</category>
    </item>
    <item>
      <title>How to enforce MFA in AWS - Part II - Using `aws` CLI and terraform with MFA</title>
      <dc:creator>Rafaf Tahsin</dc:creator>
      <pubDate>Tue, 20 Jun 2023 08:32:44 +0000</pubDate>
      <link>https://forem.com/rafaftahsin/how-to-enforce-mfa-in-aws-cli-part-ii-using-aws-cli-and-terraform-with-mfa-e74</link>
      <guid>https://forem.com/rafaftahsin/how-to-enforce-mfa-in-aws-cli-part-ii-using-aws-cli-and-terraform-with-mfa-e74</guid>
      <description>&lt;p&gt;Part I =&amp;gt; &lt;a href=""&gt;How to enforce MFA in AWS CLI - Part I&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here in Part II we will discuss how to access aws using MFA&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;code&gt;aws&lt;/code&gt; cli
&lt;/h1&gt;

&lt;p&gt;1. Use &lt;code&gt;aws configure --profile mfa_user&lt;/code&gt; to configure mfa user in aws cli. Get the user credentials from terraform outputs. Sensitive outputs can be retrieved with &lt;code&gt;terraform output &amp;lt;sensitive_output_data&amp;gt;&lt;/code&gt;. After configuration your &lt;code&gt;~/.aws/credentials&lt;/code&gt; should contains this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[mfa_user]
aws_access_key_id = ABCD$$$$$$$$
aws_secret_access_key = knklvdf093487jps/df\$$$$$$$$$$$$$$$$$$$$$$
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2. Lets create role profile&lt;/p&gt;

&lt;p&gt;To create a role profile add &lt;code&gt;admin_role&lt;/code&gt; profile section in &lt;code&gt;~/.aws/config&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[profile admin_role]
role_arn = arn:aws:iam::&amp;lt;account_number&amp;gt;:role/admin_mfa
source_profile = mfa_user
mfa_serial = arn:aws:iam::&amp;lt;account_number&amp;gt;:mfa/mfa  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can get &lt;code&gt;role_arn&lt;/code&gt; from terraform output. Get MFA Serial from AWS Console.&lt;/p&gt;

&lt;p&gt;3. Now you can use aws cli with &lt;code&gt;admin_role&lt;/code&gt; profile&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws s3 ls --profile admin_role
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  terraform
&lt;/h1&gt;

&lt;p&gt;If you enable MFA, configuring terraform gets a bit hacky. You can use &lt;a href="https://gitlab.com/rt07/examples/terraform/terraform-examples/-/blob/master/iam_mfa_user/auth.sh" rel="noopener noreferrer"&gt;following script&lt;/a&gt; to automate this process.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env bash&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"totp is &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="nv"&gt;ROLE_ARN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:iam::&amp;lt;account_number&amp;gt;:role/admin_role"&lt;/span&gt;
&lt;span class="nv"&gt;MFA_ARN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:iam::&amp;lt;account_number&amp;gt;:mfa/mfa"&lt;/span&gt;

aws sts assume-role &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--role-arn&lt;/span&gt; &lt;span class="nv"&gt;$ROLE_ARN&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--role-session-name&lt;/span&gt; session-one &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--serial-number&lt;/span&gt; &lt;span class="nv"&gt;$MFA_ARN&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--token-code&lt;/span&gt; &lt;span class="nv"&gt;$1&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /tmp/sts.json

aws configure &lt;span class="nb"&gt;set &lt;/span&gt;aws_access_key_id &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /tmp/sts.json | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.Credentials.AccessKeyId'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;--profile&lt;/span&gt; terraform
aws configure &lt;span class="nb"&gt;set &lt;/span&gt;aws_secret_access_key &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /tmp/sts.json | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.Credentials.SecretAccessKey'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;--profile&lt;/span&gt; terraform
aws configure &lt;span class="nb"&gt;set &lt;/span&gt;aws_session_token &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /tmp/sts.json | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.Credentials.SessionToken'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;--profile&lt;/span&gt; terraform
aws configure &lt;span class="nb"&gt;set &lt;/span&gt;region &lt;span class="s2"&gt;"ap-southeast-1"&lt;/span&gt; &lt;span class="nt"&gt;--profile&lt;/span&gt; terraform

&lt;span class="nb"&gt;rm&lt;/span&gt; /tmp/sts.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you can use this script with &lt;code&gt;./auth.sh &amp;lt;6 Digit MFA Code&amp;gt;&lt;/code&gt;. This will configure aws profile named &lt;code&gt;terraform&lt;/code&gt;. You can configure terraform aws provider with with this profile.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;provider "aws" {
  profile = "terraform"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  AWS Console
&lt;/h1&gt;

&lt;p&gt;Use Switch role button to switch to admin role after signing in to AWS Console.&lt;/p&gt;

&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%2Fuploads%2Farticles%2Fjesn579kwbtgzahkgt3j.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%2Fuploads%2Farticles%2Fjesn579kwbtgzahkgt3j.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>security</category>
      <category>tutorial</category>
      <category>bash</category>
    </item>
    <item>
      <title>You can't create aws virtual mfa with terrafrom</title>
      <dc:creator>Rafaf Tahsin</dc:creator>
      <pubDate>Sun, 18 Jun 2023 12:42:40 +0000</pubDate>
      <link>https://forem.com/rafaftahsin/you-cant-create-aws-virtual-mfa-with-terrafrom-1io0</link>
      <guid>https://forem.com/rafaftahsin/you-cant-create-aws-virtual-mfa-with-terrafrom-1io0</guid>
      <description>&lt;p&gt;It's just an FYI. Though theoretically you can create an aws virtual mfa device through terraform but you can't enable it or assign it to a user.&lt;/p&gt;

&lt;p&gt;The process to create virtual mfa has two steps from aws-cli perspective.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/cli/latest/reference/iam/create-virtual-mfa-device.html"&gt;Creating the mfa device&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws iam create-virtual-mfa-device --virtual-mfa-device-name BobsMFADevice --outfile C:/QRCode.png --bootstrap-method QRCodePNG
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/cli/latest/reference/iam/enable-mfa-device.html"&gt;Enabling the mfa device with auth Code&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws iam enable-mfa-device \
    --user-name Bob \
    --serial-number arn:aws:iam::210987654321:mfa/BobsMFADevice \
    --authentication-code1 123456 \
    --authentication-code2 789012
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can complete both steps using aws-cli. But using terraform you only can create the mfa device, you can't enable it or assign it to a user.&lt;/p&gt;

&lt;p&gt;Yes, I understand it's legit from terraform's perspective. As you need to put auth code every time to enable a virtual mfa device. That's not what we want to do with every &lt;code&gt;terraform apply&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But the scope to create the virtual mfa doesn't mean anything without having the opportunity to assign it.&lt;/p&gt;

&lt;p&gt;Looking forward how terraform solves this in future.&lt;/p&gt;

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