avatarTeri Radichel

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

6528

Abstract

an>, <span class="hljs-string">"s3:PutObjectRetention"</span>, <span class="hljs-string">"s3:PutBucketLogging"</span>, <span class="hljs-string">"s3:PutBucketObjectLockConfiguration"</span>, <span class="hljs-string">"s3:ReplicateDelete"</span> ], <span class="hljs-string">"Resource"</span>: [ <span class="hljs-string">"arn:aws:s3:::my.bucket/"</span>, <span class="hljs-string">"arn:aws:s3:::my.bucket"</span> ] }</pre></div><p id="8326">Note that I added the two variations of resources for the bucket or any object in the bucket. That’s because it’s annoying to try to remember which actions apply to a bucket or an object and write multiple hard-to-read, convoluted statements. Is that causing my problem? Because this should allow all read access to the bucket and the other policy should allow all write access.</p><p id="1a34">But just for sanity purposes I’ll just allow all actions on this bucket and see what happens. BTW that’s not he real bucket name.</p><p id="7814">Alright I give.</p><div id="8eab"><pre><span class="hljs-built_in">S3</span>.</pre></div><p id="de22">It still doesn’t work. I have s3* to * resources.</p><p id="0610"><b>Conditions and MFA</b></p><p id="1e1f">As with my last post I have MFA required on the KMS portion of the policy and MFA does not show up for assume role in CloudTrail so let’s remove that.</p><div id="361a" class="link-block"> <a href="https://readmedium.com/fatal-error-an-error-occurred-403-when-calling-the-headobject-operation-forbidden-2a532ecabac4"> <div> <div> <h2>fatal error: An error occurred (403) when calling the HeadObject operation: Forbidden</h2> <div><h3>Error trying to copy a file from an S3 bucket: Possible MFA bug.</h3></div> <div><p>medium.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/1*4oxP4LXk8l8c3mpRvO7ejg.png)"></div> </div> </div> </a> </div><p id="39d6">I’ve confirmed you can’t use those conditions with assumed roles.</p><div id="6236" class="link-block"> <a href="https://readmedium.com/mfaauthenticated-with-aws-assume-role-6cbe7bdee274"> <div> <div> <h2>mfaAuthenticated with AWS Assume Role</h2> <div><h3>Needs a change to enforce MFA on actions taken by IAM roles</h3></div> <div><p>medium.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/1*4oxP4LXk8l8c3mpRvO7ejg.png)"></div> </div> </div> </a> </div><p id="ce9a"><b>Encryption and KMS Keys</b></p><p id="ebd3">The only other thing I can think of, is that the problem has to do with the KMS key assigned to the bucket. That’s not what the error message says, however. You would expect — or at least hope — that the error message would be more specific that this if it were a KMS key issue. I believe I granted access to the key but let’s just remove encryption.</p><div id="2dbb"><pre><span class="hljs-keyword">And</span> Finally. <span class="hljs-keyword">It</span> works.</pre></div><p id="b767">Now, this is not where I’m going to stop. If you’re a developer don’t just stop when you get things working. Figure out why they are not working and fix it — and if it is a bug or feature request shoot that over to AWS one way or another. You can tweet it out on Twitter with the hash tag #AWSWishList and someone will probably get your request over to the appropriate AWS team.</p><p id="ca6e">In this case I know that my problem is related to one of the KMS error messages I wrote about before in this blog.</p><ol><li>Check the KMS Key policy and make sure my role is allowed to use the key.</li><li>Check my IAM Permissions and make sure the IAM user is allowed to use KMS for that key.</li></ol><p id="ba62">Oops. I forgot to add users to my KMS Key policy. I could have sworn I did that, but like I said I’ve been doing this far too long. That’s why I’m going to automate…everything. I’m just testing out the plan at the moment. For now, I’ll add the role to the users list on the KMS key and add it back to the bucket and I should be good to go.</p><p id="20e3">Oh…hang on…I have allowed permission by way of another account at the bottom of the key policy screen. Though I would prefer to add a specific role I only have my report builder in that account so I guess it’s OK.</p><p id="9211">Let’s check the IAM policy…</p><p id="569c">Here’s where I noticed the visual editor just stuck s3.* in the middle of all the other actions when I allowed it for my testing above:</p><figure id="140b"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*kp9NA_YMJF30wepEF3pmQA.png"><figcaption></figcaption></figure><p id="be6d">And people wonder why I don’t generally like things that write code for you. I use them as a starting point, but never in production. Let’s clean that up because I really only need PutObject for the local bucket and read access to the remote buckets.</p><p id="415a">When I navigate to AWS Access Advisor in IAM for this role, even after a successful PutObject operation I only see ListAllMyBuckets as the action.</p><figure id="d4af"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*ZIPFKZDw-ukqTek0TOhFGw.png"><figcaption></figcaption></figure><p id="6535">I turned on server logging on the s3 bucket in order to see other bucket actions that may be failing. It seems like there is some kind of delay between adding the bucket policy and when it actually works because after restricting my role back down, the policy was failing. I looked in CloudTrail logs and turned on server access logging so I can see what’s failing and now it works without any additional changes.</p><p id="a04d">Here’s the policy I ended up with that allows me to access the remote bucket read-only and put-object on the local bucket (with no encryption currently.)</p><div id="1257"><pre>{ <span class="hljs-string">"Version"</span>: <span class="hljs-string">"2012-10-17"</span>, <span class="hljs-string">"Statement"</span>: [ { <span class="hljs-string">"Sid"</span>: <span class="hljs-string">"VisualEditor0"</

