accessing path through cloudfront gives access denied - amazon-cloudfront

I got a website hosted in cloudfront using an origin id to acess angualr app data in my non-public s3 bucket.
things work fine except that users cannot access paths like www.exmaple.com/path, users do get access denied. They always have to start at root.
I need to enable that access but am struggeling. I found that post, but frank, I dont understand it.
AWS CloudFront redirect to path
I found a workaround by making bucket public and use static website hosting, problem is only that users can bybass cloudfront and go to bucket right away.
anybody got a hint on how to enable paths?

I found some post explaining it.
U need to use the static website hosting enpoint an make it public
In cloudfront you set a header named Referer and give some random secret as value.
You put a bucket policy like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "",
"Action": [
"s3:GetObject",
"s3:GetObjectVersion"
],
"Resource": "arn:aws:s3:::yours3bucket/",
"Condition": {
"StringLike": {
"aws:Referer": "yoursecretvalue"
}
}
},
{
"Effect": "Deny",
"Principal": "",
"Action": [
"s3:GetObject",
"s3:GetObjectVersion"
],
"Resource": "arn:aws:s3:::yours3bucket/",
"Condition": {
"StringNotLike": {
"aws:Referer": "yoursecretvalue"
}
}
}
]
}

Related

No ParameterStore access with sub path definition

