question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[aws-s3] Bucket.grantRead do nothing with an imported ec2.Instance

See original GitHub issue

I expected that the code below would add a policy to the bucket or the EC2 instance.

const bucket = new s3.Bucket(this, 'Bucket', { ... });
bucket.grantRead(someImportedEC2Instance);

However, the policy was not added to either of them. Other grant methods also have the same issue.

Reproduction Steps

  1. Create an EC2 instance in one stack (call it Stack A)
  2. Pass the EC2 instance created in Stack A to another stack (Stack B)
  3. Create an S3 bucket in Stack B
  4. Call bucket.grantRead with the EC2 instance from Stack A.

What did you expect to happen?

A new policy is added to the EC2 instance’s role (i.e. principal) or to the bucket (i.e. resource).

What actually happened?

A new policy is not added to either of them and resource cannot be read from the EC2 instance.

Environment

  • CLI Version : 1.58.0
  • Framework Version: 1.58.0
  • Node.js Version: 14.7.0
  • OS : Ubuntu 18.04
  • Language (Version): TypeScript (3.8.3)

Other

I investigated a bit why it happened and it turned out that iam.Role.addToPrincipalPolicy associated with the EC2 instance always returns an object having statementAdded: true regardless of whether it’s imported or not. Because of that, iam.Grant.addToPrincipalOrResource, which internally calls addToPrincipalPolicy, never tries to add a policy to a resource. At the same time, a policy that seemed to be added to the EC2 instance didn’t take effect. As a result, a newly created policy is not added to anywhere.

As a workaround, I’m adding a resource policy to the bucket with an explicit principal. So, this issue isn’t too critical, but it was quite confusing as it didn’t report any error or warning.


This is 🐛 Bug Report

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
iliapolocommented, Aug 25, 2020

@nobu-k

In other words, I didn’t think writing some code in StackB would required StackA to be deployed again.

Yeah, in general, if the code you write in StackB interacts with resources from StackA, it might create additional resources in StackA, which means StackA needs to be redeployed.

However, if StackB depends on StackA, CDK will detect that and automatically redeploy StackA for you. The “problem” here is that actually StackB doesn’t depend on StackA since the policy is added to the instance principal rather than the resource. So in fact, StackA actually depends on StackB, which means that if you had just deployed StackA again after implementing StackB, it would have deployed both stacks.

I would recommend to always deploy all stacks in the application (or at least with a pattern), CDK will deploy the stacks in the correct order, and skip stacks that haven’t changed.

Also, what is the best way to do something equivalent to this without affecting StackA

You’ll have to explicitly add the relevant policy using bucket.addToResourcePolicy.

const statement = new iam.PolicyStatement({
  actions: [
    's3:GetObject*',
    's3:GetBucket*',
    's3:List*',
  ],
  resources: [bucket.bucketArn, bucket.arnForObjects('*')],
  principals: [props.principal],
});

bucket.addToResourcePolicy(statement);

I’m gonna go ahead and close this issue out, feel free to reach out if something still isn’t clear.

0reactions
nobu-kcommented, Aug 24, 2020

You then pass the instance itself as an IPrincipal even though ec2.Instance does not implement iam.IPrincipal - It only implements iam.IGrantable - Is this a typing mistake or am I missing something?

Thank you for pointing this out. I messed up the example during trial and errors I did. I originally passed the instance as IGrantable, but later I changed it to IPrincipal and passed stackA.instance.grantPrincipal to Stack B instead to see if it could make any difference. Then, I mixed up two versions into the example above.

I prepared the repository at https://github.com/nobu-k/cdk-reproduction-9661 . What I’ve done is

  1. Implement StackA
  2. Deploy StackA
  3. Implement StackB
  4. Deploy StackB

These steps don’t add any permission to the instance in StackA. However, I noticed that, after deploying StackB, I had to deploy StackA again to make the grantRead in StackB to take effect. I think this was my misunderstanding, but I thought everything I wrote in a stack would only affect that stack. In other words, I didn’t think writing some code in StackB would required StackA to be deployed again.

So, I now understand what I need to do with the issue I had, but I want to confirm if this is an intended behavior.

Also, what is the best way to do something equivalent to this without affecting StackA (i.e. to add resource-based policy to the bucket rather than adding a policy to IGrantable from other stacks)? Please feel free to redirect me to the AWS support if this isn’t the right place to ask this kind of questions.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Grant an EC2 instance access to an S3 bucket - Amazon AWS
I'm unable to access an Amazon Simple Storage Service (Amazon S3) bucket from my Amazon Elastic Compute Cloud (Amazon EC2) instance. How can...
Read more >
Unable to export ec2 instance to S3 - Stack Overflow
Based on the error you're getting the destination bucket must grant WRITE and READ_ACL permissions to the vm-import-export@amazon.com AWS ...
Read more >
How to set up an Amazon S3 Bucket using AWS CDK
Once you've installed AWS CDK you can validate that you're running ... import * as s3 from 'aws-cdk-lib/aws-s3'; import { Construct } from ......
Read more >
S3 Bucket Example in AWS CDK - Complete Guide | bobbyhadz
import * as s3 from 'aws-cdk-lib/aws-s3'; import * as cdk from 'aws-cdk-lib'; export class CdkStarterStack extends cdk.Stack { constructor(scope: cdk.
Read more >
AWS S3 Implementation using Node.js | by Shraddha Paghdar
AWS S3 (Simple Storage Service) allows you to store & retrieve any amount of ... GrantRead specifies who can read the bucket &...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found