AWS Backupvault SNS notification - aws-cloudformation

I have created a backup plan and configured SNS using cloud formation ( not CLI ), but backup job has running and completed successfully but not receiving emails notification ( already subscribe to the SNS topic ).
Backup vault section in cloudformation :
BackupVaultWithDailyBackupssns:
Type: "AWS::Backup::BackupVault"
Properties:
BackupVaultName: "Vault_name"
Notifications:
BackupVaultEvents:
- BACKUP_JOB_STARTED
- BACKUP_JOB_COMPLETED
- BACKUP_JOB_SUCCESSFUL
- BACKUP_JOB_FAILED
SNSTopicArn:
!Sub 'arn:aws:sns:${AWS::Region}:${AWS::AccountId}:My_topic'
SNS Policy :
{
"Version": "2008-10-17",
"Id": "__default_policy_ID",
"Statement": [
{
"Sid": "__default_statement_ID",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": [
"SNS:GetTopicAttributes",
"SNS:SetTopicAttributes",
"SNS:AddPermission",
"SNS:RemovePermission",
"SNS:DeleteTopic",
"SNS:Subscribe",
"SNS:ListSubscriptionsByTopic",
"SNS:Publish",
"SNS:Receive"
],
"Resource": "arn:aws:sns:us-east-1:111111111111:My_topic",
"Condition": {
"StringEquals": {
"AWS:SourceOwner": "111111111"
}
}
},
{
"Sid": "My-statement-id",
"Effect": "Allow",
"Principal": {
"Service": "backup.amazonaws.com"
},
"Action": "SNS:Publish",
"Resource": "arn:aws:sns:us-east-1:111111111111:My_topic"
}
]
}

For anyone looking for an answer on this here I how I set mine up, this is working for all failed notifications.
Set up your vault referencing a topic
BackupVault:
Type: "AWS::Backup::BackupVault"
Properties:
BackupVaultName: Backup Vault Name
Notifications:
BackupVaultEvents:
- "BACKUP_JOB_EXPIRED"
- "BACKUP_JOB_FAILED"
SNSTopicArn: !Ref FailedBackupTopic
DependsOn:
- FailedBackupTopic
Set up a topic, topic policy and topic subscription
FailedBackupTopic:
Type: AWS::SNS::Topic
Properties:
DisplayName: "AWS Backup - Failed backup notification"
FailedBackupTopicPolicy:
Type: 'AWS::SNS::TopicPolicy'
Properties:
PolicyDocument:
Id: SNSPolicyV1
Version: '2012-10-17'
Statement:
- Sid: Sid1
Effect: Allow
Principal:
Service:
- 'backup.amazonaws.com'
Action: 'sns:Publish'
Resource: !Ref FailedBackupTopic
Topics:
- !Ref FailedBackupTopic
FailedBackupTopicSubscription:
Type: 'AWS::SNS::Subscription'
Properties:
Endpoint: "email#email.com"
Protocol: email
TopicArn: !Ref FailedBackupTopic

Related

Serverless cfn resource references not resolving

