<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Gurjot's Blog]]></title><description><![CDATA[Cloud Engineer @AWS, Web Developer, Writer, Creator. 

Writing articles to make your tech journey smoother and productive!]]></description><link>https://blog.gurjot.dev</link><generator>RSS for Node</generator><lastBuildDate>Sat, 05 Sep 2026 07:39:46 GMT</lastBuildDate><atom:link href="https://blog.gurjot.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Enabling Autocomplete for AWS CLI]]></title><description><![CDATA[AWS CLI is the standard way to interact with AWS services using commands in your command-line shell. AWS has over 200 fully-featured services. So, it is almost impossible to remember every CLI command and their parameters. This requires us to refer t...]]></description><link>https://blog.gurjot.dev/enabling-autocomplete-for-aws-cli</link><guid isPermaLink="true">https://blog.gurjot.dev/enabling-autocomplete-for-aws-cli</guid><category><![CDATA[AWS]]></category><category><![CDATA[command line]]></category><category><![CDATA[cli]]></category><category><![CDATA[Cloud]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Gurjot Singh]]></dc:creator><pubDate>Sun, 28 Nov 2021 12:35:22 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1638098716905/Zthv93Ij1.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>AWS CLI is the standard way to interact with AWS services using commands in your command-line shell. AWS has over 200 fully-featured services. So, it is almost impossible to remember every CLI command and their parameters. This requires us to refer the  <a target="_blank" href="https://awscli.amazonaws.com/v2/documentation/api/latest/reference/index.html">AWS CLI documentation</a>  again and again.</p>
<p>The in-built <strong>"Auto-prompt"</strong> feature provided by <strong><em>AWS CLI (v2)</em></strong> can be easily used to minimise the number of times we refer the CLI documentation.</p>
<p><strong>Note:</strong> The AWS CLI (v1) does not support this feature. We can easily check the current version of our AWS CLI using the following command:</p>
<pre><code class="lang-bash">aws --version
</code></pre>
<h3 id="heading-auto-prompt-in-action">Auto-prompt in action 🧑‍💻</h3>
<p>Just type the partial command that you know, and then click "Enter" to kick-in this feature 👇</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1638099949800/SfiXWpP-c.gif" alt="aws-cli-blog.gif" /></p>
<h3 id="heading-modes-of-auto-prompt">Modes of Auto-prompt</h3>
<p>Before configuring this, lets talk about the two modes of auto-prompt feature that are provided by AWS CLI:</p>
<ul>
<li><strong>Full mode:</strong> This mode uses the auto-prompt feature each time user runs an AWS command which can be either a complete command or an incomplete command. This can be done manually using the --cli-auto-prompt parameter or can be enabled permanently using the configuration file.</li>
<li><strong>Partial mode:</strong> This mode uses the auto-prompt feature if a command is incomplete or cannot be run due to a client-side validation error. This mode is useful in scenarios where you only want to be auto-prompted for commands you are unfamiliar with rather than prompted on every command.</li>
</ul>
<h3 id="heading-recommendation">Recommendation</h3>
<p>Based on my experience, the "Partial mode" for this feature is better than the "Full mode". This helps to avoid any unnecessary prompts if the AWS CLI command you are running is already correct.</p>
<h3 id="heading-configuration">Configuration</h3>
<p>The "auto-prompt" feature can be enabled using the following command:</p>
<p>⭐️ <strong>Full mode</strong></p>
<pre><code class="lang-bash">aws configure <span class="hljs-built_in">set</span> cli_auto_prompt on
</code></pre>
<p>⭐️ <strong>Partial mode</strong></p>
<pre><code class="lang-bash">aws configure <span class="hljs-built_in">set</span> cli_auto_prompt on-partial
</code></pre>
<p>After using the above commands, this feature is only enabled for the AWS CLI default profile. </p>
<p>⭐️ <strong>Enabling it for a specific AWS CLI profile</strong></p>
<p>We can enable this for a specific AWS CLI profile using the --profile parameter i.e.</p>
<pre><code class="lang-bash">aws configure <span class="hljs-built_in">set</span> cli_auto_prompt on-partial --profile &lt;profile-name&gt;
</code></pre>
<p>And thats it. We are done learning another less known but an useful feature while working with AWS. </p>
<p>Now you can enjoy this feature and reduce the amount of time you  spend referring to the AWS CLI documentation.</p>
<h3 id="heading-reference">Reference</h3>
<p><a target="_blank" href="https://docs.aws.amazon.com/cli/latest/userguide/cli-usage-parameters-prompting.html">Having the AWS CLI prompt you for commands</a></p>
<hr />
<p>👋 Enjoyed the article? Reach out to me anytime in the comments below or on  <a target="_blank" href="https://twitter.com/gurjotsingh4398">Twitter</a>  for any further discussion or feedback.</p>
]]></content:encoded></item><item><title><![CDATA[AWS Access Keys - AKIA vs ASIA]]></title><description><![CDATA[AWS require different types of security credentials depending upon how we are going to access the AWS resources i.e.
AWS Management Console - requires user name and password
Programmatic access (CLI/S]]></description><link>https://blog.gurjot.dev/aws-access-keys</link><guid isPermaLink="true">https://blog.gurjot.dev/aws-access-keys</guid><category><![CDATA[AWS]]></category><category><![CDATA[Security]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Gurjot Singh]]></dc:creator><pubDate>Mon, 06 Sep 2021 13:25:17 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1630932462653/U23giW7dd.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>AWS require different types of security credentials depending upon how we are going to access the AWS resources i.e.</p>
<p><strong>AWS Management Console</strong> - requires user name and password</p>
<p><strong>Programmatic access (CLI/SDK/API)</strong> - requires access keys</p>
<h2>What are Access Keys?</h2>
<p>Access keys are a type of AWS credential which are used to sign programmatic requests. These requests can be generated using any of the following methods:</p>
<ul>
<li><p>AWS CLI</p>
</li>
<li><p>AWS API</p>
</li>
<li><p>AWS SDK</p>
</li>
</ul>
<h2>Access Keys General Structure:</h2>
<p>The Access keys generally consist of two parts:</p>
<ul>
<li><p><strong>Access Key ID</strong></p>
</li>
<li><p><strong>Secret Access Key</strong></p>
</li>
</ul>
<p>However, there can be a third part called "<strong>Session Token</strong>". We will discuss more about this in our post.</p>
<h2>Access Keys Classification:</h2>
<p>Access keys can be classified into two types depending upon the time for which they are valid i.e.</p>
<ol>
<li><p>Long Term Access Keys</p>
</li>
<li><p>Temporary Access Keys</p>
</li>
</ol>
<h3>Long Term Access Keys 👇</h3>
<p>As the name suggests, the long term access keys are programmatic credentials which are valid forever, until they are explicitly deleted from our AWS account. This type of key is a long term customer-managed credential which is associated with an IAM user or AWS account root user.</p>
<p>A sample long term access key is as follows:</p>
<ul>
<li><p><strong>Access Key ID</strong> (for example, AKIAIOSFODNN7EXAMPLE)</p>
</li>
<li><p><strong>Secret Access Key</strong> (for example, wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY).</p>
</li>
</ul>
<p>We can assign up to two access keys per user (root user or IAM user). This allows the user to easily rotate the keys and meet their security standards.</p>
<p>Refer the AWS documentation "<a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access-keys.html">Managing access keys for IAM users</a>" to create long term access keys for your user using Console/CLI/API.</p>
<p>However, using long term credentials is not always the ideal approach, in cases where you want to give someone limited period access to your AWS resources. This brings us to the other type of access key i.e. temporary access key.</p>
<h3>Temporary Access Keys 👇</h3>
<p>As you might have already guessed by the name, these keys are valid for a short period of time. So, once these keys are expired, they can no longer be used to access any AWS resources. These keys are generated using the AWS Security Token Service (<strong>STS</strong>).</p>
<p>A sample temporary access key is as follows</p>
<ul>
<li><p><strong>Access Key ID</strong> (for example, ASIAJEXAMPLEXEG2JICEA)</p>
</li>
<li><p><strong>Secret Access Key</strong> (for example, 9drTJvcXLB89EXAMPLELB8923FB892xMFI).</p>
</li>
<li><p><strong>Session Token</strong> (for example, AQoXdzELDDY//////////wEaoAK1wvxJY12r2IrDFT2IvAzTCn3zHoZ7YNtpiQLF0MqZye/qwjzP2iEXAMPLEbw/m3hsj8VBTkPORGvr9jM5sgP+w9IZWZnU+LWhmg+a5fDi2oTGUYcdg9uexQ4mtCHIHfi4citgqZTgco40Yqr4lIlo4V2b2Dyauk0eYFNebHtYlFVgAUj+7Indz3LU0aTWk1WKIjHmmMCIoTkyYp/k7kUG7moeEYKSitwQIi6Gjn+nyzM+PtoA3685ixzv0R7i5rjQi0YE0lf1oeie3bDiNHncmzosRM6SFiPzSvp6h/32xQuZsjcypmwsPSDtTPYcs0+YN/8BRi2/IcrxSpnWEXAMPLEXSDFTAQAM6Dl9zR0tXoybnlrZIwMLlMi1Kcgo5OytwU=)</p>
</li>
</ul>
<p>The "<strong>Session Token</strong>" plays the most important role in the temporary access keys. So, when we make a call using a temporary access key, the call must include the session token. AWS uses the session token to validate the temporary security credentials and confirm if these credentials are expired or not.</p>
<p>These keys are generally used in following scenarios:</p>
<ul>
<li><p>Temporary AWS access in less secure environments</p>
</li>
<li><p>Providing external identity temporary access to AWS resources</p>
</li>
<li><p>Cross account access to AWS resources.</p>
</li>
</ul>
<p>For more details around the common scenarios for using temporary credentials, please refer the AWS documentation <a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp.html#sts-introduction">here</a>.</p>
<p>Also, refer the "<a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_request.html">Requesting temporary security credentials</a>" AWS documentation to get details around all the possible ways to generate temporary credentials in AWS.</p>
<h3>⚡️Interesting Observation⚡️</h3>
<p>Now let's assume the following scenario:</p>
<p>I am using temporary access keys to interact with my AWS resources via CLI. However, instead of configuring all the three parts of the access key, I excluded the "SessionToken" from the CLI configuration. So...</p>
<p><strong>Q. How will now AWS know if I am using temporary credentials?</strong><br /><strong>Q. Will this make my credentials long term instead of temporary?</strong></p>
<p>Give it a thought. The answer to this is in the blog's title 🤔</p>
<p>Lets discuss that now 👇</p>
<h2>Access Key ID - AKIA vs ASIA</h2>
<p>If you have not already noticed, the first four characters of the Access Key ID helps us to determine the type of access key:</p>
<ul>
<li><p>Long Term Access Key → Access KeyID begin with "AKIA".</p>
</li>
<li><p>Temporary Access Key → Access Key ID begin with "ASIA".</p>
</li>
</ul>
<p>So, this allows AWS to determines the type of access key when the requests comes in to access any AWS resource.</p>
<p>In case you are using temporary access key i.e. a key starting with "ASIA", AWS would except the session token to be the third parameter in the credentials. In case the session token is missing, you would get an error for not using valid credentials.</p>
<hr />
<p>👋 Enjoyed the article? Reach out to me anytime in the comments below or on <a href="https://twitter.com/gurjotsingh4398">Twitter</a> for any further discussion or feedback.</p>
]]></content:encoded></item><item><title><![CDATA[Generate MFA authenticated credentials for AWS CLI (and a script to automate this task)]]></title><description><![CDATA[In my previous post Securing AWS Infrastructure using MFA, we discussed how we can enforce MFA authentication on AWS Console and AWS CLI, so that users cannot access any AWS resource until they use MFA authenticated credentials.
A quick recap for AWS...]]></description><link>https://blog.gurjot.dev/generate-mfa-authenticated-credentials-for-aws-cli</link><guid isPermaLink="true">https://blog.gurjot.dev/generate-mfa-authenticated-credentials-for-aws-cli</guid><category><![CDATA[AWS]]></category><category><![CDATA[Security]]></category><category><![CDATA[command line]]></category><category><![CDATA[Cloud]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Gurjot Singh]]></dc:creator><pubDate>Mon, 30 Aug 2021 09:14:27 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1630246948237/2BhAMinrw.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In my previous post <a target="_blank" href="https://blog.gurjot.dev/securing-aws-infrastructure-using-mfa">Securing AWS Infrastructure using MFA</a>, we discussed how we can enforce MFA authentication on AWS Console and AWS CLI, so that users cannot access any AWS resource until they use MFA authenticated credentials.</p>
<p>A quick recap for AWS CLI, the following IAM policy can be attached to the IAM users, which will enforce users to use MFA to access any AWS service:</p>
<pre><code>{
    <span class="hljs-attr">"Version"</span>: <span class="hljs-string">"2012-10-17"</span>,
    <span class="hljs-attr">"Statement"</span>: [
        {
            <span class="hljs-attr">"Sid"</span>: <span class="hljs-string">"BlockMostAccessUnlessSignedInWithMFA"</span>,
            <span class="hljs-attr">"Effect"</span>: <span class="hljs-string">"Deny"</span>,
            <span class="hljs-attr">"NotAction"</span>: [
                <span class="hljs-string">"iam:CreateVirtualMFADevice"</span>,
                <span class="hljs-string">"iam:DeleteVirtualMFADevice"</span>,
                <span class="hljs-string">"iam:ListVirtualMFADevices"</span>,
                <span class="hljs-string">"iam:EnableMFADevice"</span>,
                <span class="hljs-string">"iam:ResyncMFADevice"</span>,
                <span class="hljs-string">"iam:ListAccountAliases"</span>,
                <span class="hljs-string">"iam:ListUsers"</span>,
                <span class="hljs-string">"iam:ListSSHPublicKeys"</span>,
                <span class="hljs-string">"iam:ListAccessKeys"</span>,
                <span class="hljs-string">"iam:ListServiceSpecificCredentials"</span>,
                <span class="hljs-string">"iam:ListMFADevices"</span>,
                <span class="hljs-string">"iam:GetAccountSummary"</span>,
                <span class="hljs-string">"sts:GetSessionToken"</span>
            ],
            <span class="hljs-attr">"Resource"</span>: <span class="hljs-string">"*"</span>,
            <span class="hljs-attr">"Condition"</span>: {
                <span class="hljs-attr">"BoolIfExists"</span>: {
                    <span class="hljs-attr">"aws:MultiFactorAuthPresent"</span>: <span class="hljs-string">"false"</span>
                }
            }
        }
    ]
}
</code></pre><p>In this article, we are going to discuss the steps to generate those MFA authenticated temporary credentials. These will allow the user to pass the MFA check that we applied using the above mentioned IAM policy and will grant access to our AWS resources using AWS CLI.</p>
<p>To accomplish this we need to:</p>
<ul>
<li><a class="post-section-overview" href="#configure-the-aws-cli-with-long-term-credentials">Configure the AWS CLI with long-term credentials</a></li>
<li><a class="post-section-overview" href="#generate-the-mfa-authenticated-temporary-credentials">Generate the MFA authenticated temporary credentials</a></li>
<li><a class="post-section-overview" href="#configure-an-aws-cli-profile-to-use-the-credentials">Configure an AWS CLI profile to use the MFA authenticated credentials</a></li>
<li><a class="post-section-overview" href="#bonus-create-a-script-to-automate-mfa-credentials-generation-and-setup">Bonus: Create a script to automate MFA credentials generation and setup</a></li>
</ul>
<h2 id="configure-the-aws-cli-with-long-term-credentials">Configure the AWS CLI with long-term credentials</h2>
<p>The long term credentials belongs to an IAM user and are called "Access Keys". These are used to sign programmatic requests to the AWS CLI. Access keys consist of two parts: </p>
<ul>
<li>Access Key ID (for example, AKIAIOSFODNN7EXAMPLE)</li>
<li>Secret Access Key (for example, wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY).</li>
</ul>
<p>Just a heads up, the above mentioned access key is not valid 😉</p>
<p>The access key is prompted to be saved when we create a new IAM user with programmatic access. In case you don't have an access key for your user, we can create a new access key from the user's summary page in IAM console as shown below:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1630249895120/jCbEgKI-x.png" alt="blog-0002-1.png" /></p>
<p>Once you have the access key, now we can configure that in AWS CLI using the following command:</p>
<pre><code class="lang-bash">$ aws configure
AWS Access Key ID: AKIAIOSFODNN7EXAMPLE
AWS Secret Access Key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Default region name: us-east-1
Default output format: json
</code></pre>
<h3 id="interesting-observation">⚡️Interesting observation⚡️</h3>
<p>After the above AWS CLI configuration, try running a CLI command such as to list all the S3 buckets in your AWS account and observe the output:</p>
<pre><code class="lang-bash">$ aws s3 ls

