This policy contains the following error: Has prohibited field Principal - json

I am allowing action from only specified range of ip address and denies aceess for rest ip's.
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::510680944440:user/wu-core-dev-auto-start-stop-lambda-invoke"
},
"Action": "sts:AssumeRole",
"Condition": {
"IpAddress": {
"aws:SourceIp": [
"10.38.6.123/24"
]
}
}
}]
}

So, from the official AWS docs we know the following;
Use the Principal element to specify the IAM user, federated user, IAM role, AWS account, AWS service, or other principal entity that is allowed or denied access to a resource. You cannot use the Principal element in an IAM identity-based policy. You can use it in the trust policies for IAM roles and in resource-based policies. Resource-based policies are policies that you embed directly in an IAM resource.
Assuming that answers your question, my proposed solution would be simple;
Remove Principal block from your policy
Add "Resource": "arn:aws:iam::510680944440:user/wu-core-dev-auto-start-stop-lambda-invoke"
More on principals -> AWS docs

Related

Permission Boundary IAM role denying attaching administrator policy

Can anyone point me how to accomplish the instruction below. I am trying to find it playing with roles and policy but I can't find any way to accomplish a granular approach to deny attaching administrator policy and maintaining other IAM rights.
Set an IAM permission boundary on the development IAM role that explicitly denies attaching the administrator policy
You need to combine multiple conditions to achieve this:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "IAMPermissions",
"Effect": "Allow",
"Action": [
"iam:*"
],
"Resource": "*"
},
{
"Sid": "DenyAttachAdministratorPolicy",
"Effect": "Deny",
"Action": [
"iam:AttachRolePolicy"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"iam:PermissionsBoundary": "arn:aws:iam::012345678912:policy/MyPermissionBoundary"
},
"ArnEquals": {
"iam:PolicyARN": "arn:aws:iam::aws:policy/AdministratorAccess"
}
}
}
]
}
(You would need to update the PB ARN mentioned in the policy)
Note that this might not handle other edge cases where a malicious user could potentially attach AdministratorAccess to something else and escalate their privileges (e.g. via a Lambda function or container maybe?).

Why does the Condition Element in AWS API Gateway Resource Policy not trigger?

I'm attempting to understand how the Condition Element in Resource Policies for AWS API-Gateway triggers.
I've tried using SourceIP to block all traffic by allowing only 128.0.0.0/1 and 0.0.0.0/1 but I was able to hit my API from the same IP both times. I've also tried blocking my API with CurrentTime. But nothing I add to my condition seems to stop my ability to call my API. What am I misunderstanding?
My current attempt to block my API from all calls is this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<AccountID>:root"
},
"Action": "execute-api:Invoke",
"Resource": "arn:aws:execute-api:us-west-2:<AccountID>:<API>/*/*",
"Condition": {
"DateGreaterThan": {
"aws:CurrentTime": "2019-12-15T12:00:00Z"
}
}
}
]
}
From my understanding, by stating "DateGreaterThan" "CurrentTime" to December 2019 when it is currently September 2019, this API should not be callable for another three months.
Can someone show me where I'm going off track?
Thank you in advance!
PS: I have correct authorization in the body using AWS PublicKey/SecretKey. I'm just looking to block my call with the condition currently.
PPS: I forgot to mention that I've confirmed my API deployment is utilizing this Resource Policy as my API was rejecting calls before I added my AWS PublicKey/SecreyKey. (I enabled AWS_IAM Authorization)
As Joey Kilpatrick requested, here is my updated (still ineffectual) Resource Policy.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<AccountID>:user/Service_Account"
},
"Action": "execute-api:Invoke",
"Resource": "arn:aws:execute-api:us-west-2:<AccountID>:<API>/*/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": "0.0.0.0/1"
}
}
}
]
}
In this case, i'm hitting the API with a 147.x.x.x IP so I would expect this API to return a 403. I have also tested with the previously stated "CurrentTime" Condition.
I want to first note that restricting SourceIP to 128.0.0.0/1 and 0.0.0.0/1 denies no IP address because every IP is in one of those two CIDR blocks.
But this is not your biggest problem: you cannot restrict any permissions from your root user. This is by design. See why it is a bad idea to use root user here.

How do you dynamically create an AWS IAM policy document with a variable number of resource blocks using terraform?