I have the following policy in place which works fine on any parameter within /network/testnet/*
{
"Statement": [
{
"Action": [
"ssm:DescribeParameters"
],
"Resource": "*",
"Effect": "Allow"
},
{
"Action": [
"ssm:GetParameters",
"ssm:GetParameter",
"ssm:GetParametersByPath"
],
"Resource": "arn:aws:ssm:eu-central-1:xx:parameter/network/*",
"Effect": "Allow"
}
]
}
but as soon as I want to restrict the resource to arn:aws:ssm:eu-central-1:xx:parameter/network/testnet/* it does no longer allow access to any of the parameters within /network/testnet/*.
My lambda function then gets the following error
"errorType": "Runtime.UnhandledPromiseRejection",
"errorMessage": "AccessDeniedException: User: arn:aws:sts::xxx:assumed-role/dsome-app/some-function is not authorized to perform: ssm:GetParametersByPath on resource: arn:aws:ssm:eu-central-1:xxx:parameter/network/testnet because no identity-based policy allows the ssm:GetParametersByPath action",
Specifically I use CloudFormation and define access like that
Policies:
- SSMParameterReadPolicy:
ParameterName: "network/testnet/*"
Are restriction to sub paths not allowed or what am I missing?
You should be able to do dynamoose.model('example_user', schema, {"create": false}) to get away from the need to create a table https://dynamoosejs.com/guide/Model/

AWS CLI not honoring MultiFactorAuthAge

I'm trying to setup my AWS CLI to assume a role using MFA and expiring the creds after 15 minutes (minimum duration_seconds allowed, apparently).
My IAM role policy is:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::XXXXXXXXXXXX:user/myuser"
},
"Action": "sts:AssumeRole",
"Condition": {
"Bool": {
"aws:MultiFactorAuthPresent": "true"
},
"NumericLessThan": {
"aws:MultiFactorAuthAge": "900"
}
}
}
]
}
My CLI config is setup as follows:
[profile xxx]
role_arn = arn:aws:iam::XXXXXXXXXXXX:role/mfa
mfa_serial = arn:aws:iam::XXXXXXXXXXXX:mfa/foobar
source_profile = mfa
When I run a command using the xxx profile above, MFA is asked the first time and remains valid for all the subsequent requests. However, after 15 minutes, the token is still valid and MFA isn't asked again.
$ aws s3 ls --profile xxx
I tried setting the duration_seconds parameter on my CLI as below:
[profile xxx]
role_arn = arn:aws:iam::XXXXXXXXXXXX:role/mfa
mfa_serial = arn:aws:iam::XXXXXXXXXXXX:mfa/foobar
source_profile = mfa
duration_seconds = 900
But now, I'm asked the MFA token for every command issued, even if the time difference is in the order of seconds.
Am I missing something here?
AWS CLI version: aws-cli/2.0.49 Python/3.7.4 Darwin/19.6.0 exe/x86_64
Appreciate any help.
Thanks in advance!
So, I discovered the reason for this behavior:
As described in this Github Issue, AWS CLI treats any session within 15min as expired, refreshing the creds automatically (or asking for a new one-time passcode, in case of MFA).
So, setting the session duration for 15min (900s) is basically the same as getting a one-time credential.
I just tested setting the session_duration to 930 (15min + 30s), and the session is indeed valid for 30 seconds.
Seems that the issue is with your conditions.
"Bool": {
"aws:MultiFactorAuthPresent": "true"
},
This will always require the MFA
instead try something like that:
{
"Version": "2012-10-17",
"Statement":[
{
"Sid": "AllowActionsForEC2",
"Effect": "Allow",
"Action": ["ec2:RunInstances",
"ec2:DescribeInstances",
"ec2:StopInstances "],
"Resource": "*"
},
{
"Sid": "AllowActionsForEC2WhenMFAIsPresent",
"Effect":"Allow",
"Action":"ec2:TerminateInstances",
"Resource":"*",
"Condition":{
"NumericLessThan ":{"aws:MultiFactorAuthAge":"300"}
}
}
]
}
The Users with short-term credentials older than 300 seconds must reauthenticate to gain access to this API.
So for your policy it will look like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::XXXXXXXXXXXX:user/myuser"
},
"Action": "sts:AssumeRole",
"Condition": {
"NumericLessThan": {
"aws:MultiFactorAuthAge": "900"
}
}
}
]
}
The issue is that every conditions needs to be met in order for you to be able to assume the role. "aws:MultiFactorAuthPresent": "true" will always check if you used the MFA to login.

How to access cross region s3 bucket by lambda using CDK Python

I have created lambda in region A and a S3 bucket in region B , trying to access bucket from lambda boto-3 client but getting an error(access denied).Please suggest some solution for this in python CDK. Will I need to create any specific policy for it.
Your lambda function requires permissions to read S3.
The easiest way to enable that is to add AWS managed policy:
arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
to your lambda execution role.
Specifying region is not required, as S3 buckets have global scope.
You have to explicitly pass the region name of the bucket if it is not in the same region as the lambda (because AWS have region specific endpoints for S3 which needs to be explicitly queried when working with s3 api).
Initialize your boto3 S3 client as:
import boto3
client = boto3.client('s3', region_name='region_name where bucket is')
see this for full reference of boto3 client:
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/core/session.html#boto3.session.Session.client
---------Edited------------
you also need the following policy attached to (or inline in) the role of your lambda:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ExampleStmt",
"Action": [
"s3:GetObject"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::YOUR-BUCKET-NAME/*"
]
}
]
}
If you need to list and delete the objects too, then you need to have the following policy instead, attached to (or inline in) the role of the lambda:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "ExampleStmt1",
"Action": [
"s3:GetObject",
"s3:DeleteObject"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::YOUR-BUCKET-NAME/*"
]
},
{
"Sid": "ExampleStmt2",
"Action": [
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::YOUR-BUCKET-NAME"
]
}
]
}

Lambda function is not authorized to perform sts:AssumeRole

I have a lambda function in account A trying to access resources from account B. Created a new lambda role with basic execution with access to upload logs to cloud watch.
Here's my function code in Python 3.7:
import boto3
allProfiles = ['account2']
def lambda_handler(event, context):
sts_connection = boto3.client('sts')
acct_b = sts_connection.assume_role(
RoleArn="arn:aws:iam::2222222222:role/role-on-source-account",
RoleSessionName="account2"
)
for profiles in allProfiles:
print("\nusing profile %s" % profiles)
newMethod..
return {
'statusCode': 200,
'body': json.dumps('Hello from Lambda!')
}
Also modified the trust policy of the assumed role in account B as mentioned in documentation: https://aws.amazon.com/premiumsupport/knowledge-center/lambda-function-assume-iam-role/
ERROR: An error occurred (AccessDenied) when calling the AssumeRole
operation: User:
arn:aws:sts::11111111:assumed-role/lambda-role/lambda-function is not
authorized to perform: sts:AssumeRole on resource:
arn:aws:iam::2222222222:role/role-on-source-account"
Note: I am able to run this in my local successfully but not in lambda.
Created a new lambda role with basic execution with access to upload logs to cloud watch
Basic execution role for lambda is not enough. You need to explicitly allow your function to AssumeRole. The following statement in your execution role should help:
{
"Effect": "Allow",
"Action": [
"sts:AssumeRole"
],
"Resource": [
"arn:aws:iam::2222222222:role/role-on-source-account"
]
}
Ok so what we have is:
Your (your own trusted account) accountA need to assume a specific role in the AccountB account
A role in the AccountB (the trusting account) that your lambda is going to access a, let's say a bucket on.
AccountBBucket
You mentioned you had Basic execution for your lambda and that alone would not be enough...
Solution:
Create a role "UpdateBucket":
you need to establish trust between AccountB(account ID number:999) and AccountA.
Create an IAM role and define the AccountA as a trusted entity, specify a permission policy that allows trusted users to update the AccountB_resource(AccountBBucket).
We Are in AccountA now
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:ListAllMyBuckets",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetBucketLocation"
],
"Resource": "arn:aws:s3:::AccountBBucket"
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:DeleteObject"
],
"Resource": "arn:aws:s3:::AccountBBucket/*"
}
]
}
Grant Access:
we will now use the role we created earlier, the (UpdateBucket) role
This needs to be added to your AccountB permissions
We are now in AccountB now:
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::999:role/UpdateBucket"
}
}
Note that the 999 above is AccountB account Id and the UpdateBucket is the role that was created in AccountA
This would create the trust you need for your lambda to access the bucket on AccountB
More info on here:
Delegate Access Across AWS Accounts Using IAM Roles

How to go from a AWS-console-derived policy to a working terraform-scripted policy?

I have a terraform script that provides a lambda function on aws to send emails. I pieced this terraform script from tutorials and templates on the web to use AWS SES, Api Gateway, Lambda and Cloudwatch services.
To get permissions to work though, I had to run the script and then, separately, build a policy in the AWS console and apply it to the lambda function so that it could fully access the SES and Cloudwatch services. But it's not at all not clear to me how to take that working policy and adapt it to my terraform script. Could anyone please provide or point to guidance on this matter?
The limited/inadequate but otherwise working role in my terraform script looks like this:
resource "aws_iam_role" "iam_for_lambda" {
name = "${var.role_name}"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": [
"lambda.amazonaws.com"
]
},
"Effect": "Allow",
"Sid": ""
}
]
} EOF
}
... and the working policy generated in the console (by combining two roles together for all-Cloudwatch and all-SES access):
{
"permissionsBoundary": {},
"roleName": "las_role_new",
"policies": [
{
"document": {
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"autoscaling:Describe*",
"cloudwatch:*",
"logs:*",
"sns:*",
"iam:GetPolicy",
"iam:GetPolicyVersion",
"iam:GetRole"
],
"Effect": "Allow",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "iam:CreateServiceLinkedRole",
"Resource": "arn:aws:iam::*:role/aws-service-role/events.amazonaws.com/AWSServiceRoleForCloudWatchEvents*",
"Condition": {
"StringLike": {
"iam:AWSServiceName": "events.amazonaws.com"
}
}
}
]
},
"name": "CloudWatchFullAccess",
"id": "ANPAIKEABORKUXN6DEAZU",
"type": "managed",
"arn": "arn:aws:iam::aws:policy/CloudWatchFullAccess"
},
{
"document": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ses:*"
],
"Resource": "*"
}
]
},
"name": "AmazonSESFullAccess",
"id": "ANPAJ2P4NXCHAT7NDPNR4",
"type": "managed",
"arn": "arn:aws:iam::aws:policy/AmazonSESFullAccess"
}
],
"trustedEntities": [
"lambda.amazonaws.com"
]
}
There are fields
So my question in summary, and put most generally, is this:
given a "policy" built in the aws console (by selecting a bunch of roles, etc. as in ), how do you convert that to a "role" as required for the terraform script?
To anyone else who might struggle to understand terraform-aws-policy matters, here's my understanding after some grappling. The game here is to carefully distinguish the various similar-sounding terraform structures (aws_iam_role, aws_iam_role_policy, aws_iam_role, assume_role_policy, etc.) and to work out how these black-box structures fit together.
First, the point of an aws role is to collect together policies (i.e. permissions to do stuff). By assigning such a role to a service (e.g. lambda), you thereby give that service the permissions described by those policies. A role must have at least one policy sort of built-in to it: the 'assume-role' policy that specifies which service(s) can use ('assume') that role. This assume-role policy is relatively simple and so 'might as well' be included in the terraform script explicitly (using the <<EOF ... EOF syntax above).
Secondly, if you want to now let that service with the (basic) role do anything to other services, then you need to somehow associate additional policies with that role. I've learned that there are several ways to do this but, in order to answer my question most succinctly, I'll now describe the most elegant way I have found to incorporate multiple template policies offered in the AWS console into one's terraform script.
The code is:
# Define variable for name of lambda function
variable "role_name" {
description = "Name for the Lambda role."
default = "las-role"
}
# Create role with basic policy enabling lambda service to use it
resource "aws_iam_role" "iam_for_lambda" {
name = "${var.role_name}"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": [ "lambda.amazonaws.com" ]
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
# Define a list of policy arn's given in the AWS console
variable "iam_policy_arn_list" {
type = list(string)
description = "IAM Policies to be attached to role"
default = ["arn:aws:iam::aws:policy/CloudWatchFullAccess", "arn:aws:iam::aws:policy/AmazonSESFullAccess"]
}
# Create attachment of the policies for the above arn's to our named role
# The count syntax has the effect of looping over the items in the list
resource "aws_iam_role_policy_attachment" "role-policy-attachment" {
role = var.role_name
count = length(var.iam_policy_arn_list)
policy_arn = var.iam_policy_arn_list[count.index]
depends_on = [aws_iam_role.iam_for_lambda]
}
As you can see, the template policies are included here using the arns which can be found in the AWS console. For example, here's the view for finding the arn for full access to Amazon SES via the AWS Management Console:
When you succesfully deploy your lambda to AWS using terraform, it will pull down these policies from the arns and generate a permission json for your lambda function (which you can view in the lambda-service section of the aws console) that looks a lot like the json I posted in the question.

Resources