Options

span>, <span class="hljs-string">"Effect"</span>: <span class="hljs-string">"Allow"</span>, <span class="hljs-string">"Action"</span>: [ <span class="hljs-string">"s3:GetObject"</span>, <span class="hljs-string">"s3:ListAllMyBuckets"</span>, <span class="hljs-string">"s3:ListBucket"</span> ], <span class="hljs-string">"Resource"</span>: <span class="hljs-string">""</span> }, { <span class="hljs-string">"Sid"</span>: <span class="hljs-string">"VisualEditor1"</span>, <span class="hljs-string">"Effect"</span>: <span class="hljs-string">"Allow"</span>, <span class="hljs-string">"Action"</span>: [ <span class="hljs-string">"s3:PutObject"</span>, <span class="hljs-string">"s3:ListBucket"</span> ], <span class="hljs-string">"Resource"</span>: [ <span class="hljs-string">"arn:aws:s3:::my.bucket/"</span>, <span class="hljs-string">"arn:aws:s3:::my.bucket"</span> ] } ] }</pre></div><p id="ac1c">I wish I could further restrict access to remote buckets with a condition on the OU but that doesn’t seem to work. But this role will only have access to the bucket policies that explicitly allow cross-account access to this account and any local buckets. I’m tryin to create a generic tool for certain projects in a specific OU and I don’t want this tool reading buckets in any other account. I also only want it to be able to write to one local bucket. I think that part is OK.</p><div id="bdee"><pre>Thoughts <span class="hljs-keyword">on</span> <span class="hljs-keyword">my</span> architecture...</pre></div><div id="ddc3"><pre>I can <span class="hljs-built_in">get</span> around this issue <span class="hljs-keyword">of</span> <span class="hljs-keyword">not</span> being able <span class="hljs-built_in">to</span> lock down <span class="hljs-keyword">with</span> OUs <span class="hljs-keyword">and</span> MFA <span class="hljs-keyword">by</span> granting copying <span class="hljs-keyword">the</span> <span class="hljs-built_in">files</span> this <span class="hljs-built_in">process</span> needs <span class="hljs-built_in">to</span> <span class="hljs-built_in">read</span> <span class="hljs-built_in">to</span> <span class="hljs-keyword">a</span> specific bucket <span class="hljs-built_in">from</span> <span class="hljs-keyword">the</span> external accounts instead <span class="hljs-keyword">of</span> having this <span class="hljs-built_in">process</span> reach out <span class="hljs-built_in">to</span> buckets <span class="hljs-keyword">in</span> other accounts. But <span class="hljs-keyword">then</span> I have <span class="hljs-keyword">the</span> reverse problem. Every account has <span class="hljs-built_in">write</span> access <span class="hljs-built_in">to</span> <span class="hljs-keyword">a</span> single account <span class="hljs-keyword">and</span> that<span class="hljs-string">'s more risky than read access the other way around.</span></pre></div><div id="72cc"><pre>I could <span class="hljs-keyword">create</span> a single bucket per project <span class="hljs-keyword">in</span> this account <span class="hljs-keyword">and</span> <span class="hljs-keyword">limit</span> <span class="hljs-keyword">each</span> remote account <span class="hljs-keyword">to</span> its own bucket <span class="hljs-keyword">in</span> the central account, but <span class="hljs-keyword">then</span> I risk a misconfiguration <span class="hljs-keyword">where</span> one <span class="hljs-keyword">of</span> those accounts can see everyone <span class="hljs-keyword">else</span>’s data. I think <span class="hljs-keyword">having</span> <span class="hljs-keyword">to</span> manage the permissions <span class="hljs-keyword">for</span> one single resource <span class="hljs-keyword">to</span> have <span class="hljs-keyword">read</span>-<span class="hljs-keyword">only</span> <span class="hljs-keyword">access</span> <span class="hljs-keyword">to</span> <span class="hljs-keyword">all</span> the other data <span class="hljs-keyword">is</span> safer. But at <span class="hljs-keyword">some</span> <span class="hljs-type">point</span> I’ll probably have <span class="hljs-keyword">to</span> <span class="hljs-keyword">write</span> automation <span class="hljs-keyword">to</span> <span class="hljs-keyword">only</span> allow <span class="hljs-keyword">access</span> <span class="hljs-keyword">to</span> specific buckets since the OU thing doesn’t seem <span class="hljs-keyword">to</span> be working…<span class="hljs-keyword">or</span> figure that <span class="hljs-keyword">out</span> <span class="hljs-keyword">if</span> I’m just doing something wrong.</pre></div><p id="8325">Now to figure out why KMS is denying access when I enable it…</p><p id="bdd7">Follow for updates.</p><p id="4a3a">Teri Radichel | <i>© <a href="https://2ndsightlab.com/?source=post_page---------------------------">2nd Sight Lab</a> 2022</i></p><div id="8b5f"><pre><span class="hljs-section">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</pre></div><div id="caae"><pre><span class="hljs-section">Need Help With Cybersecurity, Cloud, or Application Security?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</span>
🔒 Request a penetration test or security assessment
🔒 Schedule a consulting call
🔒 Cybersecurity Speaker for Presentation</pre></div><div id="46f6"><pre>Follow <span class="hljs-keyword">for</span> more stories like <span class="hljs-keyword">this</span>:

