finding out what HCL literals GCP roles map to - google-cloud-platform

I have the following code:
resource "google_project_iam_binding" "px_kubernetes_engine_cluster_viewer" {
project = var.project_id
role = "roles/kubernetesEngineCluster.viewer"
members = [
"serviceAccount:${google_service_account.px.email}",
]
}
My aim is to assign the Kubernetes Engine Cluster viewer role to a service account, however, whatever string literal represents this and I have tried: "roles/kubernetesEngineCluster.viewer" and "roles/kubernetesEngineClusterViewer" without success, the GCP provider does not like this.
How can I find out what Kubernetes Engine Cluster viewer maps to in HCL ?

The role is roles/container.clusterViewer.
The HCL supports the same definitions that Google Cloud IAM uses. For Kubernetes they are here:
Predefined GKE Roles
The CLI can list all predefined roles:
gcloud iam roles list

Related

Can't use GCP IAM API with a service account

I am trying to create a new service account with terraform code. This code works well when I run it on behalf of my user credentials (the project Owner). But I see an error when I run the code on behalf of terraform service account
module "service_accounts" {
source = "terraform-google-modules/service-accounts/google"
version = "~> 4.1"
project_id = var.project
prefix = var.env
names = ["dataproc-sa"]
project_roles = [
"${var.project}=>roles/cloudkms.cryptoKeyEncrypterDecrypter",
"${var.project}=>roles/storage.objectViewer",
"${var.project}=>roles/dataproc.worker",
]
}
The terraform-google-modules/service-accounts/google module documentation says
Service account or user credentials with the following roles must be used to provision the resources of this module:
* Service Account Admin: roles/iam.serviceAccountAdmin
* (optional) Service Account Key Admin: roles/iam.serviceAccountKeyAdmin when generate_keys is set to true
* (optional) roles needed to grant optional IAM roles at the project or organizational level
I've bound roles/iam.serviceAccountAdmin to the gitlab-terraform#xxxxxx.iam.gserviceaccount.com service account, despite this I see the next error
Error: Error creating service account: googleapi: Error 403:
Identity and Access Management (IAM) API has not been used in project xxxxxxxxx
before or it is disabled. Enable it by visiting
https://console.developers.google.com/apis/api/iam.googleapis.com/overview?project=xxxxxxxxx
then retry. If you enabled this API recently, wait a few minutes for
the action to propagate to our systems and retry.
It looks like the terraform service account doesn't have the appropriate permissions to create a new service account
What should I do to allow the service account create another one? What kind of permissions are missed? The code works well if I run it with the project Owner role (but I don't want to do this)
EDIT: Forgot to mention that I tried to bind roles/iam.admin to the terraform service account but it gave me the next error
ERROR: Policy modification failed. For a binding with condition,
run "gcloud alpha iam policies lint-condition" to identify
issues in condition.
ERROR: (gcloud.projects.add-iam-policy-binding)
INVALID_ARGUMENT: Role roles/iam.admin is not supported for this resource.
The problem is the IAM service is not enabled. To enable that service you need the IAM role Service Usage Admin aka roles/serviceusage.serviceUsageAdmin. The Owner and Editor roles also have the permission serviceusage.services.enable.
You can enable the service using the CLI:
gcloud services enable iam.googleapis.com
Or add this to your Terraform HCL to enable the IAM service.
resource "google_project_service" "iam_service" {
project = var.project
service = "iam.googleapis.com"
}
You should also add a depends_on to resources that depend on the service being enabled:
depends_on = [
google_project_service.iam_service
]

Terraform in aws multi account env created by AWS Control Tower

I have just moved to a multi account set up using Control Tower and am having a 'mare using Terraform to deploy resources in different accounts.
My (simplified) account structure is:
|--Master
|--management (backends etc)
|--images (s3, ecr)
|--dev
|--test
As a simplified experiment I am trying to create an ecr in the images account. So I think I need to create a policy to enable role switching and provide permissions within the target account. For now I am being heavy handed and just trying to switch to Admin access. The AWSAdministratorAccess role is created by Control Tower on configuration.
provider "aws" {
region = "us-west-2"
version = "~> 3.1"
}
data "aws_iam_group" "admins" { // want to attach policy to admins to switch role
group_name = "administrators"
}
// Images account
resource "aws_iam_policy" "images-admin" {
name = "Assume-Role-Images_Admin"
description = "Allow assuming AWSAdministratorAccess role on Images account"
policy = <<EOP
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"sts:AssumeRole"
],
"Resource": "arn:aws:iam::<Images_Account_ID>:role/AWSAdministratorAccess"
}
]
}
EOP
}
resource "aws_iam_group_policy_attachment" "assume-role-images-admin" {
group = data.aws_iam_group.admins.group_name
policy_arn = aws_iam_policy.images-admin.arn
}
Having deployed this stack I then attempt to deploy another stack which creates a resource in the images account.
provider "aws" {
region = var.region
version = "~>3.1"
}
provider "aws" {
alias = "images"
region = var.region
version = "~> 3.1"
assume_role {
role_arn = "arn:aws:iam::<Images_Account_ID>:role/AWSAdministratorAccess"
}
}
resource "aws_ecr_repository" "boot-images" {
provider = aws.images
name = "boot-images"
}
On deployment I got:
> Error: error configuring Terraform AWS Provider: IAM Role (arn:aws:iam::*********:role/AWSAdministratorAccess) cannot be assumed.
There are a number of possible causes of this - the most common are:
* The credentials used in order to assume the role are invalid
* The credentials do not have appropriate permission to assume the role
* The role ARN is not valid
Error: NoCredentialProviders: no valid providers in chain. Deprecated.
For verbose messaging see aws.Config.CredentialsChainVerboseErrors
First one: the creds provided are from the master account which always worked in a single account environment
Second: that's what I think has been achieved by attaching the policy
Third: less sure on this but AWSAdministratorAccess defo exists in the account, I think the arn format is correct and while AWS Single Sign On refers to it as a Permission Set the console also describes this as a role.
I found Deploying to multiple AWS accounts with Terraform? which was helpful but I am missing something here.
I am also at a loss of how to extend this idea to deploying an s3 remote backend into my "management" account.
Terraform version 0.12.29
Turns out there were a couple of issues here:
Profile
The credentials profile was incorrect. Setting the correct creds in Env Vars let me run a simple test when just using the creds file failed. There is still an issue here I don't understand as updating the creds file also failed but I have a system that works.
AWS created roles
While my assumption was correct that the Permission Sets are defined as Roles, they have a trust relationship which was not extended to my Master Admin User (my bad) AND it cannot be amended as it was created by AWS automatically and it is locked down.
Manually grant permissions
So while I can grant permissions to a Group to assume a role programatically via Terraform I need to manually create a role in the Target account which extends trust and hence permissions to the Master account.
In my own experience and considering you already have a working AWS infrastructure, I'd rule out and move away from Control Tower and look into doing same things with CloudFormation StackSets. They let you target OUs or individual accounts.
Control Tower has been recommended to me several times, but having an AWS ecosystem of more >25 accounts with production workloads, I am very reluctant to event try. It's great to start from scratch I guess, but not when you already have a decent amount of workloads and accounts in AWS.

