Cloudformation for a kube2iam role - kubernetes

I'm having trouble creating a role for kube2iam, everything seems to work fine I deploy the stack with the role and the pods spin up but whenever a pod tries to perform an authorized action (put an item into dynamo in this case) I get an error that the assumed role is not authorized. Here's the snippet that creates the role:
ServiceRole:
Type: "AWS::IAM::Role"
Properties:
RoleName:
Ref: StackName
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Service:
- "ec2.amazonaws.com"
Action:
- "sts:AssumeRole"
Path: "/"
Policies:
- PolicyName:
Ref: StackName
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Action:
- dynamodb:PutItem
Resource:
Fn::GetAtt: [Table, Arn]
The table is elsewhere in the same stack and deploys just fine. I deployed kube2iam via a helm chart
The error I get is:
User: arn:aws:sts::<BLAHBLAH>:assumed-role/nodes.k8s.logint.cimpress.io/<BLAHBLAH> is not authorized to perform: dynamodb:PutItem on resource <BLAHBLAH>
I also tried this for the assume role:
- Effect: "Allow"
Principal:
AWS: "arn:aws:iam::<BLAHBLAH>:role/nodes.<BLAHBLAH>"
Action:
- "sts:AssumeRole"
I still get the same error

Related

The state machine IAM Role is not authorized to access the Log Destination