❤️ Sign Up my Medium Email List ❤️ Twitter: <span class="hljs-meta">@teriradichel</span> ❤️ LinkedIn: https:<span class="hljs-comment">//www.linkedin.com/in/teriradichel</span> ❤️ Mastodon: <span class="hljs-meta">@teriradichel</span><span class="hljs-meta">@infosec</span>.exchange ❤️ Facebook: 2nd Sight Lab ❤️ YouTube: @2ndsightlab</pre></div><figure id="550c"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*4oxP4LXk8l8c3mpRvO7ejg.png"><figcaption></figcaption></figure></article></body>

upload failed: ./[xyz] to s3://abc/xyz An error occurred (AccessDenied) when calling the PutObject operation: Access Denied

Error uploading a file to an S3 bucket

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

⚙️ Check out my series on Automating Cybersecurity Metrics | Code.

🔒 Related Stories: Bugs | AWS Security | Secure Code

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

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

How many years have I been writing S3 bucket policies and IAM policies? At least 10. I’d like to think I’m a halfway decent programmer, though I realize I’ve been doing this way too long and not as quick as I used to be. But that’s where experience is supposed to kick in, right?

I still think programming is fun but sometimes, but when I hit the same non-obvious error messages over and over and I think, there must be a better way. I’ve often thought about writing a better IAM and resource policy generator since AWS doesn’t have very good options. I’m using the IAM policy generator now and it’s not working. I have standard bucket policies I’ve used for years but I’m trying to do something different here so I have been testing with the visual editor, with plans to further automate.

