avatarTeri Radichel

Summary

The content outlines the process of troubleshooting and resolving a malformed AWS S3 bucket policy for an organization CloudTrail bucket, detailing the step-by-step approach to identify and fix errors in the policy document.

Abstract

The author, Teri Radichel, documents their journey in troubleshooting a malformed AWS S3 bucket policy that was causing errors during deployment. The process begins with the author receiving an error message stating "Malformed Policy Document" after attempting to deploy a policy copied and adapted from AWS documentation. The lack of specific information in the error message leads the author to adopt a methodical approach, breaking down the policy into individual statements and hardcoding values to isolate the issue. Through a series of iterative tests, the author identifies and corrects several syntax errors related to the use of ImportValue and Sub functions within the CloudFormation template. The author also addresses common pitfalls, such as incorrect formatting and the use of mappings where lists are expected in YAML. The successful deployment of the policy is confirmed in the S3 bucket permissions, and the article concludes with the author planning to examine the S3 Access Log bucket policy created by AWS Control Tower.

Opinions

  • The author expresses frustration with the vague "Malformed Policy Document" error message and suggests that more detailed feedback would be helpful for developers.
  • There is an appreciation for the importance of methodical troubleshooting, particularly when dealing with complex AWS CloudFormation templates and policies.
  • The author emphasizes the value of using hardcoded values to test individual components of a policy before integrating dynamic references.
  • The author points out the need for careful attention to the syntax and formatting of YAML, especially when using intrinsic functions like Sub and ImportValue.
  • There is a note of satisfaction or relief when the policy is successfully deployed after several iterations of debugging and refinement.
  • The author suggests that AWS Control Tower may not always configure policies as expected, hinting at potential shortcomings in automated setup processes.
  • The author encourages readers to follow their work for updates, indicating a commitment to sharing knowledge and best practices within the cybersecurity community.

Troubleshooting S3 bucket policies

ACM.199 A working Organization CloudTrail Bucket Policy

Part of my series on Automating Cybersecurity Metrics and stories on AWS S3 Buckets. The Code.

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

In the last post I pieced together a bucket policy for an organization CloudTrail bucket policy. Then I got a malformed policy document error.

Now I need to troubleshoot the policy. After a few failed attempts, I have to do it the old-fashioned way (and a more sensible way if you are new to S3 bucket policies).

I’m going to piece together my bucket policy one statement at a time. I’m going to hard-code the values to something that works. Then I’m going to turn each value into a parameter one at a time.

S3 policy deploy function

First, here’s my function that I create to deploy the template. As always this function uses the generic code I wrote to deploy a CloudFormation stack.

I look up the organization ID to pass into the CloudFormation template. The trail is optional, if passed in. Right now we don’t have a trail, so that parameter does not get passed to the template. The rest is standard, per how I’ve been deploying things up to now.

Then I add a line to call to the script at the end of the deployment function.

Malformed Policy Document

“Malformed Policy Document” could be anything. The error returns no number, no information, nothing. I wrote about that in the last post and here:

I really, really wish the CloudFormation team or whomever passes them this message could help a dev out and give me a hint.

The other problem is that this particular problem I caused, whatever it is, takes a very long time to fail. So I have to wait forever for the failure to try again. It’s a waste of time to randomly try different things and sit there waiting for a failure.

As a reminder, I pretty much copied this policy from the AWS Documentation and the Control Tower bucket policy. Then I converted it from JSON to YAML using an online tool and swapped values for parameters. I was crossing my fingers that copying the code would keep my policy free of typos and errors but alas, no.

Pinpointing the error in the S3 bucket policy

Here’s the current policy.

I copy and paste that policy to a backup file.

cp CloudTrailPolicy.yaml CloudtrailPolicy.yaml.bak

Next I delete everything except the first statement in the first file.

vi CloudTrailPolicy.yaml

[delete, delete, delete]

!wq

I end up with this:

