Using role in aws-auth config-map - amazon-web-services

I'm using this terraform module to create eks cluster: https://github.com/terraform-aws-modules/terraform-aws-eks
Then I create an additional role and added to map_roles input similar to the example in the repo
(my role is to use CloudWatch)
{
rolearn = "arn:aws:iam::66666666666:role/role1"
username = "role1"
groups = ["system:masters"]
}
I can verify that the role is added to the aws-auth config map together with a role created by the module.
I got this error when the app trying to use CloudWatch:
User: arn:aws:sts::xxx:assumed-role/yyy/zzz is not authorized to perform: logs:DescribeLogGroups on resource: arn:aws:logs:xxx:yyy:log-group::log-stream
the User arn in the error message has the yyy part match the role arn created by the module. So I thought I'm using the wrong role? if so how can I choose the correct credential? (I'm using .NETcore, create AmazonCloudWatchLogsClient without specify any credential)
When I manually edit that role and add the log's permission, the app works. Not sure if it's the right way, if so how can I add the permission in terraforming?

I ended up pulling the eks module to local and add more policies to the existing role:
resource "aws_iam_policy" "my_new_policy" {
name_prefix = "eks-worker-my_new_policy-${aws_eks_cluster.this.name}"
description = "EKS worker node my_new_policy policy for cluster ${aws_eks_cluster.this.name}"
policy = data.aws_iam_policy_document.my_new_policy.json
path = var.iam_path
}
data "aws_iam_policy_document" "my_new_policy" {
statement {
sid = "my_new_policy"
effect = "Allow"
actions = [
"logs:DescribeLogGroups"
]
resources = ["*"]
}
}

Related

Using a multi-region S3 accesspoint with sagemaker (terraform)

I have a sagemaker model that will be deployed in different aws regions. This model will download models from an s3 bucket that is in region x. As long as the model is deployed in region x, the endpoint works.
However, when I deploy the sagemaker model from region y, it fails with the message.
Error: error creating SageMaker model: ValidationException: Could not
access model data at s3://mmmm/. Please ensure that the role
"arn:aws:iam::xxxx:role/dev-xxx-iam-role" exists and that its trust
relationship policy allows the action "sts:AssumeRole" for the service
principal "sagemaker.amazonaws.com". Also ensure that the role has
"s3:GetObject" permissions and that the object is located in region x.
My iam role permissions are as follows:
resource "aws_iam_policy_attachment" "sm_full_access_attach" {
name = "sm-full-access-attachment"
roles = [aws_iam_role.sagemaker_inferencer_iam_role.name]
policy_arn = "arn:aws:iam::aws:policy/AmazonSageMakerFullAccess"
}
resource "aws_iam_policy_attachment" "s3_full_access_attach" {
name = "s3-full-access-attachment"
roles = [aws_iam_role.sagemaker_inferencer_iam_role.name]
policy_arn = "arn:aws:iam::aws:policy/AmazonS3FullAccess"
}
with the assume role policy of:
data "aws_iam_policy_document" "sm_assume_role_policy" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["sagemaker.amazonaws.com"]
}
}
}
The iam role is as follows:
resource "aws_iam_role" "sagemaker_inferencer_iam_role" {
name = "${var.app_environment}-inferencer-sm-${var.aws_region}-iam-role"
assume_role_policy = data.aws_iam_policy_document.sm_assume_role_policy.json
}
And the above works for same region buckets.
I can of course create have buckets in each region with replication rules from the original bucket. However, this is costly as the model files are huge. So I created a multi-region accesspoint for my original bucket with an alias zzz.mrap
However, when I specify the accesspoint alias in the aws_sagemaker_model resource as follows:
resource "aws_sagemaker_model" "sagemaker_multimodel" {
name = "${var.app_environment}-inferencer-sm-${var.aws_region}-model"
execution_role_arn = aws_iam_role.sagemaker_inferencer_iam_role.arn
primary_container {
image = local.multi_model_inferencer_container_name
mode = "MultiModel"
model_data_url = "s3://zzz.mrap/"
}
}
I get the following error:
Error: error creating SageMaker model: ValidationException: Could not
access model data at s3://zzzz.mrap/. Please ensure that the role
"arn:aws:iam::878435376106:role/dev-xxx-iam-role" exists and that its
trust relationship policy allows the action "sts:AssumeRole" for the
service principal "sagemaker.amazonaws.com". Also ensure that the role
has "s3:GetObject" permissions and that the object is located in
region x.
AWS says that I only have to replace the bucket name by the alias and that they support sagemaker, however this does not seem to be the case.
What am I doing wrong?

Error Attaching IAM Role to an Instance Profile

