I'm trying to create a KSM key to use it in the S3 service, but I get the MalformedPolicyDocument exception. Here is the resource:
"CustomerMasterKey":{
"Type" : "AWS::KMS::Key",
"Condition" : "EnableEncryption",
"Properties" : {
"Description" : "Client Master Key used to encrypt data",
"Enabled" : true,
"EnableKeyRotation" : true,
"KeyPolicy" :
{
"Version": "2012-10-17",
"Id": {"Fn::Join": ["",["Key","Policy",{"Ref": "CustomerParam"}]]},
"Statement":
[{
"Sid": "Allow access for Key Administrators",
"Effect": "Allow",
"Principal": {
"AWS": {"Fn::Join": ["",["arn:aws:iam::",{"Ref": "AWS::AccountId"},"moimeco"]]}
},
"Action": [
"kms:Create*",
"kms:Describe*",
"kms:Enable*",
"kms:List*",
"kms:Put*",
"kms:Update*",
"kms:Revoke*",
"kms:Disable*",
"kms:Get*",
"kms:Delete*",
"kms:TagResource",
"kms:UntagResource",
"kms:ScheduleKeyDeletion",
"kms:CancelKeyDeletion"
],
"Resource": "*"
},
{
"Sid": "Allow use of the key",
"Effect": "Allow",
"Principal": {
"AWS":
[
{"Fn::Join": ["",["arn:aws:iam::",{"Ref": "AWS::AccountId"}, {"Ref": "CustomerParam"}]]},
{"Fn::Join": ["",["arn:aws:iam::",{"Ref": "AWS::AccountId"},"userprod"]]}
]
},
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
],
"Resource": "*",
"Condition": {
"StringEquals": {
"kms:ViaService": "s3.eu-west-1.amazonaws.com"
}
}
}]
}
}
},
I don't know where is the error, for me it is all good. Any idea please ?
::EDIT::
This code is giving the same error:
"CustomerMasterKey":{
"Type" : "AWS::KMS::Key",
"Properties" : {
"Description" : "A sample key",
"KeyPolicy" : {
"Version": "2012-10-17",
"Id": {"Fn::Join": ["-",["Key","Policy",{"Ref": "CustomerParam"}]]},
"Statement": [
{
"Sid": "Enable IAM User Permissions",
"Effect": "Allow",
"Principal": {
"AWS": {"Fn::Join": ["", ["arn:aws:iam::",{"Ref": "AWS::AccountId"},":root"]]}
},
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "Allow administration of the key",
"Effect": "Allow",
"Principal": { "AWS": {"Fn::Join": ["",["arn:aws:iam::",{"Ref": "AWS::AccountId"},":user/","userprod"]]} },
"Action": [
"kms:Create*",
"kms:Describe*",
"kms:Enable*",
"kms:List*",
"kms:Put*",
"kms:Update*",
"kms:Revoke*",
"kms:Disable*",
"kms:Get*",
"kms:Delete*",
"kms:ScheduleKeyDeletion",
"kms:CancelKeyDeletion"
],
"Resource": "*"
},
{
"Sid": "Allow use of the key",
"Effect": "Allow",
"Principal": { "AWS": [{"Fn::Join": ["",["arn:aws:iam::",{"Ref": "AWS::AccountId"},":user/",{"Ref": "CustomerParam"}]]},
{"Fn::Join": ["",["arn:aws:iam::",{"Ref": "AWS::AccountId"},":user/","moimeco"]]}]
},
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey"
],
"Resource": "*"
},
{
"Sid": "Allow attachment of persistent resources",
"Effect": "Allow",
"Principal": {
"AWS": {"Fn::Join": ["",["arn:aws:iam::",{"Ref": "AWS::AccountId"},":user/",{"Ref": "CustomerParam"}]]}
},
"Action": [
"kms:CreateGrant",
"kms:ListGrants",
"kms:RevokeGrant"
],
"Resource": "*",
"Condition": {"Bool": {"kms:GrantIsForAWSResource": "true"}}
}
]
}
}
},
The defined principals do not evaluate into Arns.
The first principal would evaluate to:
"AWS": "arn:aws:iam::11111111moimeco"
A valid ARN for a user would look like this:
"arn:aws:iam::1111111:user/username"
Additionally, you need to include the root user into your principals.
Otherwise, AWS wouldn't let you create the key at all. The reason behind this is described here:
AWS Key policies under "Allows Access to the AWS Account and Enables IAM Policies"
(background) Currently I am trying to make a general policy for anyone who needs an account at my company so that they have access to anything they need on AWS except the ability to change their own permissions. The idea there is to give them the managed policy "PowerUserAccess". Also, in their account, they will have an S3 bucket with billing permissions, "arn:aws:s3:::c3-uits-s3".
(problem) I have try to make this s3 bucket read only, so that they can see/download their billing, but not be able to upload/delete from the bucket. My first attempt was to
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"NotAction": "iam:*",
"Resource": "*"
},
{
"Effect": "Deny",
"NotAction": [
"s3:List*",
"s3:Get*"
],
"Resource": [
"arn:aws:s3:::c3-uits-s3"
]
}
]
}
deny every action but Get* and List* but with those permissions I was still able to upload/delete, so I tried to get only the necessary permissions from there to only view and do nothing else and I came up with
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"NotAction": "iam:*",
"Resource": "*"
},
{
"Effect": "Deny",
"NotAction": [
"s3:ListBucket",
"s3:GetBucketLocation"
],
"Resource": [
"arn:aws:s3:::c3-uits-s3"
]
}
]
}
Which still had the same effect of being able to upload/delete. Another variation I tried was
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"NotAction": [
"iam:*",
"s3:*"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"NotResource": [
"arn:aws:s3:::c3-uits-s3"
]
},
{
"Effect": "Allow",
"Action": [
"s3:List*",
"s3:Get*"
],
"Resource": [
"arn:aws:s3:::c3-uits-s3"
]
}
]
}
and
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"NotAction": "iam:*",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"s3:List*",
"s3:Get*"
],
"Resource": [
"arn:aws:s3:::c3-uits-s3"
]
},
{
"Effect": "Deny",
"Action": [
"s3:Put*",
"s3:Create*",
"s3:Delete*",
"s3:Replicate*"
],
"Resource": [
"arn:aws:s3:::c3-uits-s3"
]
}
]
}
any help or pointers in the right direction would be greatly appreciated!
The Resource for a bucket is "arn:aws:s3:::bucket-name" but the Resource for the objects in a bucket is "arn:aws:s3:::bucket-name/*".
You aren't denying any operations on objects, here.
IAM policy are complicated beasts. It would be nice to add a comment when crafting them. For example,
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1422979261000",
"Effect": "Allow",
"Action": [
"route53:ListHostedZones",
],
"Comment": "Foo"
# or Bar
"Resource": [
"*"
]
}
]
}
Neither of these work. Does there exist a way to add comments to these policies?
Hyper Anthony's answer is correct in the strict sense of 'comment' - however, in most situations you can at least use the Sid for pseudo comments to communicate the intent or any constraints etc.:
The Sid (statement ID) is an optional identifier that you provide for the policy statement. You can assign a Sid value to each statement in a statement array. In services that let you specify an ID element, such as SQS and SNS, the Sid value is just a sub-ID of the policy document's ID. In IAM, the Sid value must be unique within a policy. [emphasis mine]
This is e.g. exemplified by the use of TheseActionsSupportResourceLevelPermissions within the (very helpful) AWS blog post Demystifying EC2 Resource-Level Permissions:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "TheseActionsSupportResourceLevelPermissions",
"Effect": "Allow",
"Action": [
"ec2:RunInstances",
"ec2:TerminateInstances",
"ec2:StopInstances",
"ec2:StartInstances"
],
"Resource": "arn:aws:ec2:us-east-1:accountid:instance/*"
}
]
}
As mentioned in Sid some services might require this element and have uniqueness requirements for it, but I haven't experienced resulting naming constraints yet.
No. In general, comments as you describe them are not allowed in JSON. To effectively create a comment, you would need to allow for a new element that describes comments. Since AWS is the master of this json object, they would be responsible for allowing this.
They currently only allow the following elements:
Version
Id
Statement
Sid
Effect
Principal
NotPrincipal
Action
NotAction
Resource
NotResource
Condition
JSON doesn't support comment. but we can add 'Sid:' as a comment to categorize multiple service policies inside one single policy. below i am uploading single json policy for Ec2, S3, Lambda, ElasticBeanStalk services.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "EC2FullAccess",
"Action": "ec2:*",
"Effect": "Allow",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "elasticloadbalancing:*",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "cloudwatch:*",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "autoscaling:*",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "iam:CreateServiceLinkedRole",
"Resource": "*",
"Condition": {
"StringEquals": {
"iam:AWSServiceName": [
"autoscaling.amazonaws.com",
"ec2scheduled.amazonaws.com",
"elasticloadbalancing.amazonaws.com",
"spot.amazonaws.com",
"spotfleet.amazonaws.com",
"transitgateway.amazonaws.com"
]
}
}
},
{
"Sid": "S3FullAccess",
"Effect": "Allow",
"Action": [
"s3:*",
"s3-object-lambda:*"
],
"Resource": "*"
},
{
"Sid": "LambdaFullAccess",
"Effect": "Allow",
"Action": [
"cloudformation:DescribeStacks",
"cloudformation:ListStackResources",
"cloudwatch:ListMetrics",
"cloudwatch:GetMetricData",
"ec2:DescribeSecurityGroups",
"ec2:DescribeSubnets",
"ec2:DescribeVpcs",
"kms:ListAliases",
"iam:GetPolicy",
"iam:GetPolicyVersion",
"iam:GetRole",
"iam:GetRolePolicy",
"iam:ListAttachedRolePolicies",
"iam:ListRolePolicies",
"iam:ListRoles",
"lambda:*",
"logs:DescribeLogGroups",
"states:DescribeStateMachine",
"states:ListStateMachines",
"tag:GetResources",
"xray:GetTraceSummaries",
"xray:BatchGetTraces"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "*",
"Condition": {
"StringEquals": {
"iam:PassedToService": "lambda.amazonaws.com"
}
}
},
{
"Effect": "Allow",
"Action": [
"logs:DescribeLogStreams",
"logs:GetLogEvents",
"logs:FilterLogEvents"
],
"Resource": "arn:aws:logs:*:*:log-group:/aws/lambda/*"
},
{
"Effect": "Allow",
"Action": [
"acm:Describe*",
"acm:List*",
"autoscaling:Describe*",
"cloudformation:Describe*",
"cloudformation:Estimate*",
"cloudformation:Get*",
"cloudformation:List*",
"cloudformation:Validate*",
"cloudtrail:LookupEvents",
"cloudwatch:DescribeAlarms",
"cloudwatch:GetMetricStatistics",
"cloudwatch:ListMetrics",
"codecommit:Get*",
"codecommit:UploadArchive",
"ec2:AllocateAddress",
"ec2:AssociateAddress",
"ec2:AuthorizeSecurityGroup*",
"ec2:CreateLaunchTemplate*",
"ec2:CreateSecurityGroup",
"ec2:CreateTags",
"ec2:DeleteLaunchTemplate*",
"ec2:DeleteSecurityGroup",
"ec2:DeleteTags",
"ec2:Describe*",
"ec2:DisassociateAddress",
"ec2:ReleaseAddress",
"ec2:RevokeSecurityGroup*",
"ecs:CreateCluster",
"ecs:DeRegisterTaskDefinition",
"ecs:Describe*",
"ecs:List*",
"ecs:RegisterTaskDefinition",
"elasticbeanstalk:*",
"elasticloadbalancing:Describe*",
"iam:GetRole",
"iam:ListAttachedRolePolicies",
"iam:ListInstanceProfiles",
"iam:ListRolePolicies",
"iam:ListRoles",
"iam:ListServerCertificates",
"logs:Describe*",
"rds:Describe*",
"s3:ListAllMyBuckets",
"sns:ListSubscriptionsByTopic",
"sns:ListTopics",
"sqs:ListQueues"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"autoscaling:*"
],
"Resource": [
"arn:aws:autoscaling:*:*:launchConfiguration:*:launchConfigurationName/awseb-e-*",
"arn:aws:autoscaling:*:*:launchConfiguration:*:launchConfigurationName/eb-*",
"arn:aws:autoscaling:*:*:autoScalingGroup:*:autoScalingGroupName/awseb-e-*",
"arn:aws:autoscaling:*:*:autoScalingGroup:*:autoScalingGroupName/eb-*"
]
},
{
"Effect": "Allow",
"Action": [
"cloudformation:CancelUpdateStack",
"cloudformation:ContinueUpdateRollback",
"cloudformation:CreateStack",
"cloudformation:DeleteStack",
"cloudformation:GetTemplate",
"cloudformation:ListStackResources",
"cloudformation:SignalResource",
"cloudformation:TagResource",
"cloudformation:UntagResource",
"cloudformation:UpdateStack"
],
"Resource": [
"arn:aws:cloudformation:*:*:stack/awseb-*",
"arn:aws:cloudformation:*:*:stack/eb-*"
]
},
{
"Effect": "Allow",
"Action": [
"cloudwatch:DeleteAlarms",
"cloudwatch:PutMetricAlarm"
],
"Resource": [
"arn:aws:cloudwatch:*:*:alarm:awseb-*",
"arn:aws:cloudwatch:*:*:alarm:eb-*"
]
},
{
"Effect": "Allow",
"Action": [
"codebuild:BatchGetBuilds",
"codebuild:CreateProject",
"codebuild:DeleteProject",
"codebuild:StartBuild"
],
"Resource": "arn:aws:codebuild:*:*:project/Elastic-Beanstalk-*"
},
{
"Effect": "Allow",
"Action": [
"dynamodb:CreateTable",
"dynamodb:DeleteTable",
"dynamodb:DescribeTable",
"dynamodb:TagResource"
],
"Resource": [
"arn:aws:dynamodb:*:*:table/awseb-e-*",
"arn:aws:dynamodb:*:*:table/eb-*"
]
},
{
"Effect": "Allow",
"Action": [
"ec2:RebootInstances",
"ec2:TerminateInstances"
],
"Resource": "arn:aws:ec2:*:*:instance/*",
"Condition": {
"StringLike": {
"ec2:ResourceTag/aws:cloudformation:stack-id": [
"arn:aws:cloudformation:*:*:stack/awseb-e-*",
"arn:aws:cloudformation:*:*:stack/eb-*"
]
}
}
},
{
"Effect": "Allow",
"Action": "ec2:RunInstances",
"Resource": "*",
"Condition": {
"ArnLike": {
"ec2:LaunchTemplate": "arn:aws:ec2:*:*:launch-template/*"
}
}
},
{
"Effect": "Allow",
"Action": [
"ecs:DeleteCluster"
],
"Resource": "arn:aws:ecs:*:*:cluster/awseb-*"
},
{
"Effect": "Allow",
"Action": [
"elasticloadbalancing:*Rule",
"elasticloadbalancing:*Tags",
"elasticloadbalancing:SetRulePriorities",
"elasticloadbalancing:SetSecurityGroups"
],
"Resource": [
"arn:aws:elasticloadbalancing:*:*:loadbalancer/app/*/*",
"arn:aws:elasticloadbalancing:*:*:listener/app/*/*/*",
"arn:aws:elasticloadbalancing:*:*:listener-rule/app/*/*/*/*"
]
},
{
"Effect": "Allow",
"Action": [
"elasticloadbalancing:*"
],
"Resource": [
"arn:aws:elasticloadbalancing:*:*:targetgroup/awseb-*",
"arn:aws:elasticloadbalancing:*:*:targetgroup/eb-*",
"arn:aws:elasticloadbalancing:*:*:loadbalancer/awseb-*",
"arn:aws:elasticloadbalancing:*:*:loadbalancer/eb-*",
"arn:aws:elasticloadbalancing:*:*:loadbalancer/*/awseb-*/*",
"arn:aws:elasticloadbalancing:*:*:loadbalancer/*/eb-*/*",
"arn:aws:elasticloadbalancing:*:*:listener/awseb-*",
"arn:aws:elasticloadbalancing:*:*:listener/eb-*",
"arn:aws:elasticloadbalancing:*:*:listener/*/awseb-*/*/*",
"arn:aws:elasticloadbalancing:*:*:listener/*/eb-*/*/*",
"arn:aws:elasticloadbalancing:*:*:listener-rule/app/awseb-*/*/*/*",
"arn:aws:elasticloadbalancing:*:*:listener-rule/app/eb-*/*/*/*"
]
},
{
"Effect": "Allow",
"Action": [
"iam:AddRoleToInstanceProfile",
"iam:CreateInstanceProfile",
"iam:CreateRole"
],
"Resource": [
"arn:aws:iam::*:role/aws-elasticbeanstalk*",
"arn:aws:iam::*:instance-profile/aws-elasticbeanstalk*"
]
},
{
"Effect": "Allow",
"Action": [
"iam:AttachRolePolicy"
],
"Resource": "arn:aws:iam::*:role/aws-elasticbeanstalk*",
"Condition": {
"StringLike": {
"iam:PolicyArn": [
"arn:aws:iam::aws:policy/AWSElasticBeanstalk*",
"arn:aws:iam::aws:policy/service-role/AWSElasticBeanstalk*"
]
}
}
},
{
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "arn:aws:iam::*:role/*",
"Condition": {
"StringEquals": {
"iam:PassedToService": [
"elasticbeanstalk.amazonaws.com",
"ec2.amazonaws.com",
"ec2.amazonaws.com.cn",
"autoscaling.amazonaws.com",
"elasticloadbalancing.amazonaws.com",
"ecs.amazonaws.com",
"cloudformation.amazonaws.com"
]
}
}
},
{
"Effect": "Allow",
"Action": [
"iam:CreateServiceLinkedRole"
],
"Resource": [
"arn:aws:iam::*:role/aws-service-role/autoscaling.amazonaws.com/AWSServiceRoleForAutoScaling*",
"arn:aws:iam::*:role/aws-service-role/elasticbeanstalk.amazonaws.com/AWSServiceRoleForElasticBeanstalk*",
"arn:aws:iam::*:role/aws-service-role/elasticloadbalancing.amazonaws.com/AWSServiceRoleForElasticLoadBalancing*",
"arn:aws:iam::*:role/aws-service-role/managedupdates.elasticbeanstalk.amazonaws.com/AWSServiceRoleForElasticBeanstalk*",
"arn:aws:iam::*:role/aws-service-role/maintenance.elasticbeanstalk.amazonaws.com/AWSServiceRoleForElasticBeanstalk*"
],
"Condition": {
"StringLike": {
"iam:AWSServiceName": [
"autoscaling.amazonaws.com",
"elasticbeanstalk.amazonaws.com",
"elasticloadbalancing.amazonaws.com",
"managedupdates.elasticbeanstalk.amazonaws.com",
"maintenance.elasticbeanstalk.amazonaws.com"
]
}
}
},
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:DeleteLogGroup",
"logs:PutRetentionPolicy"
],
"Resource": "arn:aws:logs:*:*:log-group:/aws/elasticbeanstalk/*"
},
{
"Effect": "Allow",
"Action": [
"rds:*DBSubnetGroup",
"rds:AuthorizeDBSecurityGroupIngress",
"rds:CreateDBInstance",
"rds:CreateDBSecurityGroup",
"rds:DeleteDBInstance",
"rds:DeleteDBSecurityGroup",
"rds:ModifyDBInstance",
"rds:RestoreDBInstanceFromDBSnapshot"
],
"Resource": [
"arn:aws:rds:*:*:db:*",
"arn:aws:rds:*:*:secgrp:awseb-e-*",
"arn:aws:rds:*:*:secgrp:eb-*",
"arn:aws:rds:*:*:snapshot:*",
"arn:aws:rds:*:*:subgrp:awseb-e-*",
"arn:aws:rds:*:*:subgrp:eb-*"
]
},
{
"Effect": "Allow",
"Action": [
"s3:Delete*",
"s3:Get*",
"s3:Put*"
],
"Resource": "arn:aws:s3:::elasticbeanstalk-*/*"
},
{
"Effect": "Allow",
"Action": [
"s3:CreateBucket",
"s3:GetBucket*",
"s3:ListBucket",
"s3:PutBucketPolicy"
],
"Resource": "arn:aws:s3:::elasticbeanstalk-*"
},
{
"Effect": "Allow",
"Action": [
"sns:CreateTopic",
"sns:DeleteTopic",
"sns:GetTopicAttributes",
"sns:Publish",
"sns:SetTopicAttributes",
"sns:Subscribe",
"sns:Unsubscribe"
],
"Resource": "arn:aws:sns:*:*:ElasticBeanstalkNotifications-*"
},
{
"Effect": "Allow",
"Action": [
"sqs:*QueueAttributes",
"sqs:CreateQueue",
"sqs:DeleteQueue",
"sqs:SendMessage",
"sqs:TagQueue"
],
"Resource": [
"arn:aws:sqs:*:*:awseb-e-*",
"arn:aws:sqs:*:*:eb-*"
]
}
]
}