Can I allow anonymous access to AWS API Gateway documentation? - amazon-web-services

I have a CloudFormation template that includes an API Gateway configured using an OpenAPI 3.0 body. I would like to make the OpenAPI specification available to the users of my API. Ideally within a nice GUI but this answer suggests that's not possible. I do not want to set up a developer portal.
My CFT contains a DocumentationVersion element that creates documentation for the API.
According to this and this I should be able to download my documentation from a URL like
https://apigateway.[my_aws_region].amazonaws.com/restapis/[my_api_id]/stages/[my_api_stage]/exports/oas30
Indeed when I go to this URL I get something like
{"logref":"56f5173b-a329-11e9-a8d5-e97c525eb634","message":"Missing Authentication Token"}
Which suggests that this will work with the correct token.
This page shows that you can control access to API documentation with a policy. (Although oddly it says that the account_id to use is the one of the users you want to grant access to - is that correct?)
So I tried adding the following resource to my CFT:
"ApiDocumentationAccessPolicy": {
"Type": "AWS::IAM::ManagedPolicy",
"Properties": {
"Description": "Read access to API documentation restricted by IP",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"apigateway:GET"
],
"Resource": {
"Fn::Join": [
"",
[
"arn:aws:apigateway::",
{ "Ref": "AWS::AccountId" },
":/restapis/",
"*/documentation/*"
]
]
},
"Condition" : {
"IpAddress": {
"aws:SourceIp": ["xxx.xxx.xxx.xxx" ]
}
}
}
]
}
}
},
However, I still get "Missing Authentication Token". I am confident that the "condition" part is correct as it is used elsewhere in CFT.
Is what I want to do possible, and if so where am I going wrong?
EDIT Adding "Principal": "*" to the policy statement above and also moving it directly to the APIGateway's policy don't appear to help either.

Related

New AWS Lambda URLs - has anyone got the 'secure' version with the AWS_IAM working?

I have a simple function that returns an item of text.
When I set auth to NONE it works fine.
When I set auth to AWS_IAM and create the resource based policy within the permissions section of AWS Lambda I set the following:
"Version": "2012-10-17",
"Id": "default",
"Statement": [
{
"Sid": "sid8",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::xxxxxxxxxx:user/xxxxxxxxxx"
},
"Action": "lambda:InvokeFunctionUrl",
"Resource": "arn:aws:lambda:eu-west-1:xxxxxxxxx:function:simpleFunction",
"Condition": {
"StringEquals": {
"lambda:FunctionUrlAuthType": "AWS_IAM"
}
}
}
]
}
On this I get a forbidden error.
Every demo / example on the internet uses NONE for auth.
I have also tried adding the lambda:InvokeFunctionUrl to the IAM policy of the user for the specified resource but still getting a forbidden error.
Am I missing something or does this aspect of the new function not work?
The problem is that when you are using IAM_AUTH you're required to sign your requests with SigV4. Essentially, this is identical to using API Gateway with IAM_AUTH type.
There are multiple ways of signing requests you can even use botocore functionality to do so. The easiest would be to use awscurl or postman, also check this doco that confirms this requirement https://docs.aws.amazon.com/lambda/latest/dg/urls-invocation.html

SCP to deny all resources except certain resources in AWS Organization

I want to block all resources except EC2, RDS and global services in AWS Organization. Below is my SCP Policy.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyAllOutsideEU",
"Effect": "Deny",
"NotAction": [
"iam:*",
"cloudfront:*",
"route53:*",
"route53domains:*",
"s3:GetAccountPublic*",
"s3:ListAllMyBuckets",
"s3:PutAccountPublic*",
"shield:*",
"sts:*",
"support:*",
"trustedadvisor:*",
"waf-regional:*",
"waf:*",
"wafv2:*",
"wellarchitected:*"
],
"Resource": "*",
"Condition": {
"StringNotEquals": {
"aws:RequestedRegion": [
"ap-south-1"
]
},
"ArnNotLike": {
"aws:PrincipalARN": [
"arn:aws:iam::*:role/Role1AllowedToBypassThisSCP",
"arn:aws:iam::*:role/Role2AllowedToBypassThisSCP"
]
}
}
}
]
}
Using this policy, I'm not able to get full access to WAF. Below is WAF service access denied error screen shot.
Can any one please help me to achieve this?
What you are missing is ec2:DescribeRegions.
You already have all the access you want. If you try through aws cli you can do whatever you have allowed in the policy. However Web ACLs page in AWS console has a dropdown to load all AWS regions which uses the ec2:DescribeRegions api call and if you don't have it you can't open the page.
You have two options. Either add the missing permission to your policy. Or if you don't want to add that you can add region=ap-south-1 to your URL in the browser every time you navigate to WAF page.
Also I suggest you to look into arn:aws:iam::aws:policy/AWSWAFConsoleFullAccess. There are other permissions you might need. For example if you want to associate a web-acl to a Load Balancer you will need elasticloadbalancing:DescribeLoadBalancers and elasticloadbalancing:SetWebACL.