I am trying to attach an IAM role to an instance profile for aws karpenter to be able to provision nodes on my behalf. I have already created the role, role-karpenter, from the console.
Below is the terraform script:
data "aws_iam_role" "karpenter_node_group_role" {
name = "role-karpenter"
}
resource "aws_iam_instance_profile" "karpenter" {
name = "KarpenterNodeInstanceProfile"
role = data.aws_iam_role.karpenter_node_group_role.name
}
This is the Error I am getting:
removing role arn:aws:iam::xxxx:role/role-karpenter from IAM instance profile KarpenterNodeInstanceProfile-cluster: ValidationError: The specified value for roleName is invalid. It must contain only alphanumeric characters and/or the following: +=,.#_-
│ status code: 400, request id: 7e631745-e7cb-4542-b19f-2b3872c8cbc3
Options I have tried:
I have used all these different terraform attribute references for the role
# name attribute
role = data.aws_iam_role.karpenter_node_group_role.name
# id attribute
role = data.aws_iam_role.karpenter_node_group_role.id
# arn attribute
role = data.aws_iam_role.karpenter_node_group_role.arn
The fix for me was to remove the resource from the state file and rerun it again
terraform state rm module.eks.aws_iam_instance_profile.karpenter
Then
terraform plan && terraform apply

update aws_iam_policy with terraform in GitLab-CI fails with EntityAlreadyExists error

I am trying to update an IAM Role and it's attached policy with Terraform through GitLab-CI. My terraform code looks like below:-
data "aws_iam_policy_document" "billing-roles" {
statement {
effect = "Allow"
principals {
type = "Federated"
identifiers = ["${var.samlprovider_arn}"]
}
actions = ["sts:AssumeRoleWithSAML"]
condition {
test = "StringEquals"
variable ="SAML:aud"
values = ["https://signin.aws.amazon.com/saml"]
}
}
}
resource "aws_iam_role" "billing_role" {
name = "billing-role"
permissions_boundary = "${var.permissions_boundary_arn}"
assume_role_policy = "${data.aws_iam_policy_document.billing-roles.json}"
tags = {
Applicatio_ID = "${var.app_id}"
Environment = "${var.environment}"
Name = "billing-role"
Owner = "Terraform"
}
}
resource "aws_iam_policy" "billing_policy" {
name = "billing-policy"
policy= "${file("${path.module}/policies/billing-role-policy.json")}"
}
resource "aws_iam_role_policy_attachment" "billing_attachment" {
role = aws_iam_role.billing_role.name
policy_arn = aws_iam_policy.billing_policy.arn
}
I am running various phases of terraform(INIT, PLAN, APPLY) through GitLab-CI. This works the first time but fails with EntityAlreadyExists error.
The .gitlab-ci.yml looks like this:-
include:
- project: 'infrastructure/infrastructure-code-cicd-files'
ref: master
file: '.for_terraform_iam.yml'
stages:
- init
- plan
- apply
tf_init:
extends: .tf_init
tags:
- integration
stage: init
variables:
ACCOUNT: "ACCOUNT_ID"
ASSUME_ROLE: "arn:aws:iam::ACCOUNT_ID:role/devops-cross-account"
backend_bucket_name: "iam-role-backend-${ACCOUNT}"
tfstate_file: "iam-role/terraform.tfstate"
tf_plan:
extends: .tf_plan
variables:
ASSUME_ROLE: "arn:aws:iam::ACCOUNT_ID:role/devops-cross-account"
tags:
- integration
stage: plan
tf_apply:
extends: .tf_apply
variables:
ASSUME_ROLE: "arn:aws:iam::ACCOUNT_ID:role/devops-cross-account"
tags:
- integration
stage: apply
This gitlab-ci configuration includes a utility file which has all the terraform logic for Init, Plan and Apply.
I am running the setup on Terraform 0.12.13.
Terraform import though successful in importing the resources does not help here as terraform complains about "EntityAlreadyExists"
Terraform taint does not work dues to a bug in the terraform version that I am using here.
I want a workflow where IAM Role once created, its attached inline policy can be updated by an Ops Engineer and an approver will approve the merge request and that way the IAM role will have added services as desired by the Ops engineer.
Is there a way we can update the IAM policy here. I understand that updating an IAM role would require detaching the policies first and then attach the new policies to it.
Please help
The issue was with passing terraform.tfstate file into plan stage which I had missed. We run an "aws s3 cp s3://backend-bucket/keys ." to get the statefile and this has solved the problem.

How can i provision IAM Role in aws with terraform?

