TLDR
I'm just trying to start up a simple vm and it terraform tells me I don't have sufficient permissions. Keep in mind I have a Trial account (and like $290 left of sweet sweet free money).
Details
provider.tf
provider "google" {
project = "My First Project"
region = "us-east1"
}
resource.tf
resource "google_compute_instance" "vm_instance" {
name = "terraform-instance"
machine_type = "f1-micro"
zone = "us-east1-c"
boot_disk {
initialize_params {
image = "debian-cloud/debian-9"
}
}
network_interface {
# A default network is created for all GCP projects
network = "default"
access_config {
}
}
}
Error
Error: Error loading zone 'us-east1-c': googleapi: Error 403: Permission denied on resource project My First Project., forbidden
My Trouble Shooting
I tried switching us-east1-c for other zones and tried us-central1 with different zones. Always got the same error.
I'm passing the credentials withGOOGLE_APPLICATION_CREDENTIALS environment variable and I know I'm passing it in correctly cause when I change the filename it breaks and says something like "that filename doesn't exist"
I've tried different server types (n1-standard-1, n1-highcpu-16)
I've tried so many different IAM permissions of particular note I tried Compute Admin, Compute Admin with Service Account User, and Compute Instance Admin and Service Account Admin.
Concerning the last point. I used
gcloud projects get-iam-policy <PROJECT NAME> \
--flatten="bindings[].members" \
--format='table(bindings.role)' \
--filter="bindings.members:<KEY NAME>"
And got this output
ROLE
roles/compute.admin
roles/compute.instanceAdmin
roles/compute.instanceAdmin.v1
roles/compute.instanceAdmin.v1
roles/iam.serviceAccountUser
But wait there's more
I went through this link and added all the permissions they suggested using the aforementioned key (except for all the ones that have to do with billing cause the organization is my school). When I checked the roles again I saw that it had added roles/storage.admin. Produced the same error though.
Update
A billing account is linked to my account and now the roles are this. AND IT STILL doesn't work
roles/billing.projectManager
roles/compute.admin
roles/compute.instanceAdmin
roles/compute.instanceAdmin.v1
roles/compute.instanceAdmin.v1
roles/iam.serviceAccountUser
roles/storage.admin
Related
Running terraform apply getting below error.
{"error":{"code":403,"message":"The billing account for the owning project is disabled in state absent","errors":[{"message":"The billing account for the owning project is disabled in state absent","domain":"global","reason":"accountDisabled","locationType":"header","location":"Authorization"}]}}: timestamp=2022-12-31T00:04:43.690-0500
For the project I added the billing account.
I am able to run gcloud commands from shell without any errors using the same service account.
terraform_gcp % gcloud auth activate-service-account --key-file=sakey.json
Activated service account credentials for: [gcp-terraform#saproject.iam.gserviceaccount.com]
terraform_gcp % gsutil ls
gs://mygcptfstatebucket/
terraform_gcp % gcloud compute instances list
Listed 0 items.
my main.tf is
terraform {
required_providers {
google = {
source = "hashicorp/google"
version = "4.47.0"
}
}
}
provider "google" {
project = "my-gcp-project"
region = "us-east1"
zone = "us-east1-b"
}
Any insights into this error.
Tried adding below block and its working seems issue with my configuration.
data "google_project" "project_name" {
project_id = "projectid"
}
and referencing project_id in the resource block.
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
]
I have a brand new GCP account that I'm the only owner of, this is a personal/clean brand new project.
I manage the infrastructure exclusively with terraform and trying to create a HTTPS load balancer to route requests to a fixed ip, which I then want to forward to a bucket where I have a webapp, I've setup this type of infrastructure in the past via the UI but not via terraform.
When attempting to create this piece of infrastructure:
resource "google_compute_global_address" "main" {
name = "main"
}
resource "google_compute_forwarding_rule" "lb" {
name = "lb"
provider = google-beta
region = "europe-west2"
project = "owlee-software"
ip_protocol = "TCP"
load_balancing_scheme = "EXTERNAL_MANAGED"
port_range = "443"
target = google_compute_global_address.main.address
network_tier = "PREMIUM"
}
this throws
│ Response: {
│ "error": "invalid_grant",
│ "error_description": "Account has been deleted"
│ }
for brand new service accounts -- I have deleted the account and created another one -- with another file, if I remove this resource everything gets instantiated fine via the service account in the GCP account. This is the only 'google beta' provider that I have in the project as well.
I'm not sure if this is because of the resource configuration being wrong or something is happening with the service account.
When I try to inspect the service account I just created and made editor on the project, I can't, it shows greyed out with the following text:
Could not find an ancestor of the selected project where you have access to view a policy report. On at least one ancestor, you need the following permissions:
cloudasset.assets.analyzeIamPolicy,
cloudasset.assets.searchAllIamPolicies,
and cloudasset.assets.searchAllResources
My single-main account has the following roles attached to it:
Cloud Asset Owner
Organization Administrator
Owner
Project IAM Admin
Security Admin
I've added all of them after the Owner didn't seem to be enough.
Any suggestions appreciated, thank you.
It's an authentication issue. For me what solved was running.
gcloud auth application-default login
Followed by the terraform apply
But you can check here the documentation on how to authenticate with terraform
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.
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.