I'm new to serverless, and trying to create a deployment using the Serverless 3 framework. I currently have some resources defined with references to other cfn resources that I've defined in my template, i.e.:
WebsiteBucketPolicy:
Type: AWS::S3::BucketPolicy
DependsOn:
- CloudFrontOriginAccessIdentity
- WebsiteBucket
Properties:
Bucket: WebsiteBucket
PolicyDocument:
Statement:
- Sid: PublicReadGetObject
Effect: Allow
Principal:
AWS:
Fn::Join: [ ' ', [ 'arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity', CloudFrontOriginAccessIdentity ] ]
Action:
- s3:GetObject
Resource:
- Fn::Join: [ '', [ 'arn:aws:s3:::', WebsiteBucket, '/*' ] ]
However, I keep getting cfn errors when I deploy as it seems that the references to these resources aren't resolving. I tried looking at the serverless-state.json output file to troubleshoot, and I see them defined as follows, for example:
"WebsiteBucketPolicy": {
"Type": "AWS::S3::BucketPolicy",
"DependsOn": [
"CloudFrontOriginAccessIdentity",
"WebsiteBucket"
],
"Properties": {
"Bucket": "WebsiteBucket",
"PolicyDocument": {
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": {
"AWS": {
"Fn::Join": [
" ",
[
"arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity",
"CloudFrontOriginAccessIdentity"
]
]
}
},
"Action": [
"s3:GetObject"
],
"Resource": [
{
"Fn::Join": [
"",
[
"arn:aws:s3:::",
"WebsiteBucket",
"/*"
]
]
}
]
}
]
}
}
},
Am I referencing these incorrectly in my template?
To reference the resource correctly you need to use the Ref function:
Bucket: !Ref WebsiteBucket
Two more notes regarding your template:
You can omit the DependsOn section in this case as you are referencing all the resources you are waiting for. When using Ref, CloudFormation automatically creates the resources in the correct order (in this case it is Bucket and Access Identity first, Bucket Policy last)
Instead of using Join for combining strings and parameters, you can also use the Sub function which returns referenced values written like ${WebsiteBucket}, just as Ref/GetAtt does.
Template:
WebsiteBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref WebsiteBucket
PolicyDocument:
Statement:
- Sid: PublicReadGetObject
Effect: Allow
Principal:
AWS:
Fn::Join: [ ' ', [ 'arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity', !Ref CloudFrontOriginAccessIdentity ] ]
Action:
- s3:GetObject
Resource:
- !Sub arn:aws:s3:::${WebsiteBucket}/*
# OR:
# - Fn::Join: [ '', [ 'arn:aws:s3:::', !Ref WebsiteBucket, '/*' ] ]

Cloudformation to covert string into list on apigateway policy document with condition

Below is the my cloudformation template. I want to convert aws:SourceVpc into list in the resource policy document. I tried with spilt but cft below error.
Invalid policy document. Please check the policy syntax and ensure that Principals are valid. (Service: AmazonApiGateway; Status Code: 400; Error Code: BadRequestException; Request ID: xxxxx; Proxy: null)
Also devl and sdbx have 1 value where as others acnt and acpt have two values in mappings how can do it. Please suggest.
Output should like below.
aws:SourceVpc: ["vpc-7830jkd", "vpc-a1236"]
Mappings:
vpcid:
us-east-1:
sdbx: "vpc-1234"
devl: "vpc-2345"
acpt: "vpc-7830jkd,vpc-a1236"
us-east-2:
acnt: "vpc-a1236,vpc-7830jkd"
Parameters:
Env:
Type: String
Resources:
apigateway:
Type: "AWS::ApiGateway::RestApi"
Properties:
Name: mygateway
EndpointConfiguration:
Types:
- "PRIVATE"
Policy: !Sub
- |-
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "execute-api:Invoke",
"Resource": [
"execute-api:/*"
]
},
{
"Effect": "Deny",
"Principal": "*",
"Action": "execute-api:Invoke",
"Resource": [
"execute-api:/*"
],
"Condition": {
"StringNotEquals": {
"aws:SourceVpc": !Split ["," , "${myappid}"]
}
}
}
]
}
- { myappid: !FindInMap [ vpcid, !Ref "AWS::Region", !Ref "Env" ] }
Output should like below. aws:SourceVpc: ["vpc-7830jkd", "vpc-a1236"]
Sadly, you can't do this. CFN is very limited in what it can do, and what you want is simply not achievable with plain CFN. You have to modify your Maps and provide all the vpc ids individually, not mix lists with individual values.
The other way would be through development of CFN macro or custom resource.

AWS Cloudformation Error: Policy has invalid resource

I need to create an S3 bucket with public access, but restrict that access to only a specific IP.
I generated a policy using the policy generator for S3 buckets and then adapted it to my template by referencing the name of the bucket; however, CloudFormation keeps giving a "Policy has invalid resource" error.
Below is the relevant portion of the CloudFormation template I am using. "FirstS3BucketName" is the a parameter.
FirstS3BucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref FirstS3BucketName
PolicyDocument: |
{
"Id": "Policy1581542658034",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1581542655517",
"Action": "s3:*",
"Effect": "Allow",
"Resource": "arn:aws:s3:::${FirstS3BucketName}/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": "3.132.69.181/32"
}
},
"Principal": "*"
}
]
}
All you really need to do is add a !Sub on your PolicyDocument line. FYI, all that JSON can be turned into YAML as well.
FirstS3BucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref FirstS3BucketName
PolicyDocument: !Sub |
{
"Id": "Policy1581542658034",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1581542655517",
"Action": "s3:*",
"Effect": "Allow",
"Resource": "arn:aws:s3:::${FirstS3BucketName}/*",
"Condition": {
"IpAddress": {
"aws:SourceIp": "3.132.69.181/32"
}
},
"Principal": "*"
}
]
}

Policy to limit subnets or hosted zone CodeStar can use

Is there an IAM policy that can be created/attached to CodeStarWorker-*-CloudFormation that limits either the Subnets or HostedZoneIds the CodeStar worker can use?
Here's an example template.yml:
Resources:
# other resources
DevAlb:
Properties:
LoadBalancerAttributes: []
Name: !Sub '${ProjectId}-dev-alb'
Scheme: internal
SecurityGroups:
- !Ref AlbSecurityGroup
Subnets:
- !ImportValue PrivateSubnet1
- !ImportValue PrivateSubnet2
Tags:
- Key: Name
Value: !Sub '${ProjectId}-dev'
Type: 'AWS::ElasticLoadBalancingV2::LoadBalancer'
DevAlbDns:
Properties:
AliasTarget:
DNSName: !GetAtt
- AlbDev
- DNSName
HostedZoneId: !GetAtt
- AlbDev
- CanonicalHostedZoneID
HostedZoneId: !ImportValue InternalDomainDotCom
Name: !Sub '${ProjectId}.internal-domain.com'
Type: A
Type: 'AWS::Route53::RecordSet'
I don't want users with CodeStar access to import/use anything that would allow public internet access (without admin approval, anyway). How can I prevent someone from setting/importing PublicSubnet1 and PublicSubnet2 as one of the Subnets? Or prevent them from setting/import PublicDomainDotCom as the HostedZoneId?
I was able to do this by attaching the following policy to CodeStarWorker-app-CloudFormation!
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"route53:GetChange",
"route53:GetHostedZone",
"route53:ListHostedZones",
"route53:ListHostedZonesByName",
"route53:ListResourceRecordSets",
"route53:GetHostedZoneCount",
"route53domains:*"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"route53:ChangeResourceRecordSets",
"route53:ListResourceRecordSets",
"apigateway:GET"
],
"Resource": [
"arn:aws:route53:::hostedzone/REPLACE_WITH_HOSTED_ZONE_ID",
"arn:aws:apigateway:*::/domainnames"
]
}
]
}
This will only allow CodeStar's CloudFormation role to create a Route 53 record set in the hosted zone ID an admin has allowed.
I'm sure there are other ways to protect your infrastructure and data from bad actors with CodeStar roles. Feel free to share if you have any ideas (e.g., limiting EC2 VPCs/Subnets).

Create S3 only user

I am trying to create a S3 only user who will by definition have no access to any other resource. The user can upload and download files from S3. I have created a basic template that can be found here...
https://github.com/shantanuo/aws-cloudformation-templates/blob/master/aws/services/IAM/IAM_Users_Groups_and_Policies.yaml
But it is allowing access to cloudformation that is not necessary in my case. I have read the following pages, but do not know how to include them in my template.
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-iam-user.html
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html
https://docs.aws.amazon.com/AWSCloudForation/latest/UserGuide/aws-properties-iam-group.html
What are the minimum parameters required to create a S3 only user?
Update:
Here is the cloudformation code that I tried and the error that I got:
error message: The following resource(s) failed to create: [CFNRole, CFNUser]. . Rollback requested by user.
The template:
Parameters:
NewUsername:
NoEcho: 'false'
Type: String
Description: New account username
MinLength: '1'
MaxLength: '41'
ConstraintDescription: the username must be between 1 and 41 characters
Password:
NoEcho: 'true'
Type: String
Description: New account password
MinLength: '1'
MaxLength: '41'
ConstraintDescription: the password must be between 1 and 41 characters
Resources:
CFNUser:
Type: AWS::IAM::User
Properties:
LoginProfile:
Password: !Ref 'Password'
UserName : !Ref 'NewUsername'
CFNRole:
Type: AWS::IAM::Role
Properties :
PermissionsBoundary : arn:aws:iam::aws:policy/AmazonS3FullAccess
RoleName : 'myPermissionBoundary'
CFNKeys:
Type: AWS::IAM::AccessKey
Properties:
UserName: !Ref 'CFNUser'
Outputs:
AccessKey:
Value: !Ref 'CFNKeys'
Description: AWSAccessKeyId of new user
SecretKey:
Value: !GetAtt [CFNKeys, SecretAccessKey]
Description: AWSSecretAccessKey of new user
I have checked this link, but not sure how to include the policy in my current template.
https://aws.amazon.com/blogs/security/easier-way-to-control-access-to-aws-regions-using-iam-policies/
You are explicit giving your new user access to Cloudformation in your template.
You have this section:
CFNUserPolicies:
Type: AWS::IAM::Policy
Properties:
PolicyName: CFNUsers
PolicyDocument:
Statement:
- Effect: Allow
Action: ['cloudformation:Describe*', 'cloudformation:List*', 'cloudformation:Get*']
Resource: '*'
Groups: [!Ref 'CFNUserGroup']
CFNAdminPolicies:
Type: AWS::IAM::Policy
Properties:
PolicyName: CFNAdmins
PolicyDocument:
Statement:
- Effect: Allow
Action: cloudformation:*
Resource: '*'
Groups: [!Ref 'CFNAdminGroup']
In which your allow statements specifically provide access to Cloudformation. If you are trying to give access to s3 then why are you giving access to Cloudformation?
If you want a user to have access to s3 only, and going further one specific s3 bucket then your policy would look something like this (note this is in json):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetBucketLocation",
"s3:ListAllMyBuckets"
],
"Resource": "arn:aws:s3:::*"
},
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::YOUR-BUCKET",
"arn:aws:s3:::YOUR-BUCKET/*"
]
}
]
}
If you want your user to have access to all buckets, then your policy would look more like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1557048549844",
"Action": "s3:*",
"Effect": "Allow",
"Resource": "*"
}
]
}
See this source: https://objectivefs.com/howto/how-to-restrict-s3-bucket-policy-to-only-one-aws-s3-bucket