avatarTeri Radichel

Summarize

Adding Conditions to AWS IAM, Resource, and Trust Policies

ACM.17 Details of policy evaluation and adding MFA to our batch job policies

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

⚙️ Part of my series on Automating Cybersecurity Metrics. The Code.

🔒 Related Stories: AWS Security | Application Security | IAM

💻 Free Content on Jobs in Cybersecurity | ✉️ Sign up for the Email List

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

FYI, I’m not getting paid for anyone who reads or claps on this particular story by Medium for some unknown reason. If you like this story please read and clap on the story in this blog to show your support.

~~

In the last post we created an IAM Role for a batch job using CloudFormation.

In this post we’re going to add the MFA condition to our IAM policies created in the last two posts in this series. I already explained the reasoning behind our architectural and policy choices in the prior posts in this series so please read those first if you haven’t already. There are two places where we should be able to add an effective MFA condition — in our user policy and the trust policy associated with our batch job role.

AWS IAM Policy Conditions

We can add a Condition element to our AWS IAM policies to only allow actions when certain conditions are met. The following documentation has some details about Condition operators.

Essentially when you write your policy with a condition operator, you are checking that a particular key in the request to the AWS API has a particular value.

Only perform the requested action if key = value

What keys and values can we check? We’ll need to consult the AWS documentation for which keys exist in which type of requests and what their values should be.

Global Condition Keys

The first type of keys we can use in a condition statement are those present globally in every request. That means if you add condition logic for these keys in an IAM policy of any type you can reasonably be sure they will exist and can be evaluated — but that doesn’t mean they will be set the way you might expect as was covered in prior posts where I wrote about how MFA applies to IAM roles.

Notice that one of these keys is aws:MultiFactorAuthPresent. We could also limit the age of the MFA session. We’ll start with the simply checking MFA is present to start. We may add other conditions later if needed.

IAM and STS Condition Keys

In addition to global keys, you can leverage other types of keys specific to different services in AWS requests. For example, there are a number of keys related to IAM and STS:

What you’ll need to understand here is which condition keys are applicable to the authentication method those used in your cloud environment. If you are trying to use IAM conditions and your users are logging in via SAML, those conditions may not apply. Consider that AWS SSO (now AWS Identity Center) leverages SAML.

Service Condition Keys

Each AWS Service may have additional keys that you can use in AWS IAM conditions to create fine-grained policies for the specific services you are using in your AWS account.

Condition Keys in Resource Policies

You can also use condition keys in resource policies such as S3 bucket policies:

As always, don’t assume things are working as you expect — test each IAM Policy you implement.

And this is the point where I remind my readers that there’s no easy button for multi-cloud as I discuss at IANS events. You need to understand the fine-grained details of each cloud provider. I'll be presenting on multi-cloud security at an IANS Research event in LA in October if all goes according to plan and you want to learn more:
https://www.iansresearch.com/what-we-do/events/forums/details/2022/10/4/2022-forums/2022-los-angeles

Writing our Condition Logic

The global condition context keys documentation recommends that you write your condition logic as follows and warns against other approaches that may fail.

I have converted this to yaml since that’s what we’re using for our CloudFormation templates.

Condition:
   "BoolIfExists":
      "aws:MultiFactorAuthPresent": "false"

Let’s look at the condition line with the key and value:

"aws:MultiFactorAuthPresent": "false"

Note that this condition is checking if MFA is *not* present, so we will need to associate this with a deny statement.

If aws:MultiFactorAuthPresent equals false then the condition evaluates to TRUE, so apply the associated DENY statement to the request.

Deny Statement Logic

If we wanted to add a deny statement to our policy it would look like this:

- Effect: Deny
  Action: '*'
  Resource: '*'
  Condition:
    "BoolIfExists":
       "aws:MultiFactorAuthPresent":"false"

This leads to the need to understanding precedence and how multiple statements work together in an IAM Policy which you can read about here in this documentation on IAM Policy Evaluation logic:

What if we have one statement that allows an action but another statement that denies actions in an IAM Policy? We can take a look at this policy decision flow document from the above documentation:

In the very first column, the decision logic checks for an explicit deny. Stop. Game over. Go to Jail. Do not not pass Go. Do not collect $200. (For those who don’t understand that reference it’s from the game of Monopoly which hopefully at least some of my readers played as a kid like I did.)

BoolIfExists

Before you read this section… I am only thinking through BoolIfExists here. I haven’t actually tested this because I decided not to use it. It may work perfectly fine as documented I just found the wording of the documentation and/or the name of the variable confusing compared to what I’m used to seeing an “if exists” construct do in a programming language.

What does the BoolIfExists operator in the statement above do exactly? To answer that question you’ll need to understand how BoolIfExists works.

"If the key is not present, evaluate the condition element as TRUE."

So for the purposes of our policy and if I understand that statement correctly, it translates to:

"If [MFAAuthPresent = false] is not present, evaluate the condition element as TRUE." Deny the request.

Because the “thing” passed into boolifexists is not MFAAuthPresent, it is whatever “MFAAuthPresent =false” evaluates to in a normal programming language.

So what if the key MFAAuthPresent key is not in the request at all. Does that mean that MFAAuthPresent = false is not present? I guess it must. So according to the documentation the value doesn’t exist and the result of the if exists check translates to true. Deny the request.

But here’s the thing that seems odd to me. The name of this condition logic operator is BoolIfExists and so I read the translation of the name of the operator in conjunction with the statement in the documentation like this:

If the boolean value doesn’t exist thenif the boolean value existsreturns true.

That doesn’t really make sense does it? Perhaps the logic applied in AWS behind the scenes where this statement gets evaluated is different than other programming languages or the way I’m reading this operator name.

Based on many years of programming, an “if exists” construct in most languages usually translates to “if the referenced item exists, then return true”.

So I would read BoolIfExists if it were a standard programming language construct as follows:

If the item exists and it is a boolean, return true, otherwise return false.

To me, if our referenced item is [MFAAuthPresent=false] that translates to:

If the result of [MFAAuthPresent = false] exists and it is a boolean, then return the result of [MFAAuthPresent = false]. In the case MFAAuthPresent = true it doesn't match the condition and the result is false, so the condition fails. The deny statement will not apply. If MFAAuthPresent = false then it matches the condition requirement and the result is true. The condition succeeds and the DENY statement will apply.
Otherwise the value of [MFAAuthPresent=false] is not a boolean or it doesn't exist so return false. The Deny statement will not apply.

With the above interpretation (which does not match what the AWS documentation states so should not be correct) the “otherwise” portion of the logic indicates that if someone could remove the MFAAuthPresent key in a request to the API or pass in something other than true or false, then the deny statement wouldn't apply. The request would succeed. Someone could bypass our MFA requirement with one of those options.

But the documentation says it works otherwise, and I am not using this form of the logic so I'm not going to test it further right now. If you are using the above double negative logic, you might want to test it out with no key or a key that evaluates to something other than true or false confirm it works the way the documentation states.

For my purposes, it seems that it would be much simpler to add the following condition to the allow statement in our policy.

Condition:
    "Bool": 
       "aws:MultiFactorAuthPresent": "true"

Note that I have removed the “if exists” altogether. The key must exist and it must be true. I presume in this case if the key does not exist, the logic will evaluate such that the condition fails. The documentation seems to support this but it’s always good to test and validate your IAM policies work the way you expect.

Let’s revisit why the documentation is not recommending this approach over the others and see if any caveats apply to our use case.

This combination of the Allow, Bool, and true allows only MFA-authenticated requests. This applies only to temporary credentials that support using MFA. This statement does not allow access to requests that were made using long-term access keys, or to requests made using temporary credentials without MFA.

I think the statement above regarding “long term access keys” is a bit misleading or at least confusing. You can use access keys to make CLI requests with MFA and the above policy condition will work because I have used it before as I wrote about here.

I want to get my code done so I’ll stick to the simpler approach if it works as expected. I am not concerned with other actions that won’t work with MFA because currently the only thing in my policy is STS:AssumeRole. If I need to add anything that doesn’t work with MFA, I could add a separate statement for that, but so far I don’t expect that I will need to do so.

Add the MFA condition the user policy

The first place we’ll add an MFA condition is in our user policy. Add the condition logic to our statement that allows the sts:AssumeRole action.

batch_job_admins/cfn/policy_batch_job_admins.yaml
https://github.com/tradichel/SecurityMetricsAutomation/blob/main/iam/batch_job_admins/cfn/policy_batch_job_admins.yaml

After making that change navigate to the batch_job_admins directory and run the deploy script to redeploy the policy we deployed in the last blog post in this series.

Navigate to the folder with the deploy script for the batch admins

https://github.com/tradichel/SecurityMetricsAutomation/blob/main/iam/batch_job_admins/deploy.sh

Run the deploy script to redeploy the policy with the new MFA condition.

./deploy.sh

Add the MFA condition to the batch job role trust policy

Next add the MFA condition to the batch job trust policy or AssumeRolePolicyDocument as it is called in CloudFormation.

batch_job_role/cfn/role_batch_job.yaml
https://github.com/tradichel/SecurityMetricsAutomation/blob/main/iam/batch_job_role/cfn/role_batch_job.yaml

Navigate to the folder with the deploy script for the batch job role.

Run the following command to redeploy the role we created in our last blog post with this new condition.

./deploy.sh POC

Now, hopefully, we have created the scenario where only our batch job administrator can assume the batch job role and only if authenticated with MFA. We’ll test this all out in future posts.

A few related error messages I’ve had to troubleshoot trying to use conditions:

Follow for updates.

Teri Radichel | © 2nd Sight Lab 2022

About Teri Radichel:
~~~~~~~~~~~~~~~~~~~~
⭐️ Author: Cybersecurity Books
⭐️ Presentations: Presentations by Teri Radichel
⭐️ Recognition: SANS Award, AWS Security Hero, IANS Faculty
⭐️ Certifications: SANS ~ GSE 240
⭐️ Education: BA Business, Master of Software Engineering, Master of Infosec
⭐️ Company: Penetration Tests, Assessments, Phone Consulting ~ 2nd Sight Lab
Need Help With Cybersecurity, Cloud, or Application Security?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
🔒 Request a penetration test or security assessment
🔒 Schedule a consulting call
🔒 Cybersecurity Speaker for Presentation
Follow for more stories like this:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
❤️ Sign Up my Medium Email List
❤️ Twitter: @teriradichel
❤️ LinkedIn: https://www.linkedin.com/in/teriradichel
❤️ Mastodon: @teriradichel@infosec.exchange
❤️ Facebook: 2nd Sight Lab
❤️ YouTube: @2ndsightlab
Iam Policy
Conditions
MFA
Boolifexists
Security Automation
Recommended from ReadMedium