In my current terraform configuration I am using a static JSON file and importing into terraform using the file function to create an AWS IAM policy.
Terraform code:
resource "aws_iam_policy" "example" {
policy = "${file("policy.json")}"
}
AWS IAM Policy definition in JSON file (policy.json):
{
"Version": "2012-10-17",
"Id": "key-consolepolicy-2",
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111122223333:root"
},
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "Allow use of the key",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::777788889999:root"
]
},
"Action": [
"kms:Decrypt"
],
"Resource": "*"
},
{
"Sid": "Allow use of the key",
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::444455556666:root"
]
},
"Action": [
"kms:Decrypt"
],
"Resource": "*"
}
]
}
My goal is to use a list of account numbers stored in a terraform variable and use that to dynamically build the aws_iam_policy resource in terraform. My first idea was to try and use the terraform jsonencode function. However, it looks like there might be a way to implement this using the new terraform dynamic expressions foreach loop.
The sticking point seems to be appending a variable number of resource blocks in the IAM policy.
Pseudo code below:
var account_number_list = ["123","456","789"]
policy = {"Statement":[]}
for each account_number in account_number_list:
policy["Statement"].append(policy block with account_number var reference)
Any help is appreciated.
Best,
Andrew
The aws_iam_policy_document data source from aws gives you a way to create json policies all in terraform, without needing to import raw json from a file or from a multiline string.
Because you define your policy statements all in terraform, it has the benefit of letting you use looping/filtering on your principals array.
In your example, you could do something like:
data "aws_iam_policy_document" "example_doc" {
statement {
sid = "Enable IAM User Permissions"
effect = "Allow"
actions = [
"kms:*"
]
resources = [
"*"
]
principals {
type = "AWS"
identifiers = [
for account_id in account_number_list:
account_id
]
}
}
statement {
...other statements...
}
}
resource "aws_iam_policy" "example" {
// For terraform >=0.12
policy = data.aws_iam_policy_document.example_doc.json
// For terraform <0.12
policy = "${data.aws_iam_policy_document.example_doc.json}"
}
1st option:
if you don't want to rebuild the policy in aws_iam_policy_document you can use templatefile see https://www.terraform.io/docs/language/functions/templatefile.html
resource "aws_iam_policy" "example" {
policy = templatefile("policy.json",{account_number_list = ["123","456","789"]})
}
...
%{ for account in account_number_list ~}
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::${account}:root"
},
"Action": "kms:*",
"Resource": "*"
},
%{ endfor ~}
...
2nd option:
https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_variables.html#policy-vars-infotouse
AWS's IAM policy document syntax allows for replacement of policy
variables within a statement using ${...}-style notation, which
conflicts with Terraform's interpolation syntax. In order to use AWS
policy variables with this data source, use &{...} notation for
interpolations that should be processed by AWS rather than by
Terraform.
...
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::&{aws:userid}:root"
},
"Action": "kms:*",
"Resource": "*"
},
Like in: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document
This was great and is a good pattern to be able to hold onto. Unfortunately, I ran into an issue with it going up against the quota limit:
Assume Role Policy: LimitExceeded: Cannot exceed quota for ACLSizePerRole: 2048
You can request an increase on this quota size but supposedly the max is 4098. the assume role policy I am attempting to create is needed for every AWS account we have so we will eventually hit that limit as well.
It's unfortunate that you can use wild cards within arns of an assume role policy but you can use "*" which I would argue is much much riskier.

Amazon S3 bucket policy allow access to ONLY specific http

I'm trying to restrict access to objects (media files) in an Amazon S3 bucket to a specific referral domain, privatewebsite.com, with a bucket policy, but keep getting access denied, no matter the domain referred.
I have the following settings for Block Public Access
Block public access to buckets and objects granted through new access control lists (ACLs) - On
Block public access to buckets and objects granted through any access control lists (ACLs) - On
Block public access to buckets and objects granted through new public bucket policies - Off
Block public and cross-account access to buckets and objects through any public bucket policies - Off
I've added the following code, URL with and without, http:// and https://, yet still get access denied. (privatewebsite.com, https://privatewebsite.com, http://privatewebsite.com)
{
"Version": "2012-10-17",
"Id": "Policy8675309",
"Statement": [
{
"Sid": "Stmt8675309",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-media-bucket/*",
"Condition": {
"StringLike": {
"aws:Referer": "https://privatewebsite.com"
}
}
},
{
"Sid": "Explicit deny to ensure requests are allowed only from specific referer.",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": "arn:aws:s3:::my-media-bucket/*",
"Condition": {
"StringNotLike": {
"aws:Referer": [
"https://privatewebsite.com/*",
"http://privatewebsite.com/*"
]
}
}
}
]
}
Can anyone see any obvious errors in my bucket policy?
I expect this policy to ALLOW any request, when coming from a page on privatewebsite.com, while DENY-ing all other requests, but at the moment ALL requests are denied.
From Bucket Policy Examples - Restricting Access to a Specific HTTP Referrer:
{
"Version": "2012-10-17",
"Id": "http referer policy example",
"Statement": [
{
"Sid": "Allow get requests originating from www.example.com and example.com.",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::examplebucket/*",
"Condition": {
"StringLike": {
"aws:Referer": [
"http://www.example.com/*",
"http://example.com/*"
]
}
}
}
]
}
This method only grants Allow access for the given Referer. There is no need to use a Deny policy with it because access is denied by default. Thus, only the Allow permissions are granted.
Try this for you string-like section (allow section):
"StringLike": {
"aws:Referer": [
"https://privatewebsite.com/*",
"http://privatewebsite.com/*"
]
}

Cloudwatch and Cloudformation AWS

is it currently possible to set up a whole cloudwatch stack including the cloudwatch agent via cloudformation ? I cant find a proper documentation and asking myself if its even possible.
Yes these types are available in CloudFormation
AWS::CloudWatch::Alarm
AWS::CloudWatch::Dashboard
Additionally, detailed monitoring can be set in other resource types (for example AWS::EC2::Instance)
Installing the Cloudwatch log agent would be done by configuring it in the AMI or installing as an action in the user data script
The following CloudFormation Resource creates a policy that will allow instances with this policy attached to their role to ship logs to CloudWatch:
"CloudWatchLogsPolicy": {
"Type" : "AWS::IAM::Policy",
"Properties" : {
"PolicyDocument" : {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
"logs:DescribeLogStreams"
],
"Resource": arn:aws:logs:eu-west-1:123456789012:log-group:my-log-group:*
}
]
}
,
"PolicyName" : "CWLogPolicy",
"Roles": [{ "Ref": "IAMRole"}]
},
"DependsOn": ["IAMRole"]
}
You will need to update the Resource ARN to match your region, account id and log group name. The "Roles" and "DependsOn" assume there is an IAM role declared called "IAMRole" in the current stack.
When attaching a Role you have to use an AWS::IAM::InstanceProfile to create the link between the AWS::IAM::Role and the instance (or Autoscale group in my case).