I am trying to deploy a CF stack which is failing because of an IAM permission issue. The concerning resources in the stack for this issue are:
state machine (step function)
Cloudwatch log group
A subscription filter for the log group
This subscription filter forwards the logs to Kenesis where the logs are streamed into splunk. Coming back to my issue, when I try to deploy the above CF stack, I get the following error: The state machine IAM Role is not authorized to access the Log Destination
I have given the following permissions to the role attached to the state machine
StateMachineRole:
Type: AWS::IAM::Role
DeletionPolicy: Retain
Properties:
RoleName: StateMachineRole-${self:custom.env.stage}
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: states.amazonaws.com
Action: sts:AssumeRole
LambdaPolicy:
Type: AWS::IAM::Policy
DeletionPolicy: Retain
DependsOn: CustomLogGroup
Properties:
PolicyName: LambdaPolicy-${self:custom.env.stage}
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- 'lambda:InvokeFunction'
Resource: lambdaArn
- Effect: Allow
Action:
- 'logs:CreateLogDelivery'
- 'logs:GetLogDelivery'
- 'logs:UpdateLogDelivery'
- 'logs:DeleteLogDelivery'
- 'logs:ListLogDeliveries'
- 'logs:PutLogEvents'
- 'logs:PutResourcePolicy'
- 'logs:DescribeResourcePolicies'
- 'logs:DescribeLogGroups'
- 'logs:PutDestination'
- 'logs:PutSubscriptionFilter'
- 'logs:PutDestinationPolicy'
Resource: !GetAtt CustomLogGroup.Arn
/*CustomLogGroup*/
CustomLogGroup:
Type: AWS::Logs::LogGroup
Properties:
KmsKeyId: !ImportValue XXXXXXX
LogGroupName: CustomLogGroupName
RetentionInDays: ${file(./.env.${self:custom.env.stage}.yaml):cloudwatchLogs.retentionDays
Referred to the following SO question: Aws step function deployment log access issue

Run a crawler using CloudFormation template

This CloudFormation template works as expected and creates all the resources required by this article:
Data visualization and anomaly detection using Amazon Athena and Pandas from Amazon SageMaker | AWS Machine Learning Blog
But the WorkflowStartTrigger resource does not actually run the crawler. How do I run a crawler using the CloudFormation template?
Resources:
MyRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Principal:
Service:
- "glue.amazonaws.com"
Action:
- "sts:AssumeRole"
Path: "/"
Policies:
-
PolicyName: "root"
PolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Action: "*"
Resource: "*"
MyDatabase:
Type: AWS::Glue::Database
Properties:
CatalogId: !Ref AWS::AccountId
DatabaseInput:
Name: "dbcrawler123"
Description: "TestDatabaseDescription"
LocationUri: "TestLocationUri"
Parameters:
key1 : "value1"
key2 : "value2"
MyCrawler2:
Type: AWS::Glue::Crawler
Properties:
Description: example classifier
Name: "testcrawler123"
Role: !GetAtt MyRole.Arn
DatabaseName: !Ref MyDatabase
Targets:
S3Targets:
- Path: 's3://nytaxi162/'
SchemaChangePolicy:
UpdateBehavior: "UPDATE_IN_DATABASE"
DeleteBehavior: "LOG"
TablePrefix: test-
Configuration: "{\"Version\":1.0,\"CrawlerOutput\":{\"Partitions\":{\"AddOrUpdateBehavior\":\"InheritFromTable\"},\"Tables\":{\"AddOrUpdateBehavior\":\"MergeNewColumns\"}}}"
WorkflowStartTrigger:
Type: AWS::Glue::Trigger
Properties:
Description: Trigger for starting the Crawler
Name: StartTrigger
Type: ON_DEMAND
Actions:
- CrawlerName: "testcrawler123"
You should be able to do that by creating a custom resource attached to a lambda whereby the lambda actually does the action of starting the crawler. You should be able to even make it wait for the crawler to complete its execution
CloudFormation directly doesn't run crawlers, it just create them.
But you can create a schedule in order to run a crawler while defining trigger:
ScheduledJobTrigger:
Type: 'AWS::Glue::Trigger'
Properties:
Type: SCHEDULED
StartOnCreation: true
Description: DESCRIPTION_SCHEDULED
Schedule: cron(5 * * * ? *)
Actions:
- CrawlerName: "testcrawler123"
Name: ETLGlueTrigger
If needed to run crawler as part of CloudFormation stack creation, Lambda could be used.

ARN of the role that is automatically created with an Lambda function

In a SAM template, is there a way to reference the ARN of the role that is automatically created with an Lambda function?
I would need to use that ARN somewhere else in the template.
# this is the role
Role:
Type: AWS::IAM::Role
Properties:
RoleName: client-role
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
- Effect: Allow
Principal:
AWS: "arn:aws:iam::xxxx:role/xxxxxxx-ApiHandlerRole-12UWXALxxxxx"
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonS3FullAccess
# this is the lambda
ApiHandler:
Type: AWS::Serverless::Function
Properties:
FunctionName: api-handler
......
Policies:
- DynamoDBCrudPolicy:
TableName: !Ref Table
- S3ReadPolicy:
BucketName: !Ref Bucket
- S3WritePolicy:
BucketName: !Ref Bucket
- Version: "2012-10-17"
Statement:
- Effect: Allow
Action: sts:AssumeRole
Resource: !GetAtt Role.Arn
I think what you do is separate the Resource build of the Role.
Then you can use the !Ref Role anywhere you need it, including in your lambda Role.
You can construct the ARN of the role yourself. It has fixed format. From docs:
If a role isn't specified, one is created for you with a logical ID of function-logical-idRole.
For example using Sub:
!Sub "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/function-logical-idRole"
where function-logical-id is your lambda function logical id.
Something like...
# this is the lambda
ApiHandler:
Type: AWS::Serverless::Function
Properties:
FunctionName: api-handler
Policies:
......
# this is the role
Role:
Type: AWS::IAM::Role
Properties:
RoleName: client-role
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
Service: lambda.amazonaws.com
Action: sts:AssumeRole
- Effect: Allow
Principal:
AWS: !GetAtt ApiHandlerRole.Arn
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonS3FullAccess
Assuming that you have not specified the "AssumeRolePolicyDocument" for your function.
(code above based on the pastebin), the SAM cli will generate a role called "ApiHandlerRole" for you.
from the docs:
If this property isn't specified, AWS SAM adds a default assume role
for this function.
Which from the looks of it you may want to just explore that property some more. I'm new to AWS SAM but there has got to be way to plug "arn:aws:iam::aws:policy/AmazonS3FullAccess" at it. :)
Hope this helps all
docs link : https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html#sam-function-assumerolepolicydocument
SOLUTION:
So, I bumped into this situation today.
Suppose your Resource Lambda is named MyLambda, then use
!Ref MyLambdaRole.Arn
Tried and tested, works like a charm.
Reason why it works: If you expand the processed template, the IAM Role resource is named using the following nomenclature
<lambda-logical-id>Role
Don't forget to upvote! :D
What worked for me is refer the ARN Attribute of the autogenerated role like
SomeLambdaFunction:
Type: AWS::Serverless::Function
Properties:
...other properties...
Policies:
... Some sam policies...
.... different resource reference Lambda autogenerate role...
- Action: //some actions here
Effect: Allow
Principal:
AWS: !GetAtt SomeLambdaFunctionRole.Arn
Resource: "*"
.... More template code...

How to get an AWS KMS Key Arn and pass it in IAM role inline policy by CloudFormation?

I am trying to create IAM role and KMS key through CloudFormation template. My requirement is first I need to create KMS Key, get the ARN of it and then while creating IAM role, beed to pass that KMS ARN. This is what my policy looks like:
Resources:
myKey:
Type: AWS::KMS::Key
Properties:
Description: Key for encrypting S3 Buckets
Enabled: TRUE
KeyPolicy:
Version: '2012-10-17'
Statement:
- Sid: Enable IAM User Permissions
Effect: Allow
Principal:
AWS: arn:aws:iam::11111111:root
Action: kms:*
Resource: '*'
KeyUsage: ENCRYPT_DECRYPT
myAlias:
Type: AWS::KMS::Alias
Properties:
AliasName: alias/key_for_s3_encrytpion
TargetKeyId:
Ref: myKey
RootRole:
Type: 'AWS::IAM::Role'
Properties:
RoleName: 'Lambda-S3-SNS-VPC-Role-cft'
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- 'sts:AssumeRole'
Path: /
ManagedPolicyArns:
- !Ref AmazonVPCFullAccessARN
- !Ref AmazonS3FullAccessARN
- !Ref AWSLambdaBasicExecutionRoleARN
- !Ref AmazonSNSFullAccessARN
- !Ref AmazonSSMFullAccessARN
Policies:
- PolicyName: kms_cross_account
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- "kms:Decrypt"
- "kms:Encrypt"
- "kms:GenerateDataKey"
- "kms:DescribeKey"
- "kms:ReEncrypt*"
Resource:
- <Here I need to pass KMS Key ARN created above>
I tried placing !Sub in Resource:
- !Sub 'arn:aws:kms:${AWS::Region}:${AWS::AccountId}:alias/key_for_s3_encrytpion'
but its directly placing this whole as a string
Solved. I used !GetAtt myKey.Arn to get the KMS ARN in iAM role

AWS ApiGateway Proxy to non-Public S3 Bucket

The following cloudformation script sets up an Api Gateway method that proxies to an S3 bucket.
The S3BucketPolicy opens up the bucket to public read access but the AWS UI warns that this should never be done.
I tried setting the S3BucketPolicy Principal to service apigateway.amazonaws.com but this results in Access Denied.
1) What is the right way to limit bucket access to the API gateway function? (Sample YAML would be great)
2) How could I debug this Access Denied failure to get more information on why it failed?
3) Where should I be looking for sample code on what should be a very standard template snippet?
ATTEMPT #1 - Works but only by making the S3 Bucket Public otherwise Access Denied
AWSTemplateFormatVersion: 2010-09-09
Parameters:
S3BucketName:
Type: String
Description: >
Name for the S3 bucket that contains the nested templates.
Resources:
RestAPI:
Type: 'AWS::ApiGateway::RestApi'
Properties:
BinaryMediaTypes:
- '*/*'
Name: !Ref 'AWS::StackName'
RestAPIRootGET:
Type: 'AWS::ApiGateway::Method'
Properties:
AuthorizationType: NONE
HttpMethod: GET
Integration:
IntegrationHttpMethod: GET
PassthroughBehavior: WHEN_NO_MATCH
Type: HTTP_PROXY
Uri: !Sub https://${S3BucketName}.s3.amazonaws.com/static-assets/index.html
ResourceId: !GetAtt RestAPI.RootResourceId
RestApiId: !Ref RestAPI
DependsOn:
- RestAPI
BucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref S3BucketName
PolicyDocument:
Version: 2012-10-17
Statement:
-
Sid: GetObject
Effect: Allow
Principal: "*"
Action:
- s3:*
Resource:
- !Sub 'arn:aws:s3:::${S3BucketName}/static-assets/*'
I think perhaps the right away is to create a role with access to the bucket and then have the ApiGateway assume this role but I'm having a hard time finding documentation that explains how to do this in a cloudformation template. (see also Michael - sqlbot comment suggesting using the credentials property of the method)
Here is my attempt which still fails with Access Denied
ATTEMPT #2 - Access Denied
AWSTemplateFormatVersion: 2010-09-09
Parameters:
S3BucketName:
Type: String
Description: >
Name for the S3 bucket that contains the nested templates.
Resources:
RestAPI:
Type: 'AWS::ApiGateway::RestApi'
Properties:
BinaryMediaTypes:
- '*/*'
Name: !Ref 'AWS::StackName'
RestAPIRootGET:
Type: 'AWS::ApiGateway::Method'
Properties:
AuthorizationType: NONE
HttpMethod: GET
Integration:
IntegrationHttpMethod: GET
PassthroughBehavior: WHEN_NO_MATCH
Type: HTTP_PROXY
Uri: !Sub https://${S3BucketName}.s3.amazonaws.com/static-assets/index.html
Credentials: !GetAtt AllowStaticAccessRole.Arn
ResourceId: !GetAtt RestAPI.RootResourceId
RestApiId: !Ref RestAPI
DependsOn:
- RestAPI
- AllowStaticAccessRole
AllowStaticAccessRole:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Principal:
Service:
- "apigateway.amazonaws.com"
Action:
- "sts:AssumeRole"
Path: "/"
Policies:
-
PolicyName: "AllowStaticAccessPolicy"
PolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Action:
- s3:*
Resource:
- !Sub 'arn:aws:s3:::${S3BucketName}/static-assets/*'
As already mentioned in the comments, the Access Denied error could be coming from KMS rather than from the S3 itself.
To solve the issue, you need to add at minimum these permissions to the role that the Api Gateway assumes: "kms:Decrypt", "kms:ReEncryptFrom", preferably also stating which Resource this should apply too for proper least privilege implementation.