An error occurred (AccessDenied) when calling the ListBuckets operation: Access Denied
</code></pre>
<p>Getting an "AccessDenied" error is an expected behaviour as we are still using long-term credentials to access S3, which are not MFA authenticated. Hence, not passing the MFA check defined using the IAM policy.</p>
<h2 id="generate-the-mfa-authenticated-temporary-credentials">Generate the MFA authenticated temporary credentials</h2>
<p>Now we will use the above configured long term credentials to generate temporary credentials which are MFA authenticated, by running the "<a target="_blank" href="https://awscli.amazonaws.com/v2/documentation/api/latest/reference/sts/get-session-token.html">get-session-token</a>" CLI command:</p>
<pre><code class="lang-bash">$ aws sts get-session-token --serial-number <span class="hljs-string">"YourMFADeviceSerialNumber"</span> --token-code 123456

{
    <span class="hljs-string">"Credentials"</span>: {
        <span class="hljs-string">"AccessKeyId"</span>: <span class="hljs-string">"ASIAIOSFODNN7EXAMPLE"</span>,
        <span class="hljs-string">"SecretAccessKey"</span>: <span class="hljs-string">"wJalrXUtnFEMI/K7MDENG/bPxRfiCYzEXAMPLEKEY"</span>,
        <span class="hljs-string">"SessionToken"</span>: <span class="hljs-string">"AQoEXAMPLEH4aoAH0gNCAPyJxz4BlCFFxWNE1OPTgk5TthT+FvwqnKwRcOIfrRh3c/LTo6UDdyJwOOvEVPvLXCrrrUtdnniCEXAMPLE/IvU1dYUg2RVAJBanLiHb4IgRmpRV3zrkuWJOgQs8IZZaIv2BXIa2R4OlgkBN9bkUDNCJiBeb/AXlzBBko7b15fjrBs2+cTQtpZ3CYWFXG8C5zqx37wnOE49mRl/+OtkIKGO7fAE"</span>,
        <span class="hljs-string">"Expiration"</span>: <span class="hljs-string">"2020-05-19T18:06:10+00:00"</span>
    }
}
</code></pre>
<p>The serial number here is an identification number of the MFA device that is associated with the IAM user. The value for this can either be the serial number for a hardware device (such as GAHT12345678 ) or an Amazon Resource Name (ARN) for a virtual MFA device (such as arn:aws:iam::123456789012:mfa/MFA-User), which we can find on the IAM console:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1630250394945/vWLYCisSz.png" alt="blog-0002-2.png" /></p>
<h2 id="configure-an-aws-cli-profile-to-use-the-credentials">Configure an AWS CLI profile to use the credentials</h2>
<p>Next up we need to create a user profile for AWS CLI to store the temporary credentials generated in the previous section, so that they can be used to access the MFA protected AWS resources.</p>
<pre><code class="lang-bash">$ aws configure --profile mfa
AWS Access Key ID: ASIAIOSFODNN7EXAMPLE
AWS Secret Access Key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Default region name: us-east-1
Default output format: json