AWS Serverless DynamoDB Row Level Authorization With Cognito and Lambda Functions

Alright, so I currently have almost everything working by following this guide here and pieces of several others.
https://aws.amazon.com/blogs/mobile/building-fine-grained-authorization-using-amazon-cognito-user-pools-groups/
However, instead of giving users direct access to the DynamoDB, I am running it through an API Gateway and then a Lambda Function using an Authorization header and the Cognito session id.
I have that part working.
In my lambda function I call the update function
const data = await documentClient.update(params).promise();
I have AWSLambdaBasicExecutionRole policy and the following policy added to my lambda function role to allow the row level access for Update
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor1",
"Effect": "Allow",
"Action": [
"dynamodb:UpdateItem"
],
"Resource": [
"arn:aws:dynamodb:us-east-2:mydynamodbid:table/userdata"
],
"Condition": {
"ForAllValues:StringEquals": {
"dynamodb:LeadingKeys": "${cognito-identity.amazonaws.com:sub}"
}
}
}
]
It works fine with the AmazonDynamoDBFullAccess but I am not sure that is accomplishing what I am looking for as I think it just completely bypasses the condition.
I am getting the following error though
"User: arn:aws:sts::**********:assumed-role/db-crud/update-user-info-by-id is not
authorized to perform: dynamodb:UpdateItem on resource: arn:aws:dynamodb:us-east-
2:************:table/userdata"
Has anyone encountered anything like this or see where I am possibly going wrong?
This is the flow I am going for, and this is related to step 6

Adding IP whitelisting security to API gateway

I have a API on AWS API gateway which calls LAMBDA function and I want to add IP whitelisting for that API so the allowed IPs only can have access to that API. How can I achieve this?
There is a really extended blog post about this which you can find here.
Bottom line, it comes to this:
Per method, select IAM Authorization method.
Create a new IAM policy that looks like the one below and attach it to the API Method.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"execute-api:Invoke"
],
"Condition": {
"IpAddress": {
"aws:SourceIp": "xxx.xx.xx.xx/32"
}
},
"Resource": "arn:aws:execute-api:*:*:*"
}
]
}
You can add multiple SourceIps if needed.

How do I confirm a subscription created using CloudFormation?

I have created a CF script that creates an EC2 instance that contains a web service. It also creates an SNS Topic and a Subscription that uses this web service as it's http endpoint.
The script successfully creates the stack; the Topic and the Subscription exist. However, the Subscription remains in the PendingConfirmation state.
What must I do to get my script to confirm this Subscription upon creation?
I had a similar issue and my problem ended up being a misconfigured CloudFomation template. An AWS::SQS::QueuePolicy is required to give your SNS topic permission to send messages to the queue.
"SQSQueuePolicy": {
"Properties": {
"PolicyDocument": {
"Id": "usecase1",
"Statement": [
{
"Action": "SQS:SendMessage",
"Condition": {
"ArnEquals": {
"aws:SourceArn": {
"Ref": "SnsTopic"
}
}
},
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Resource": {
"Fn::GetAtt": [
"SqsQueue",
"Arn"
]
},
"Sid": "1"
}
],
"Version": "2012-10-17"
},
"Queues": [
{
"Ref": "SqsQueue"
}
]
},
"Type": "AWS::SQS::QueuePolicy"
}
You need to Subscribe to endpoint for this to work.
Read the value for SubscribeURL and visit that URL. To confirm the subscription and start receiving notifications at the endpoint, you must visit the SubscribeURLURL (for example, by sending an HTTP GET request to the URL)
When you visit the URL, you will get back a response that looks like the following XML document. The document returns the subscription ARN for the endpoint within the ConfirmSubscriptionResult element.
<ConfirmSubscriptionResponse xmlns="http://sns.amazonaws.com/doc/2010-03-31/">
<ConfirmSubscriptionResult>
<SubscriptionArn>arn:aws:sns:us-west-2:123456789012:MyTopic:2bcfbf39-05c3-41de-beaa-fcfcc21c8f55</SubscriptionArn>
</ConfirmSubscriptionResult>
<ResponseMetadata>
<RequestId>075ecce8-8dac-11e1-bf80-f781d96e9307</RequestId>
</ResponseMetadata>
</ConfirmSubscriptionResponse>
As an alternative to visiting the SubscribeURL, you can confirm the subscription using the ConfirmSubscription action with the Token set to its corresponding value in the SubscriptionConfirmation message. If you want to allow only the topic owner and subscription owner to be able to unsubscribe the endpoint, you call the ConfirmSubscription action with an AWS signature.
You can Refer to this AWS Documentation
Hope this Helps!