Terraform to get AWS data from Account A and use it in Account B

I'm using two sets of terraform scripts which creates application infrastructure in AWS on Account A and codepipeline in Account B, TF scripts that creates codepipeline in Account B will need some configuration parameters(ALB, ECS..etc) from Account A which is already setup, I'm familiar on getting data if everything is hosted on the same AWS account, Is it possible to retrieve the data of one account from other using Terraform? Is there any documentation for this scenario?
Yes, it is possible. Since the question is rather generic I can only provide generic information.
In general, for cross-account access, cross-account IAM roles are used. This is a good practice, not a requirement. AWS doc info about the roles:
Providing Access to an IAM User in Another AWS Account That You Own
Tutorial: Delegate Access Across AWS Accounts Using IAM Roles
Based on these, in Account A you would have to setup an assumable role with a trust relationship allowing Account B to assume the role. In Account B, the IAM user that is used for terraform would need to have IAM permissions to assume the role.
Having the role setup, in terraform you would use aws provider that would assume_role, e.g. from docs:
provider "aws" {
alias = "assumed_role_provider"
assume_role {
role_arn = "arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME"
session_name = "SESSION_NAME"
external_id = "EXTERNAL_ID"
}
}
Then to use the provider you would use its alias for resources or data sources, e.g. from docs:
resource "aws_instance" "foo" {
provider = aws.assumed_role_provider
# ...
}