You must know that if I’m still having problems every time I write an S3 bucket policy, beginners are really struggling. And this is why we have security problems and lax security when it comes to resource and IAM policies. It’s hard. Too hard. People can’t figure out what’s wrong so they open up one thing after the other — and leave it that way.

For networking, I wrote a tool to help people figure out what ports their application requires. Cloud providers can provide better error messages and sample zero-trust policies to help people get things done more easily.

~~~~~~~~

But I digress.

~~~~~~~~

So I have a policy currently that allows a rule PutObject permissions to a specific bucket and it is not working. Let’s figure this out. I did something wrong.

For testing purposes I’m starting with IAM only and no bucket policy, so the IAM role is the only thing causing my access to fail. Let’s take a look.

In my policy I have one s3 statement that allows all read and list actions on any bucket. I tried to restrict that with conditions such as MFA, IP address, and a specific OU but as noted in a prior post, none of those are working so they don’t exist here:

My policy should also allow all read and list access to local buckets along with the cross-account buckets that are working.

Next I added the PutObject permission to a specific bucket in my account. Welp. That’s not working. Let’s revisit that policy.

Oh that’s right. I just clicked *all* write actions since I already had all read and get for all S3 resources and here’s what the visual editor created:

"Sid": "VisualEditor3",
            "Effect": "Allow",
            "Action": [
                "s3:PutAnalyticsConfiguration",
                "s3:PutAccelerateConfiguration",
                "s3:DeleteObjectVersion",
                "s3:RestoreObject",
                "s3:CreateBucket",
                "s3:ReplicateObject",
                "s3:PutEncryptionConfiguration",
                "s3:DeleteBucketWebsite",
                "s3:AbortMultipartUpload",
                "s3:PutLifecycleConfiguration",
                "s3:DeleteObject",
                "s3:DeleteBucket",
                "s3:PutBucketVersioning",
                "s3:PutIntelligentTieringConfiguration",
                "s3:PutMetricsConfiguration",
                "s3:PutBucketOwnershipControls",
                "s3:PutReplicationConfiguration",
                "s3:PutObjectLegalHold",
                "s3:InitiateReplication",
                "s3:PutBucketCORS",
                "s3:PutInventoryConfiguration",
                "s3:PutObject",
                "s3:PutBucketNotification",
                "s3:PutBucketWebsite",
                "s3:PutBucketRequestPayment",
                "s3:PutObjectRetention",
                "s3:PutBucketLogging",
                "s3:PutBucketObjectLockConfiguration",
                "s3:ReplicateDelete"
            ],
            "Resource": [
                "arn:aws:s3:::my.bucket/*",
                "arn:aws:s3:::my.bucket"
            ]
        }

Note that I added the two variations of resources for the bucket or any object in the bucket. That’s because it’s annoying to try to remember which actions apply to a bucket or an object and write multiple hard-to-read, convoluted statements. Is that causing my problem? Because this should allow all read access to the bucket and the other policy should allow all write access.

But just for sanity purposes I’ll just allow all actions on this bucket and see what happens. BTW that’s not he real bucket name.

