I am trying write the logs of a lambda function into a CloudWatch Log Group created by terraform.
This is the lambda policy json -
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1580216411252",
"Action": [
"logs:CreateLogStream",
"logs:CreateLogDelivery",
"logs:PutLogEvents"
],
"Effect": "Allow",
"Resource": "arn:aws:logs:*:*:*"
}
]
}
This is the lambda assume policy json -
{
"Version": "2012-10-17",
"Statement": [{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}]
}
I have added this to the lambda.tf file -
resource "aws_cloudwatch_log_group" "example" {
name = "/test/logs/${var.lambda_function_name}"
}
Although the CloudWatch Log Group '/test/logs/${var.lambda_function_name}' is getting created through terraform, I am unable to write the log of the lambda function to this group.
If I change the lambda policy json to this -
{
"Version": "2012-10-17",
"Statement": [{
"Sid": "Stmt1580204738067",
"Action": "logs:*",
"Effect": "Allow",
"Resource": "*"
}]
}
Then It automatically stores the log in /aws/lambda/ directory.
How can I make sure that the lambda logs get written into a CloudWatch Log Group that I create and not in the /aws/lambda/ group created by lambda itself?
If you want Terraform to manage the CloudWatch log group, you have to create the log group ahead of time with the exact name the Lambda function is going to use for its log group. You can't change the name at all. Then in your Terraform you need to make the log group a dependency of the Lambda function, to make sure Terraform has a chance to create the log group before Lambda creates it automatically.
Just adding the log group as a dependency to the lambda is not enough. You also have to attach the IAM policy to the lambda role.
The steps are following:
Define the IAM role for lambda:
resource "aws_iam_role" "iam_for_lambda" {
name = "iam_for_lambda"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}]
}
EOF
}
Define the IAM policy that allows lambda to create log streams and put log events
resource "aws_iam_policy" "function_logging_policy" {
name = "function-logging-policy"
policy = jsonencode({
"Version" : "2012-10-17",
"Statement" : [
{
Action : [
"logs:CreateLogStream",
"logs:PutLogEvents"
],
Effect : "Allow",
Resource : "arn:aws:logs:*:*:*"
}
]
})
}
Attach the policy to the IAM role created in step 1, by creating new resource 'aws_iam_role_policy_attachment'
resource "aws_iam_role_policy_attachment" "function_logging_policy_attachment" {
role = aws_iam_role.iam_for_lambda.id
policy_arn = aws_iam_policy.function_logging_policy.arn
}
Define the log group
resource "aws_cloudwatch_log_group" "lambda_log_group" {
name = "/aws/lambda/${var.lambda.function_name}"
retention_in_days = 7
lifecycle {
prevent_destroy = false
}
}
Define your lambda function with the depends_on parameter:
resource "aws_lambda_function" "lambda_function" {
filename = "../${var.lambda.function_filename}"
function_name = "${var.lambda.function_name}"
role = aws_iam_role.iam_for_lambda.arn
handler = "${var.lambda.handler}"
layers = [aws_lambda_layer_version.lambda_layer.arn]
depends_on = [aws_cloudwatch_log_group.lambda_log_group]
source_code_hash = filebase64sha256("../${var.lambda.function_filename}")
runtime = "python3.9"
}
The IAM policy creation & attachment comes from this article, the rest is from my personal project that worked for me.
Related
In API Gateway, Im having some issues getting "Aws Services" to show as an option in Integration Type when creating a method within a proxy resource. I can see that this is showing up for normal resource when I don't select the "proxy" checkbox, but if I check that box, and create a get method within the proxy resource, then I don't see that option.
Proxy resources only support HTTP or Lambda integrations.
Here is how you can do this without using a proxy resource: https://aws.amazon.com/premiumsupport/knowledge-center/api-gateway-proxy-integrate-service/
Here is how I got it working with proxy resource (NOTE: Im using TF for the IaC):
Then for the policy and role:
resource "aws_iam_policy" "s3_policy" {
name = "s3-policy"
description = "Policy for allowing all S3 Actions"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::${local.bucket_name}-root/*"
}
]
}
EOF
}
resource "aws_iam_role" "s3_api_gateyway_role" {
name = "s3-api-gateyway-role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "apigateway.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
}
resource "aws_iam_role_policy_attachment" "s3_policy_attach" {
role = aws_iam_role.s3_api_gateyway_role.name
policy_arn = aws_iam_policy.s3_policy.arn
}
Problem
I'm trying to enable audit logging on an AWS redshift cluster. I've been following the instructions provided by AWS here: https://docs.aws.amazon.com/redshift/latest/mgmt/db-auditing.html#db-auditing-enable-logging
Current Configuration
I've defined the relevant IAM role as follows
resource "aws_iam_role" "example-role" {
name = "example-role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "redshift.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
And have granted the following IAM permissions to the example-role role:
{
"Sid": "AllowAccessForAuditLogging",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetBucketAcl"
],
"Resource": [
"arn:aws:s3:::example-bucket",
"arn:aws:s3:::example-bucket/*"
]
},
The relevant portion of the redshift cluster configuration is as follows:
resource "aws_redshift_cluster" "example-cluster-name" {
cluster_identifier = "example-cluster-name"
...
# redshift audit logging to S3
logging {
enable = true
bucket_name = "example-bucket-name"
}
master_username = var.master_username
iam_roles = [aws_iam_role.example-role.arn]
...
Error
terraform plan runs correctly, and produces the expected plan based on the above configuration. However, when running terraform apply the following error occurs:
Error: error enabling Redshift Cluster (example-cluster-name) logging: InsufficientS3BucketPolicyFault: Cannot read ACLs of bucket example-bucket-name. Please ensure that your IAM permissions are set up correctly.
note: i've replaced all resource identifiers with example-* resource names and identifiers.
#shimo's answer is correct. I just detail for someone like me
Redshift has full access to S3. But you need add bucket policy too. ( S3's permission)
{
"Sid": "Statement1",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::361669875840:user/logs"
},
"Action": [
"s3:GetBucketAcl",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::<your-bucket>",
"arn:aws:s3:::<your-bucket>/*"
]
}
- `361669875840` is match with your region check [here][1]
[1]: https://github.com/finos/compliant-financial-infrastructure/blob/main/aws/redshift/redshift_template_public.yml
I always get the error
Invalid operation: Not authorized to get credentials of role arn:aws:iam::xxxxx:role/default_glue_role
I simply want to load from a json from S3 into a Redshift cluster. It is not clear to me what role I have to attach (to Redshift ?).
I have tried attaching the following IAM policy to Redshift
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::xxxxx:role/default_glue_role"
}
}
and also tried with "Resource": "*" but I always get same error.
Thanks for help!
I had a long chat with AWS support about this same issues. A few things to check:
Your s3 bucket region is the same as your redshift cluster region
You are not signed in as the root aws user, you need to create a user with the correct permissions and sign in as this user to run your queries
You should add the following permissions to your user and redshift policies:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:*",
"redshift:*",
"sqlworkbench:*",
"sts:*",
"secretsmanager:*",
"s3-object-lambda:*",
"ec2:*",
"sns:*",
"cloudwatch:*",
"tag:*",
"redshift-data:*",
"sqlworkbench:*",
"redshift-serverless:*"
],
"Resource": "*"
}
]
}
You should have the following trust relationships in your redshift and user role:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"s3.amazonaws.com",
"redshift.amazonaws.com",
"iam.amazonaws.com",
"redshift-serverless.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}
The actual set of permissions you need might be less but this is what worked for me. Took me a long time to figure this out! I hope it helps.
It looks like you might also need to add permissions for glue.
The redshift-serverless permission might tell you it's causing an error but you should be able to save it anyway (AWS told me to do this)
For everyone using Terraform:
What fixed for me it was the (4) suggestion from #patrick-ward:
data "aws_iam_policy_document" "dms_assume_role" {
statement {
actions = ["sts:AssumeRole"]
principals {
identifiers = [
"s3.amazonaws.com",
"redshift.amazonaws.com",
"iam.amazonaws.com",
"redshift-serverless.amazonaws.com",
"dms.amazonaws.com"
]
type = "Service"
}
}
}
resource "aws_iam_role" "dms-access-for-endpoint" {
assume_role_policy = data.aws_iam_policy_document.dms_assume_role.json
name = "dms-access-for-endpoint"
}
resource "aws_iam_role_policy_attachment" "dms-access-for-endpoint-AmazonDMSRedshiftS3Role" {
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonDMSRedshiftS3Role"
role = aws_iam_role.dms-access-for-endpoint.name
}
resource "aws_iam_role" "dms-cloudwatch-logs-role" {
assume_role_policy = data.aws_iam_policy_document.dms_assume_role.json
name = "dms-cloudwatch-logs-role"
}
resource "aws_iam_role_policy_attachment" "dms-cloudwatch-logs-role-AmazonDMSCloudWatchLogsRole" {
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonDMSCloudWatchLogsRole"
role = aws_iam_role.dms-cloudwatch-logs-role.name
}
resource "aws_iam_role" "dms-vpc-role" {
assume_role_policy = data.aws_iam_policy_document.dms_assume_role.json
name = "dms-vpc-role"
}
resource "aws_iam_role_policy_attachment" "dms-vpc-role-AmazonDMSVPCManagementRole" {
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonDMSVPCManagementRole"
role = aws_iam_role.dms-vpc-role.name
}
i have few s3 buckets being used in dev, test and prod environment and i am planning to create a role ( which will allow me to access those s3 buckets and attach the policy ( i.e to list and do some other permission on that buckets present in different envs say dev,test,prod)
i have written this for that -
####################################
## Role Per Service - GO-Service ##
####################################
resource "aws_iam_policy" "go-service" {
name = "go-service-policy"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:ListBucket"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::orbital-go-download-*"
}
]
}
EOF
}
resource "aws_iam_role" "go-service" {
name = "go-service-role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::orbital-go-download-*"
],
"Principal": {
"Service": "s3.amazonaws.com"
}
}
]
}
EOF
}
resource "aws_iam_role_policy_attachment" "go-services-attach" {
role = aws_iam_role.go-service.name
policy_arn = aws_iam_policy.go-service.arn
}
but with this the prob is i might be getting 3 roles getting created ( since we are creating is for 3 k8s clusters say dev,test and prod ) and i need to have one common role which can access all the s3 buckets needed to access the biz service i.e. biz-go-download-{dev,test,prod} bucket.
any help there how would i achieve this requirement , i am new to terraform ? Any suggestion help would be highly appreciated.
Reading through the docs and having a hard time seeing how to associate an aws_iam_role with an aws_iam_policy. Obviously there's aws_iam_role_policy, but that only allows making "inline policies" for a particular role.
Any suggestions?
The aws_iam_policy_attachment resource allows connections to be created between IAM policies and the various other IAM objects.
For example:
resource "aws_iam_role" "foo" {
name = "example-role"
}
resource "aws_iam_policy" "foo" {
name = "example-policy"
description = "An example policy"
policy = "..."
}
resource "aws_iam_policy_attachment" "foo" {
name = "example-attachment"
policy_arn = "${aws_iam_policy.foo.arn}"
roles = ["${aws_iam_role.foo.name}"]
}
Policies can also be attached to users and groups, as illustrated on the Terraform documentation page.
What I've had to do is create a role and a policy and then attach them as shown in an answer by Martin Atkins.
resource "aws_iam_role" "context-builder-role" {
name = "context-builder-role-${terraform.workspace}"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
}
resource "aws_iam_policy" "arm_cfs_sqs_queue_policy" {
name = "starmine-inline-policy-${terraform.workspace}"
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:*:*"
},
{
"Action": [
"sqs:SendMessage",
"sqs:GetQueueUrl",
"sqs:DeleteMessage"
],
"Effect": "Allow",
"Resource": "arn:aws:sqs:*"
}
]
}
EOF
}
resource "aws_iam_role_policy_attachment" "inline-policy-attach" {
role = aws_iam_role.context-builder-role.name
policy_arn = aws_iam_policy.arm_cfs_sqs_queue_policy.arn
}
You can also attach an AWS policy to a role by using the policies ARN:
resource "aws_iam_role_policy_attachment" "s3-read-only-attach" {
role = aws_iam_role.context-builder-role.name
policy_arn = "arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess"
}
Follow the below steps:
Step 1) Create the policy which you want to associate with the aws role.
Step 2) Create aws role as follow:
i. Set role name.
ii. Set role type according to your preference.
iii. Attach the policy which you have created in step1.
iv. Review and create the role.
Hope it helps.......