Use IAM role instead of credentials to create aws resource from an EC2 instance using terraform

We are working on a requirement where we want terraform apply which runs on AWS EC2 instance to use IAM role instead of using credentials(accesskey/secretkey) as part of aws provider to create route53 in AWS.
NOTE: IAM Role added to instance has been provided with policy which gives the role the route53fullaccess.
When we use below syntax in terraform.tf, it works fine. We are able to create route.
SYNTAX:
*provider "aws" {
access_key = "${var.aws_accesskey}
secret_key = "${var.aws_secretkey}
region = "us-east-1"
}
resource "aws_route53_record {}*
But, we want the terraform script to run with IAM Role and not with credentials. (Do not want to maintain credentials file)
STEPS TRIED:
1. Removed provider block from terraform.tf file and run the build.
SYNTAX:
resource "aws_route53_record {}
2.Getting the below error.
Provider.aws :InvalidClientTokenid.
3. Went through the terraform official documentation to use IAM Role. it says to use metadata api. but there is no working sample. (https://www.terraform.io/docs/providers/aws/index.html)
Am new to Terraforms so pardon me if its a basic question. Can someone help with the code/working sample to achieve this ?
You need to supply the profile arn in the "provider" block, not the role, like so :
provider "aws" {
profile = "arn:aws:iam::<your account>:instance-profile/<your role name>"
}
The 'role_arn' key mentioned in the answer above is actually invalid in the 'provider' context.
Insert the following line for IAM role in your terraform script, in provider:
role_arn = "arn:aws:iam::<your account>:role/SQS-Role-demo"

Terraform on GCP fails to create pubsub topic stating permission denied

Created a service user to manage terraform under the project and gave it roles/owner. Created the key for this terraform user.
Terraform code is simple:
resource "google_pubsub_topic" "my_topic" {
name = "my_topic"
project = "${var.project_id}"
}
just creating a pub-sub topic.
terraform plan works but terraform apply gives me:
google_pubsub_topic.my_topic: googleapi: Error 403: User not authorized to perform this action., forbidden
I have even tried giving the service account roles/pubsub.admin not sure I understand what's going on because my service account has the owner role associated with it yet it can't create a pubsub topic.
Can anybody help me figure this out please?
Thanks in advance.
Edit (to expand on my comment about what worked):
I had created the service account using gcloud.
gcloud iam service-accounts create terraform \
--display-name "Terraform admin account"
gcloud projects add-iam-policy-binding myproject-182220 \
--member serviceAccount:terraform#myproject-182220.iam.gserviceaccount.com \
--role roles/owner
gcloud iam service-accounts keys create terraform-admin.json \
--iam-account terraform#myproject-182220.iam.gserviceaccount.com
To continue my debugging, I created a new service account using the console / GUI --> API & Services --> Credentials --> Create Credentials --> Service Account Key --> New Service Account (With the owner role). With this new service key json file, I was able to run my terraform code without a problem.
Now my confusion is, why did this work but not when I used gcloud to create a service account and give it the same role?
You have to enable the pub/sub api via google cloud or it might be possible using terraform.
The sample usage configuration for the Google provider looks more like:
// Configure the Google Cloud provider
provider "google" {
credentials = "${file("account.json")}"
project = "my-gce-project"
region = "us-central1"
}
// Create a new instance
resource "google_compute_instance" "default" {
# ...
}
This can be read in more detail on the "Google Cloud Provider" documentation page from Terraform.