<span class="hljs-comment"># Do add "--profile mfa" at the end of the command</span>
$ aws configure <span class="hljs-built_in">set</span> aws_session_token AQoEXAMPLEH4aoAH0gNCAPyJxz4BlCFFxWNE1OPTgk5TthT+FvwqnKwRcOIfrRh3c/LTo6UDdyJwOOvEVPvLXCrrrUtdnniCEXAMPLE/IvU1dYUg2RVAJBanLiHb4IgRmpRV3zrkuWJOgQs8IZZaIv2BXIa2R4OlgkBN9bkUDNCJiBeb/AXlzBBko7b15fjrBs2+cTQtpZ3CYWFXG8C5zqx37wnOE49mRl/+OtkIKGO7fAE --profile mfa
</code></pre>
<h2 id="bonus-create-a-script-to-automate-mfa-credentials-generation-and-setup">Bonus: Create a script to automate MFA credentials generation and setup</h2>
<p>The following script first calls the "get-session-token" command to generate the temporary credentials and then automatically configure an AWS CLI profile named "mfa" to store these credentials.</p>
<pre><code class="lang-bash"><span class="hljs-meta">#!/bin/bash</span>
<span class="hljs-comment"># Usage</span>
<span class="hljs-comment">#</span>
<span class="hljs-comment"># ./setup-mfa-cred.sh $PROFILE $MFA_DEVICE_ARN $TOKEN</span>
<span class="hljs-comment"># ./setup-mfa-cred.sh mfa arn:aws:iam::123456789012:mfa/MFA-User 123456</span>
<span class="hljs-comment">#</span>
<span class="hljs-comment"># aws s3 ls --profile mfa</span>