Alright I give.

S3.*

It still doesn’t work. I have s3* to * resources.

Conditions and MFA

As with my last post I have MFA required on the KMS portion of the policy and MFA does not show up for assume role in CloudTrail so let’s remove that.

I’ve confirmed you can’t use those conditions with assumed roles.

Encryption and KMS Keys

The only other thing I can think of, is that the problem has to do with the KMS key assigned to the bucket. That’s not what the error message says, however. You would expect — or at least hope — that the error message would be more specific that this if it were a KMS key issue. I believe I granted access to the key but let’s just remove encryption.

And Finally. It works.

Now, this is *not* where I’m going to stop. If you’re a developer don’t just stop when you get things working. Figure out why they are not working and fix it — and if it is a bug or feature request shoot that over to AWS one way or another. You can tweet it out on Twitter with the hash tag #AWSWishList and someone will probably get your request over to the appropriate AWS team.

In this case I know that my problem is related to one of the KMS error messages I wrote about before in this blog.

  1. Check the KMS Key policy and make sure my role is allowed to use the key.
  2. Check my IAM Permissions and make sure the IAM user is allowed to use KMS for that key.

Oops. I forgot to add users to my KMS Key policy. I could have sworn I did that, but like I said I’ve been doing this far too long. That’s why I’m going to automate…everything. I’m just testing out the plan at the moment. For now, I’ll add the role to the users list on the KMS key and add it back to the bucket and I should be good to go.

Oh…hang on…I have allowed permission by way of another account at the bottom of the key policy screen. Though I would prefer to add a specific role I only have my report builder in that account so I guess it’s OK.

Let’s check the IAM policy…

Here’s where I noticed the visual editor just stuck s3.* in the middle of all the other actions when I allowed it for my testing above:

And people wonder why I don’t generally like things that write code for you. I use them as a starting point, but never in production. Let’s clean that up because I really only need PutObject for the local bucket and read access to the remote buckets.

When I navigate to AWS Access Advisor in IAM for this role, even after a successful PutObject operation I only see ListAllMyBuckets as the action.

I turned on server logging on the s3 bucket in order to see other bucket actions that may be failing. It seems like there is some kind of delay between adding the bucket policy and when it actually works because after restricting my role back down, the policy was failing. I looked in CloudTrail logs and turned on server access logging so I can see what’s failing and now it works without any additional changes.

Here’s the policy I ended up with that allows me to access the remote bucket read-only and put-object on the local bucket (with no encryption currently.)

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:ListAllMyBuckets",
                "s3:ListBucket"
            ],
            "Resource": "*"
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::my.bucket/*",
                "arn:aws:s3:::my.bucket"
            ]
        }
    ]
}

I wish I could further restrict access to remote buckets with a condition on the OU but that doesn’t seem to work. But this role will only have access to the bucket policies that explicitly allow cross-account access to this account and any local buckets. I’m tryin to create a generic tool for certain projects in a specific OU and I don’t want this tool reading buckets in any other account. I also only want it to be able to write to one local bucket. I think that part is OK.

Thoughts on my architecture...
I can get around this issue of not being able to lock down with OUs and MFA by granting copying the files this process needs to read to a specific bucket from the external accounts instead of having this process reach out to buckets in other accounts. But then I have the reverse problem. Every account has write access to a single account and that's more risky than read access the other way around.
I could create a single bucket per project in this account and limit each remote account to its own bucket in the central account, but then I risk a misconfiguration where one of those accounts can see everyone else’s data. I think having to manage the permissions for one single resource to have read-only access to all the other data is safer. But at some point I’ll probably have to write automation to only allow access to specific buckets since the OU thing doesn’t seem to be working…or figure that out if I’m just doing something wrong.

Now to figure out why KMS is denying access when I enable it…

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
Error Message
S3
Putobject
Kms
Access Denied
Recommended from ReadMedium