What I also do is remove the two sub statements and replace them with the correct hard coded values. I can look up the CloudTrail bucket ARN and replace these two lines:

Note that the first like is simply the bucket ARN.

The second line is the bucket ARN with /* at the end.

Then I can try to deploy just that simple policy.

And, it works.

So now I’m going to try to add back in my sub statement. I had already tried it a few different ways. Let’s revisit the ImportValue documentation and make sure I have formulated that correctly.

Now, I had tried the Sub first, and then the ImportValue first. Here’s an important note on ImportValue with sub.

In the case above, the Sub is used to formulate the value passed to ImportValue. That’s not what we are doing here. I’m trying to use the value returned from ImportValue in a Sub.

But actually, don’t need a Sub at all for the first line. Let’s replace that with a simple ImportValue and see if it works.

I’m going to copy and paste my export name to make sure I don’t have any typos in that.

I replace the first resource with this:

Run the deployment again. Success.

Now let’s try the second value. The ImportValue documentation didn’t really help us because it only covers the case of using a Sub to create an ImportValue name.

Let’s look at the Sub documentation. As I’m writing this I think I know what I need to do before even looking at it.

There are a couple of ways to use Sub. We want this one:

The String is the value you want to end up with, that has tokens that need to be replaced with values. Following that is a list of values with which to replace the token. Here’s the example in the documentation.

We want this:

I was tryin to use a shorthand version of Sub which doesn’t work with ImportValue apparently.

If you get an error “Mapping Values Not Allowed Here” make sure you have the !Sub on one line followed by the dashes indented on the next two lines. the first line contains the string with the tokens to replace. The lines after define the values for each token.

Cool let’s add the next statement. For the next statement I’m going to leave the condition off initially as I do not know if that is part of the problem. I’m trying to set the condition to * since I don’t have a CloudTrail yet.

This statement is taking a very long time to deploy, unlike the last. And yes, I get a malformed policy document. In the statement above I retyped some of the lines because CloudShell copy and paste from a Mac is pretty unusable at the moment (hopefully fixed soon). I have no space after the dash before cloudtrail.amazonaws.com. I fixed that and it works.

Now let’s try to add the policy condition. I wrote about Conditions in policies here:

Not to be confused with CloudFormation conditions which provide an if this or that construct to optionally deploy resources:

Here’s our policy condition. I can’t use that Ref because the ARN is an output of another CloudFormation staack so I need to use ImportValue.

This is one thing I’m not sure will work. I’m setting the default for this parameter to an asterisk (*).

Yay it works. One more statement to go. In the last statement I was also using an invalid sub format. I changed it to match the first statement and the template successfully deployed. Here’s what I have for at the moment:

However, there’s one more thing I need to fix. The path where the files are written is incorrect. Refer to the bucket policy for CloudFormation documentation.

This is where the files will be written for an organization:

Here’s where we need our organization id. I initially wrote the code like this:

And got this error:

One or more Fn::Sub intrinsic functions don’t specify expected arguments. Specify a string as first argument, and an optional second argument to specify a mapping of values to replace in the string.

This is kind of nuts. Everythig seems to be a list of things in YAML but in this case we need a mapping where the values to replace the tokens in the sub start with only one dash. Or in other words, remove the dahs before OrgId above.

And it works.

Final policy template:

You can head over to your S3 bucket, click on Permissions and scroll down to see that the policy is successfully deployed.

Next I want to take a look at the S3 Access Log bucket policy created by Control Tower. Supposedly that bucket was supposed to automatically get a policy assigned to it per the AWS console, but no policy existed on that bucket. I suspect we’ll need to go ahead and add one.

Follow for updates.

Teri Radichel | © 2nd Sight Lab 2023

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
S3
Bucket
Policy
AWS
Cloud Security
Recommended from ReadMedium
avatarMunidimple Muchalli
AWS GuardDuty

AWS Guard Duty

4 min read