PROFILE=<span class="hljs-variable">$1</span>
MFA_DEVICE_ARN=<span class="hljs-variable">$2</span>
TOKEN=<span class="hljs-variable">$3</span>

<span class="hljs-built_in">echo</span> <span class="hljs-string">"Getting MFA credentials"</span>
sts=$(aws sts get-session-token \
  --serial-number <span class="hljs-variable">$MFA_DEVICE_ARN</span> \
  --token-code <span class="hljs-variable">$TOKEN</span> \
  --query <span class="hljs-string">'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]'</span> \
  --output text)
sts=(<span class="hljs-variable">$sts</span>)
<span class="hljs-built_in">echo</span> <span class="hljs-string">"AWS_ACCESS_KEY_ID is <span class="hljs-variable">${sts[0]}</span>"</span>
aws configure <span class="hljs-built_in">set</span> aws_access_key_id <span class="hljs-variable">${sts[0]}</span> --profile <span class="hljs-variable">$PROFILE</span>
aws configure <span class="hljs-built_in">set</span> aws_secret_access_key <span class="hljs-variable">${sts[1]}</span> --profile <span class="hljs-variable">$PROFILE</span>
aws configure <span class="hljs-built_in">set</span> aws_session_token <span class="hljs-variable">${sts[2]}</span> --profile <span class="hljs-variable">$PROFILE</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"MFA Credentials stored in the AWS CLI profile: <span class="hljs-variable">$PROFILE</span>"</span>
</code></pre>
<p>The above script requires us to pass 3 arguments i.e.</p>
<ul>
<li>AWS CLI profile name (i.e. mfa)</li>
<li>MFA Device Serial Number (i.e. GAHT12345678 or arn:aws:iam::123456789012:mfa/MFA-User)</li>
<li>MFA Token (i.e. 123456)</li>
</ul>
<pre><code class="lang-bash">./setup-mfa-cred.sh mfa arn:aws:iam::123456789012:mfa/MFA-User 123456
</code></pre>
<p>Once the AWS CLI profile is created, then we can access our MFA protected AWS resources  using the CLI command, such as:</p>
<pre><code class="lang-bash">aws s3 ls --profile mfa
</code></pre>
<p><strong>Note:</strong> As the credentials generated above are temporary, so they will expire after 12 hours, which is the default value for session duration. So, we can re-run the above script with a new MFA token to configure new credentials automatically within the same AWS CLI profile.</p>
<hr />
<p>👋 Enjoyed the article? Reach out to me anytime in the comments below or on <a target="_blank" href="https://twitter.com/gurjotsingh4398">Twitter</a> for any further discussion or feedback.</p>
]]></content:encoded></item><item><title><![CDATA[Securing AWS Infrastructure using MFA]]></title><description><![CDATA[As security is considered  job Zero, the usage of Multi-factor authentication (MFA) within your applications has become more common nowadays. MFA is simply a security best practice that adds an extra layer of protection on top of your user name and p...]]></description><link>https://blog.gurjot.dev/securing-aws-infrastructure-using-mfa</link><guid isPermaLink="true">https://blog.gurjot.dev/securing-aws-infrastructure-using-mfa</guid><category><![CDATA[AWS]]></category><category><![CDATA[Security]]></category><category><![CDATA[console]]></category><category><![CDATA[command line]]></category><category><![CDATA[Tutorial]]></category><dc:creator><![CDATA[Gurjot Singh]]></dc:creator><pubDate>Thu, 26 Aug 2021 15:56:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1629989304950/FBL8AUe7o.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As security is considered  <strong>job Zero</strong>, the usage of Multi-factor authentication (MFA) within your applications has become more common nowadays. MFA is simply a security best practice that adds an extra layer of protection on top of your user name and password.</p>
<p>Now coming to AWS, resources are usually accessed using the AWS Console or they are accessed programmatically (which includes CLI/SDK/API). So, in this guide we'll learn about how can we secure our AWS infrastructure using MFA when used via AWS Console or CLI (where a similar approach can be applied for API/SDK).</p>
<h3 id="mfa-for-aws-console">MFA for AWS Console</h3>
<p>The access to AWS Console is generally provided by creating an IAM user. The IAM user when created without any MFA configuration can access the AWS console just using a username and password.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629547321384/ltD7QrgA_.png" alt="1 copy.png" /></p>
<p>Configuring MFA for an IAM user enforce the user to provide a MFA code during signing-in into the AWS console. </p>
<p>As an example, let's create an IAM user in AWS and configure a MFA device for that user:</p>
<p>1) Login to the AWS Management Console and visit the <a target="_blank" href="https://console.aws.amazon.com/iam/">IAM Console</a></p>
<p>2) Choose <strong>Users</strong> in the navigation pane and click "Add users" to create a new IAM user.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629384692885/v8-U5TKNo.png" alt="2.png" /></p>
<p>3) Enter the user details and click "Next: Permissions".</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629384814646/HWfbomPV9.png" alt="3.png" /></p>
<p>4) Select the permissions that you want to assign to your IAM user. For example, I have attached the "ReadOnlyAccess" AWS Managed policy which provides read-only access to all the AWS services. Now, choose "Next: Tags".</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629384875229/ivW8p2S_5.png" alt="4.png" /></p>
<p>5) (Optional) Add metadata to the user by attaching tags as key-value pairs. Then, click "Next: Review". Now, review the user details and click "Create User".</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629384917572/90bSgwnpG.png" alt="5.png" /></p>
<p>Once the user is created, go back to the <strong>Users</strong> section and select the "MFA-User" to view the user's summary. Now we're going to configure the MFA device for this user.</p>
<p>a) Click "Manage" to assign a MFA device to this user.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629385395812/gCh2Fzeiv.png" alt="6 copy.png" /></p>
<p>b) In the Manage MFA Device wizard, choose <strong>Virtual MFA device</strong>, and then choose Continue.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629385465733/NX-eNRCXR.png" alt="7.png" /></p>
<p>The Virtual MFA device option allows to configure a MFA device using apps (such as, Google Authenticator or Authy) in our mobile devices.</p>
<p>In case you want to configure a different type of MFA device, you can refer to the AWS documentation <a target="_blank" href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_mfa_enable.html">here</a></p>
<p>c) Open the virtual MFA app on your mobile. For a list of apps that we can use for hosting virtual MFA devices, click <a target="_blank" href="https://aws.amazon.com/iam/features/mfa/#Virtual_MFA_Applications">here</a>. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1629385485746/7AYj7yHLb.png" alt="8.png" /></p>
<p>Now scan the QR code as shown above. MFA app will now start generating the MFA codes. If the QR code is not supported, you can type the secret key in the MFA app as an alternative.</p>
<p>d) Input the two consecutive MFA codes generated by the app and click "Assign MFA".</p>
<p>Finally, the MFA device is now configured for the IAM user. The user will now be prompted to input a MFA code on each login.</p>
<h3 id="interesting-observation">⚡️Interesting Observation⚡️</h3>
<p>Try using the AWS CLI  to access any AWS service using the credentials of the "MFA-User" and you will observe that the resources can be accessed without MFA. Weird, huh !!</p>
<p>Let's understand that, a key named "MultiFactorAuthPresent" with a boolean value is included when a request is made to an AWS service and tells if MFA is used or not. This key is included in the request context only when the principal uses temporary credentials to make the request. The key is <strong>not</strong> present in AWS CLI, AWS API, or AWS SDK requests that are made using long-term credentials (i.e. AccessKey &amp; SecretAccessKey). So, this is the reason we are able to access the AWS services without MFA in AWS CLI.</p>
<p><strong>Note:</strong> IAM users in the AWS Console unknowingly use temporary credentials i.e. after signing in using the username, password  (which are long-term credentials) and MFA code, the console generates  temporary credentials on behalf of the user in the background with the key "MultiFactorAuthPresent" set to "true". These temporary credentials are then used to make all the requests to AWS while you are using the console. </p>
<p>We can verify the above information using a simple fact that we are logged out of the console automatically after 12 hours. This is because it was using temporary credentials which got expired.</p>
<p>The question now comes up is that if the key "MultiFactorAuthPresent" is not present in the requests made using AWS CLI (which is using long term credentials), then how can we enforce MFA for CLI. Any thoughts on that? Let's discuss that next...</p>
<h3 id="mfa-for-aws-cli-or-sdk-or-api">MFA for AWS CLI (or SDK or API)</h3>
<p>As the "MultiFactorAuthPresent" key is not present, AWS cannot perform any check for this key. Hence, the control is now shifted to our hands. But how can we control access to our AWS resources. Any guesses???</p>
<p>Yes, that's right our own IAM policies. These can be used to enforce MFA for the requests coming from AWS CLI. Instead of checking the value of the key "MultiFactorAuthPresent", we will check if this key is actually present in the request or not. If not, that means the user is using long term credentials which are not MFA authenticated. Based on that evaluation we can then allow or deny access to the AWS services.</p>
<p>The following example IAM policy can be attached to your IAM users, which will enforce users to use MFA to access any AWS services:</p>
<pre><code>{
    <span class="hljs-attr">"Version"</span>: <span class="hljs-string">"2012-10-17"</span>,
    <span class="hljs-attr">"Statement"</span>: [
        {
            <span class="hljs-attr">"Sid"</span>: <span class="hljs-string">"BlockMostAccessUnlessSignedInWithMFA"</span>,
            <span class="hljs-attr">"Effect"</span>: <span class="hljs-string">"Deny"</span>,
            <span class="hljs-attr">"NotAction"</span>: [
                <span class="hljs-string">"iam:CreateVirtualMFADevice"</span>,
                <span class="hljs-string">"iam:DeleteVirtualMFADevice"</span>,
                <span class="hljs-string">"iam:ListVirtualMFADevices"</span>,
                <span class="hljs-string">"iam:EnableMFADevice"</span>,
                <span class="hljs-string">"iam:ResyncMFADevice"</span>,
                <span class="hljs-string">"iam:ListAccountAliases"</span>,
                <span class="hljs-string">"iam:ListUsers"</span>,
                <span class="hljs-string">"iam:ListSSHPublicKeys"</span>,
                <span class="hljs-string">"iam:ListAccessKeys"</span>,
                <span class="hljs-string">"iam:ListServiceSpecificCredentials"</span>,
                <span class="hljs-string">"iam:ListMFADevices"</span>,
                <span class="hljs-string">"iam:GetAccountSummary"</span>,
                <span class="hljs-string">"sts:GetSessionToken"</span>
            ],
            <span class="hljs-attr">"Resource"</span>: <span class="hljs-string">"*"</span>,
            <span class="hljs-attr">"Condition"</span>: {
                <span class="hljs-attr">"BoolIfExists"</span>: {
                    <span class="hljs-attr">"aws:MultiFactorAuthPresent"</span>: <span class="hljs-string">"false"</span>
                }
            }
        }
    ]
}
</code></pre><p>The "BoolIfExists" condition operator in the above policy plays the main role here. It checks if the "<a target="_blank" href="https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-multifactorauthpresent">MultiFactorAuthPresent</a>" key is present in the request. </p>
<ul>
<li>If the "MultiFactorAuthPresent" key is not present, <em>IfExists</em> evaluates the condition element as true. So, based on the policy every action except the one's mentioned in the "NotAction" element is denied. The allowed actions above provide the user with minimum permission to configure a MFA device for itself and to get temporary credentials which are MFA authenticated.</li>
<li>If the "MultiFactorAuthPresent" key is present, the condition is further evaluated to check if it's value is true or false. In case the value is "true", the permissions are granted to access the AWS resources based on other attached IAM policies. If "false", the user then only has minimum permissions to configure a MFA device for itself and to get temporary credentials which are MFA authenticated.</li>
</ul>
<p>Hence, applying the above policy to our "MFA-User" has now added the additional layer of security for programmatic access too i.e. while using CLI/SDK/API you must now use MFA authenticated temporary credentials to access any AWS resource.</p>
<h3 id="whats-next">What's next 🤔</h3>
<p>The only detail now left is that how can we make our requests coming from AWS CLI/SDK/API  MFA authenticated. We will discuss that in the next post i.e. how can we use our long term credentials to generate MFA authenticated temporary credentials to access resources using CLI. We will also take a look at a script to automate this task, as getting MFA credentials manually after they get expire can be a bit tiring.</p>
<hr />
<p>👋 Enjoyed the article? Reach out to me anytime in the comments below or on <a target="_blank" href="https://twitter.com/gurjotsingh4398">Twitter</a> for any further discussion or feedback.</p>
]]></content:encoded></item></channel></rss>