My setup is as follows:
iam user --> iam user group --> assume role group policy --> eks cluster role --> eks role bindings
So, I have an assume role policy:
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Sid = ""
Principal = {
AWS = "arn:aws:iam::xxxxxxxxxxxxx:root"
}
},
]
Then I have a user group, with the following group policy:
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = [
"sts:AssumeRole",
]
Sid = "AllowAssumeOrganizationAccountRole"
Effect = "Allow"
Resource = "arn:aws:iam::xxxxxxxxxxxx:role/ro-k8s-role"
},
]
I then have the following cluster role for EKS:
rule {
api_groups = ["apps", "batch", "extensions"]
resources = ["pods", "deployments", "statefulsets", "events", "services", "pods/log", "pods/portforward"]
verbs = ["get", "list", "watch", "describe"]
}
And then a bunch of role bindings which are used for a list of namespaces:
metadata {
name = "k8s-ro-${each.value}"
namespace = each.value
}
role_ref {
api_group = "rbac.authorization.k8s.io"
kind = "Role"
name = "k8s-ro"
}
subject {
kind = "User"
name = "k8s-user"
api_group = "rbac.authorization.k8s.io"
}
If I then use the profile of a user in the group, and check the caller-identity...
{
"UserId": "XXXXXXXXXXXXXXXXXX",
"Account": "xxxxxxxxxxxxxxx",
"Arn": "arn:aws:iam::xxxxxxxxxxxxx:user/test-user"
}
I would expect to see the assume role here, right? Which explains why I can't view anything running on the cluster.
I'll close this as the initial problem is resolved. I hadn't properly configured the AWS Profiles to automatically handle the assume role. Which having done has resolved this issue.
~/.aws/config
[profile test]
cli_pager =
role_arn = arn:aws:iam::xxxxxxxxxxxx:role/k8s-role
source_profile = test
region = eu-west-1
~/.aws/credentials
[test]
aws_access_key_id = XXXXXXXXXXXXXXXXXX
aws_secret_access_key = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Related
I'm using Terraform to deploy a lambda that needs to keep secrets in the AWS SecretsManager.
I have the following abbreviated lambda:
Lambda
resource "aws_lambda_function" "thisThing" {
function_name = "functionName"
runtime = "python3.8"
handler = "thisThing.handler"
role = aws_iam_role.lambda_exec.arn
}
resource "aws_iam_role" "lambda_exec" {
name = "serverless_lambda"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Action = "sts:AssumeRole"
Effect = "Allow"
Sid = ""
Principal = {
Service = "lambda.amazonaws.com"
}
}
]
})
}
resource "aws_iam_role_policy_attachment" "lambda_policy" {
role = aws_iam_role.lambda_exec.name
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
}
Here are the secrets
Secrets
# Secrets
resource "aws_secretsmanager_secret" "SECRET" {
name = "SECRET"
recovery_window_in_days = 0
}
resource "aws_secretsmanager_secret_version" "SECRET" {
secret_id = "${aws_secretsmanager_secret.SECRET.id}"
secret_string = "${var.SECRET}"
}
The error I'm getting is:
[ERROR] ClientError: An error occurred (AccessDeniedException) when calling the GetSecretValue operation: User: arn:aws:sts::439791110569:assumed-role/serverless_lambda/thisThing is not authorized to perform: secretsmanager:GetSecretValue on resource: SECRET because no identity-based policy allows the secretsmanager:GetSecretValue action
This is my first time using secrets manager, and I'm not very experienced in AWS, but I think based on the answer here, that I need to add a policy that allows my lambda exec role to have GetSecretValue rights. I've made a few attempts, but my lack of knowledge on how to look up the different policy ARN's is shutting me down.
Here's what I've tried adding (it's wrong, and I know it's wrong.)
resource "aws_iam_role_policy_attachment" "lambda_secretsmanager_role" {
role = aws_iam_role.lambda_exec.name
# ? policy_arn = "arn:aws:iam::aws:policy/SecretsManagerGetSecretValue"
}
That's not the correct ARN, but I'm not sure where to look to find the correct ARN.
You can add the permission using aws_iam_role_policy:
resource "aws_iam_role_policy" "sm_policy" {
name = "sm_access_permissions"
role = aws_iam_role.lambda_exec.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = [
"secretsmanager:GetSecretValue",
]
Effect = "Allow"
Resource = "*"
},
]
})
}
If you want to follow least privileged permissions, then you can change Resource = "*" into Resource = "<arn-of-the-secret>".
I have created a aws_iam_policy_document with ssm and ec2 actions :
data "aws_iam_policy_document" "AdminEc2Actions" {
statement {
effect = "Allow"
sid = "sid1"
actions = [
"ssm:SendCommand",
"ec2:Start*",
"ssm:StartSession"
]
resources = [
"*"
]
}
}
# Create IAM policy for ec2
resource "aws_iam_policy" "AdminEc2Actions" {
name = "test-AdminEc2Actions-policies"
description = "ec2 policies"
path = "/"
policy = data.aws_iam_policy_document.AdminEc2Actions.json
}
# Attaches customer managed IAM poloicy to an IAM admins group
resource "aws_iam_group_policy_attachment" "AdminEc2Actions" {
group = aws_iam_group.groups[0].name
policy_arn = aws_iam_policy.AdminEc2Actions.arn
}
But, for some reason, any changes in actions sometimes are taken into account sometimes are ignored. eg. when I run this command, I got :
[ssm-user#ip-xxx.yy.zz.1]$ aws s3 mv /tmp/file* s3://test-dent-backup1/daily/
move failed: ../../tmp/file1.txt to s3://test-dent-backup1/daily/file1.txt [Errno 1] Operation not permitted: '/tmp/file1.txt'
Any suggestions?
I'm trying to create a policy following the Terraform documentation
resource "aws_iam_policy" "policy" {
name = "test_policy"
path = "/"
description = "My test policy"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = [
"ec2:Describe*",
]
Effect = "Allow"
Resource = "*"
},
]
})
}
Unfortunately, there is no description of how to include tags. I'm not able to do it such as I did with the rest of the resources, even when I can provide that manually from the AWS Management Console.
The tags setting does not seem to be working. I'm receiving an error if I try to do the same I did with an IAM role, including:
tags = {
tag-key = "tag-value"
}
Update:
This functionality was added in https://github.com/hashicorp/terraform-provider-aws/pull/18276 and released as part of v3.35.0 of the AWS provider.
You should now be able to add tags to your aws_iam_policy resources as you'd expect:
resource "aws_iam_policy" "policy" {
name = "test_policy"
path = "/"
description = "My test policy"
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = [
"ec2:Describe*",
]
Effect = "Allow"
Resource = "*"
},
]
})
tags = {
tag-key = "tag-value"
}
}
Tagging customer managed IAM policies is a new feature that was introduced on 11th February 2021. Currently there's only a feature request for this functionality on the AWS provider.
Once someone has added the necessary change and it has been merged and released you should expect this to work with the syntax you provided in the question.
This is now available from version 3.35.0
* data-source/aws_iam_policy: Add policy_id and tags attributes (#18276)
_
I have defined the creation of a StepFunction state machine in Terraform, now I want to set a timer to trigger the state machine everyday, I think probably using cloudwatch event rules is a good choice, I know how to set event rule to trigger a Lambda:
resource "aws_cloudwatch_event_rule" "lambda_event_rule" {
name = xxx
schedule_expression = xxx
description = xxx
}
resource "aws_cloudwatch_event_target" "lambda_event_target" {
target_id = xxx
rule = aws_cloudwatch_event_rule.lambda_event_rule.name
arn = xxx
}
#I must setup the right permissions using 'aws_lambda_permission'
#see: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_target
resource "aws_lambda_permission" "lambda_event_permission" {
statement_id = xxx
action = "lambda:InvokeFunction"
function_name = xxx
principal = "events.amazonaws.com"
source_arn = aws_cloudwatch_event_rule.lambda_event_rule.name
}
but how can I setup the permission part for triggerring a state machine? I couldn't find any examples about it, am I missing anything? Is it because we don't need a permission config for state machine? Can someone help please?
Below is what I got to use cloudwatch event rules to trigger state machine so far:
resource "aws_cloudwatch_event_rule" "step_function_event_rule" {
name = xxx
schedule_expression = xxx
description = xxx
}
resource "aws_cloudwatch_event_target" "step_function_event_target" {
target_id = xxx
rule = aws_cloudwatch_event_rule.step_function_event_rule.name
arn = xxx
}
?????What else should I add here?
PS: I found someone else was asking about a similar question here, but no answers yet.
The
resource "aws_lambda_permission" "lambda_event_permission" {
statement_id = xxx
action = "lambda:InvokeFunction"
function_name = xxx
principal = "events.amazonaws.com"
source_arn = aws_cloudwatch_event_rule.lambda_event_rule.name
}
part is not needed at all in your case, only needed as stated "In order to be able to have your AWS Lambda function or SNS topic invoked by an EventBridge rule".
As blr stated in his answer, you need to add the role_arn in the aws_cloudwatch_event_target, set up a role with assume_role_policy which grants access to states.amazonaws.com and events.amazonaws.com, and attach to this role an extra policy as follows:
data "aws_iam_policy_document" "CW2SF_allowexec" {
statement {
actions = [
"sts:AssumeRole"
]
principals {
type = "Service"
identifiers = [
"states.amazonaws.com",
"events.amazonaws.com"
]
}
}
}
resource "aws_iam_role" "CW2SF_allowexec" {
name = "AWS_Events_Invoke-StepFunc"
assume_role_policy = data.aws_iam_policy_document.CW2SF_allowexec.json
}
resource "aws_iam_role_policy" "state-execution" {
name = "CW2SF_allowexec"
role = aws_iam_role.CW2SF_allowexec.id
policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"states:StartExecution"
],
"Resource": [
"arn:aws:states:${var.region}:${data.aws_caller_identity.current.account_id}:stateMachine:data-pipeline-incremental"
]
}
]
}
EOF
}
You need to establish the trust between CloudWatch and StepFunctions with the AssumeRole, and then attach an inline or managed policy to the role that specifically allows this role to StartExecution of the state machine.
I'm not well versed with terraform but it seems to follow a similar pattern to the official documentation. For targets; https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_PutTargets.html >> See section "Adds a Step Functions state machine as a target"
{
"Rule": "testrule",
"Targets": [
{
"RoleArn": "arn:aws:iam::123456789012:role/MyRoleToAccessStepFunctions"
"Arn":"arn:aws:states:us-east-1:123456789012:stateMachine:HelloWorld"
}
]
}
This tells me that you need to pass the role and arn. So taking your example, here's the thing you probably need to fill
resource "aws_cloudwatch_event_rule" "step_function_event_rule" {
name = <something unique>
schedule_expression = <syntax described in https://docs.aws.amazon.com/eventbridge/latest/userguide/scheduled-events.html>
description = <something descriptive>
}
resource "aws_cloudwatch_event_target" "step_function_event_target" {
target_id = <something unique>
rule = aws_cloudwatch_event_rule.step_function_event_rule.name
arn = <step function arn>
role_arn = <role that allows eventbridge to start execution on your behalf>
}
I'm using terraform to provision an ELB & want to Enable Access logs for ELB in a S3 bucket. When I try to apply the resources, I get the below error - InvalidConfiguration: Access Denied for bucket:
Below are my TF resources with the S3 bucket policy created using the IAM Policy Document.
resource "aws_lb" "this" {
name = var.name
load_balancer_type = "application"
access_logs {
bucket = aws_s3_bucket.this.bucket
prefix = var.name
enabled = true
}
}
resource "aws_s3_bucket" "this" {
bucket = "${var.bucket_name}"
acl = "log-delivery-write"
force_destroy = true
}
resource "aws_s3_bucket_policy" "this" {
bucket = "aws_s3_bucket.this.id"
policy = "${data.aws_iam_policy_document.s3_bucket_lb_write.json}"
}
data "aws_iam_policy_document" "s3_bucket_lb_write" {
policy_id = "s3_bucket_lb_logs"
statement {
actions = [
"s3:PutObject",
]
effect = "Allow"
resources = [
"${aws_s3_bucket.this.arn}/*",
]
principals {
identifiers = ["${data.aws_elb_service_account.main.arn}"]
type = "AWS"
}
}
statement {
actions = [
"s3:PutObject"
]
effect = "Allow"
resources = ["${aws_s3_bucket.this.arn}/*"]
principals {
identifiers = ["delivery.logs.amazonaws.com"]
type = "Service"
}
}
statement {
actions = [
"s3:GetBucketAcl"
]
effect = "Allow"
resources = ["${aws_s3_bucket.this.arn}"]
principals {
identifiers = ["delivery.logs.amazonaws.com"]
type = "Service"
}
}
}
output "bucket_name" {
value = "${aws_s3_bucket.this.bucket}"
}
I get the following error
Error: Error putting S3 policy: NoSuchBucket: The specified bucket does not exist
status code: 404, request id: 5932CFE816059A8D, host id: j5ZBQ2ptHXivx+fu7ai5jbM8PSQR2tCFo4IAvcLkuocxk8rn/r0TG/6YbfRloBFR2WSy8UE7K8Q=
Error: Failure configuring LB attributes: InvalidConfigurationRequest: Access Denied for bucket: test-logs-bucket-xyz. Please check S3bucket permission
status code: 400, request id: ee101cc2-5518-42c8-9542-90dd7bb05e3c
terraform version
Terraform v0.12.23
provider.aws v3.6.0
There is mistake in:
resource "aws_s3_bucket_policy" "this" {
bucket = "aws_s3_bucket.this.id"
policy = "${data.aws_iam_policy_document.s3_bucket_lb_write.json}"
}
it should be:
resource "aws_s3_bucket_policy" "this" {
bucket = aws_s3_bucket.this.id
policy = data.aws_iam_policy_document.s3_bucket_lb_write.json
}
The orginal version (bucket = "aws_s3_bucket.this.id") will just try to look for bucket literally called "aws_s3_bucket.this.id".