as i'm new with terraform, i'd like to ask your help once i got stuck for almost a day.
When trying to apply a IAC to deploy a Nginx service into a ECS(EC2 launch type) on aws i'm facing the following problem:
Error: Error creating IAM Role nginx-iam_role: MalformedPolicyDocument: Has prohibited field Resource status code: 400, request id: 0f1696f4-d86b-4ad1-ba3b-9453f3beff2b
I have already checked the documentation and the syntax is fine. What else could be wrong?
Following the snippet code creating the IAM infra:
provider "aws" {
region = "us-east-2"
}
data "aws_iam_policy_document" "nginx-doc-policy" {
statement {
sid = "1"
actions = [
"ec2:*"
]
resources = ["*"]
}
}
resource "aws_iam_role" "nginx-iam_role" {
name = "nginx-iam_role"
path = "/"
assume_role_policy = "${data.aws_iam_policy_document.nginx-doc-policy.json}"
}
resource "aws_iam_group_policy" "nginx-group-policy" {
name = "my_developer_policy"
group = "${aws_iam_group.nginx-iam-group.name}"
policy = "${data.aws_iam_policy_document.nginx-doc-policy.json}"
}
resource "aws_iam_group" "nginx-iam-group" {
name = "nginx-iam-group"
path = "/"
}
resource "aws_iam_user" "nginx-user" {
name = "nginx-user"
path = "/"
}
resource "aws_iam_user_group_membership" "nginx-membership" {
user = "${aws_iam_user.nginx-user.name}"
groups = ["${aws_iam_group.nginx-iam-group.name}"]
}
If you guys need the remaining code: https://github.com/atilasantos/iac-terraform-nginx.git
You are trying to use the aws_iam_policy_document.nginx-doc-policy policy as an assume_role_policy which does not work as an assume role policy needs to define a principal that you trust and want to grant access to assume the role you are creating.
An assume role policy could look like this is you want to grant access to the role to EC2 instances via instance profiles. At the end you can attach your initial role via a new resource as an inline policy to the role:
data "aws_iam_policy_document" "instance-assume-role-policy" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["ec2.amazonaws.com"]
}
}
}
resource "aws_iam_role" "nginx-iam_role" {
name = "nginx-iam_role"
path = "/"
assume_role_policy = data.aws_iam_policy_document.instance-assume-role-policy.json
}
resource "aws_iam_role_policy" "role_policy" {
name = "role policy"
role = aws_iam_role.nginx-iam_role.id
policy = data.aws_iam_policy_document.nginx-doc-policy.json
}
Instead of attaching the policy as an inline policies you can also create an IAM Policy and attach it to the various iam resources. (e.g.: aws_iam_policy and aws_iam_role_policy_attachment for roles.)
We created a bunch of open-source IAM modules (and others) to make IAM handling easier: Find them here on github. But there are more modules out there that you can try.

Terraform: depends_on for module not working as expected in AWS

I am new to terraform. I was working with terraform v0.12 previously and since I wanted to bring in a dependency between modules, I started using terraform v0.13 recently. I am trying to create an IAM role and attach a few policies to the created role. But the issue arises in policy attachment to the role. Few policies are getting attached to the role but some policies throw an error saying no such role exists while the other policies are attached to the role properly. Is there anything wrong in my implementation?
module.tf
provider "aws" {
region = "ap-southeast-1"
}
#Control Plane role and policies
module "ControlPlane_Role" {
source = "../../templates/IAM/roles"
role_name = var.EKS-master-role
}
module "ControlPlane_Policy1" {
source = "../../templates/IAM/aws_policy"
role_name = var.EKS-master-role
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy"
depends_on = [module.ControlPlane_Role.role_create]
}
module "ControlPlane_Policy2" {
source = "../../templates/IAM/aws_policy"
role_name = var.EKS-master-role
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSServicePolicy"
depends_on = [module.ControlPlane_Role.role_create]
}
templates/IAM/roles/role.tf
resource "aws_iam_role" "role_create" {
assume_role_policy = data.aws_iam_policy_document.trusted_entity.json
name = var.role_name
}
aws_policy.tf
resource "aws_iam_role_policy_attachment" "aws_policy" {
role = var.role_name
policy_arn = var.policy_arn
}
I'll be passing the variable files separately and there are no issues with that.
Error:
Error: Error attaching policy arn:aws:iam::aws:policy/AmazonEKSClusterPolicy to IAM Role EKS-master: NoSuchEntity: The role with name EKS-master cannot be found.
Error attaching policy arn:aws:iam::aws:policy/AmazonEKSServicePolicy to IAM Role EKS-master: NoSuchEntity: The role with name EKS-master cannot be found.
If I re-run the command terraform apply again on the same resources without any change, the policies are getting attached.
You shouldn't use depends_on except for some exceptional cases. From the templates/IAM/roles, define an output that is the name of the role and in the other modules pass this output (role_name = module.ControlPlane_Role.output_role_name). With this setup, the dependency graph is clear (create the role, create the things that depend on the role) instead of having to manually define dependencies with depends_on.