setIAM 403 Forbidden - google-cloud-platform

resources:
- name: practice-service-account
type: iam.v1.serviceAccount
properties:
displayName: practice-service-account
projectId: {{ project }}
accountId: practice-service-account
- name: get-iam-policy
action: 'gcp-types/cloudresourcemanager-v1:cloudresourcemanager.projects.getIamPolicy'
properties:
resource: resources-practice {# make this environment variable #}
- name: set-iam-policy
action: 'gcp-types/cloudresourcemanager-v1:cloudresourcemanager.projects.setIamPolicy'
properties:
resource: {{ project }}
policy: $(ref.get-iam-policy)
gcpIamPolicyPatch:
add:
- role: roles/viewer
members:
- user:email1#example.com
- user:email2#example.com
- user:email3#example.com
Why am I always experiencing the error below when trying to create these IAM resources?
ERROR: (gcloud.deployment-manager.deployments.update) Error in Operation [operation-1544014242908-57c45d47a0760-6a2ec217-9ee53506]: errors:
- code: RESOURCE_ERROR
location: /deployments/infrastructure/resources/set-iam-policy
message: '{"ResourceType":"gcp-types/cloudresourcemanager-v1:cloudresourcemanager.projects.setIamPolicy","ResourceErrorCode":"403","ResourceErrorMessage":{"code":403,"message":"The
caller does not have permission","status":"PERMISSION_DENIED","statusMessage":"Forbidden","requestPath":"https://cloudresourcemanager.googleapis.com/v1/projects/resources-practice:setIamPolicy","httpMethod":"POST"}}'

Deployment manager acts using the [PROJECT_NUMBER]#cloudservices.gserviceaccount.com service account. This error indicates that that service account doesn't have permission to change the IAM policy on that project. Try granting the service account the iam.roleAdmin role on the project (or iam.organizationRoleAdmin role on the organization).

Related

How to refer autogenerated Role to attach to new IAM policy

I am creating a custom policy to attach it to the IAM role which has been autogenerated by AWS.
Below is the policy:-
rRotationLambdaDecryptPolicy:
Type: AWS::IAM::ManagedPolicy
DependsOn: rSecretRotationScheduleHostedRotationLambda
Properties:
Description: "Providing access to HostedLambda for decrypting KMS"
ManagedPolicyName: CustomedHostedLambdaKmsUserRolePolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Sid: AllowLambdaDecryptKMS
Effect: Allow
Action:
- kms:Decrypt
- kms:CreateGrant
Resource:
- !Sub arn:aws:kms:*:${AWS::AccountId}:key/*
Condition:
ForAnyValue:StringLike:
kms:ResourceAliases: alias/SecretsManager_KMSKey
Roles: <friendly rolename>
In Roles parameter , as i am not fully aware of the Rolename, so have been trying to generate it from its arn.
Roles:
- !Select [!Split ["/", !Sub 'arn:aws:iam::${AWS::AccountId}:role/secret-rotat-SecretsManagerRDSPostgre-*']]
but once pushed to cloudformation, getting error as below:-
The specified value for roleName is invalid. It must contain only alphanumeric characters and/or the following: +=,.#_- (Service: AmazonIdentityManagement; Status Code: 400; Error Code: ValidationError; Request ID: fbd4b14e-8c0e-459f-867f-968052828620; Proxy: null)
Not sure what is wrong here, and how can i refer it!
You can't use a wildcard * in the role name.
You would need to save the role name somewhere you can retrieve it (e.g. in Systems Manager Parameter store), or pass it as a parameter in to the template and then !Ref it.
i looked out everywhere, and found that this will be part of next version release of SAM as it requires work to add more attributes to the HostedLambda.
Till the time i managed to retrieve it from jenkins using AWSCLI (by getting the Lambda attributes which has that autogenerated role attached) and then processing it.
aur_rolename=sh(script: """aws lambda get-function --function-name SecretsManager-research-creds-rotation-lambda --query Configuration.Role --output text""", returnStdout: true).trim().split('/')[1]
aur_policyarn="arn:aws:iam::${env.account}:policy/CustomedHostedLambdaKmsUserRolePolicy"
sh(script: """aws iam attach-role-policy --policy-arn ${aur_policyarn} --role-name ${aur_rolename}""", returnStdout: true)

setIamPolicy for pubsub topics (at the resource level not project)

I'm using deployment manager to set the IAM policy of an existing pub/sub topic- I don't want to acquire it and I cannot create it with deployment manager (because it exists). So I want to set a policy on an existing resource
I can do this with buckets but the docs are confusing and I can't find the right methods for buckets
I want to do this (resource level bindings) for a topic instead of bucket:
resources:
- name: mybucket
action: gcp-types/storage-v1:storage.buckets.setIamPolicy
properties:
bucket: mybucket
bindings:
- role: roles/storage.admin
members:
- "serviceAccount:sdfsfds#sdfsdf.com"
I can only find gcp-types/pubsub-v1:projects.topics.setIamPolicy which seems like its at the project level? What is the right api for setting an IAM policy on a specific topic?
The google APIs seem inconsistent here- are these too methods equivalent? Docs are confusing:
https://cloud.google.com/storage/docs/json_api/v1/buckets/setIamPolicy
https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.topics/setIamPolicy
I attempted this but getting an error:
- name: mytopic
action: gcp-types/pubsub-v1:pubsub.projects.topics.setIamPolicy
properties:
resource: mytopic
bindings:
- role: roles/pubsub.admin
members:
- "serviceAccount:ssdfsdf#sdfsdf.com"
Getting error:
message: '{"ResourceType":"gcp-types/pubsub-v1:pubsub.projects.topics.setIamPolicy","ResourceErrorCode":"400","ResourceErrorMessage":{"code":400,"message":"Invalid
JSON payload received. Unknown name \"bindings\": Cannot find field.","status":"INVALID_ARGUMENT","details":[{"#type":"type.googleapis.com/google.rpc.BadRequest","fieldViolations":[{"description":"Invalid
JSON payload received. Unknown name \"bindings\": Cannot find field."}]}],"statusMessage":"Bad
Request","requestPath":"https://pubsub.googleapis.com/v1/projects/myproject/topics/mytopic:setIamPolicy","httpMethod":"POST"}}
When I tried projects.topics.setIamPolicy I got:
- code: COLLECTION_NOT_FOUND
message: Collection 'projects.topics.setIamPolicy' not found in discovery doc 'https://pubsub.googleapis.com/$discovery/rest?version=v1'
The pubsub-v1:projects.topics.setIamPolicy is at the topic level and the https://iam.googleapis.com/v1/{resource=projects/*/serviceAccounts/*}:setIamPolicy is to set the a Pub/Sub or other resources at the project level.
You get those error because you are giving Pub/Sub admin and this is a role at the project level. The example roles you can provide are:
roles/viewer
roles/editor
roles/owner
I understand that you are trying to to deploy a topic having a IAM policy that allows only one service account to a topic. You have to use a yaml file and a python file if that is the environment you are using.
In the python file you will set the IAM for the topic with the method "set_iam_policy" which takes 2 arguments, the policy and the topic path:
client = pubsub_v1.PublisherClient()
topic_path = client.topic_path(project, topic_name)
policy = client.get_iam_policy(topic_path)
# Add all users as viewers.
policy.bindings.add(
role='roles/pubsub.viewer',
members=['allUsers'])
# Add a group as a publisher.
policy.bindings.add(
role='roles/pubsub.publisher',
members=['group:cloud-logs#google.com'])
# Set the policy
policy = client.set_iam_policy(topic_path, policy)
print('IAM policy for topic {} set: {}'.format(
topic_name, policy))
For deployment manager:
imports:
- path: templates/pubsub/pubsub.py
name: pubsub.py
resources:
- name: test-pubsub
type: pubsub.py
properties:
topic: test-topic
accessControl:
- role: roles/pubsub.subscriber
members:
- user:demo#user.com
subscriptions:
- name: first-subscription
accessControl:
- role: roles/pubsub.subscriber
members:
- user:demo#user.com
- name: second-subscription
ackDeadlineSeconds: 15

Connecting function to empty cloud storage bucket

I am trying to use the following info from Google deployment manager examples on GitHub.
empty_bucket_in_function.yaml
empty_bucket_cf.yaml
imports:
- path: empty_bucket_cf.jinja
resources:
- name: my-function
type: empty_bucket_cf.jinja
properties:
project: <PROJECT_NAME>
region: europe-west1
entryPoint: handler
runtime: nodejs8
bucket: lskflsjfsj
empty_bucket_cf.jinja
{% set BUCKET = properties['bucket'] + '-bucket' %} resources:
#- type: cloudfunctions.v1.function
- type: gcp-types/cloudfunctions-v1:projects.locations.functions name: my-function properties:
parent: projects/{{ properties['project'] }}/locations/{{ properties['region'] }}
location: {{ properties['region'] }}
function: my-{{ properties['bucket'] }}
sourceArchiveUrl: gs://$(ref.{{ BUCKET }}.name)/my-function
entryPoint: {{ properties['entryPoint'] }}
runtime: {{ properties['runtime'] }}
eventTrigger:
resource: $(ref.my-topic.name)
eventType: providers/cloud.pubsub/eventTypes/topic.publish
#- type: pubsub.v1.topic
- type: gcp-types/pubsub-v1:projects.topics name: my-topic properties:
topic: {{ properties['bucket'] }}-topic
#- type: storage.v1.bucket
- type: gcp-types/storage-v1:buckets name: {{ BUCKET }} properties:
predefinedAcl: projectPrivate
projection: full
location: US
storageClass: STANDARD
While deploying using deployment manager I am getting error as
testsetup has resource warnings
my-function: {"ResourceType":"gcp-types/cloudfunctions-v1:projects.locations.functions","ResourceErrorCode":"400","ResourceErrorMessage":"Failed to retrieve function source code"}
Deployment properties
Any idea why this is not a bug in Google Cloud Platform GitHub repository. Isn't it the purpose of empty_bucket config to create CFs with empty bucket.
Note: Sometimes it executes successfully as well.
I don't what Google had in mind when they publish this example, but it can't work. If your bucket is empty, the function has no code. However, when you deploy a function, the code is compiled/parsed, the entry-point checked (exists, correct signature,...), and deployed on the environment.
Here, no entry point, no code to compile/parse thus no deployment -> It's normal, but the example is disturbing. You can open an issue on the repos.

How to add cloudsql role to a service account via cloud-deployment-manager

I'm trying to add the cloudsq.client role to a service account via the cloud deployment manager. How do i do this?
I figured out that i can add primitive roles like role/owner with the pubsub.v1.topic resourceType. See the official google example:
resources:
- name: {{ env['name'] }}
type: pubsub.v1.topic
properties:
topic: {{ env['name'] }}
accessControl:
gcpIamPolicy:
bindings:
- role: roles/pubsub.subscriber
members:
- "serviceAccount:$(ref.{{ properties['serviceAccountId'] }}.email)"
But it seems like that this doesn't work with role/cloudsql.client:
It says:
"message":"Role roles/cloudsql.client is not supported for this resource."
I figured out through Can't create cloudsql role for Service Account via api that i most likely have to use the cloudresourcemanager.v1.project resource. But just replacing the resources doesn't work either:
resources:
- name: {{ env['name'] }}
type: cloudresourcemanager.v1.project
properties:
projectId: {{ env['project'] }}
accessControl:
gcpIamPolicy:
bindings:
- role: roles/cloudsql.client
members:
- "serviceAccount:$(ref.{{ properties['serviceAccountId'] }}.email)"
Error:
- code: RESOURCE_ERROR
location: /deployments/test-cluster/resources/cloudsql-client-role
message: '{"ResourceType":"cloudresourcemanager.v1.project","ResourceErrorCode":"403","ResourceErrorMessage":{"code":403,"message":"Service
accounts cannot create projects without a parent.","status":"PERMISSION_DENIED","statusMessage":"Forbidden","requestPath":"https://cloudresourcemanager.googleapis.com/v1/projects","httpMethod":"POST"}}'
Im kinda stuck so i appreciate every help i can get!
To fix this you need to use the following type in your "resources": https://github.com/GoogleCloudPlatform/deploymentmanager-samples/blob/ae293a455f90746fb2e25142dbc11250cc51aad3/community/cloud-foundation/templates/iam_member/iam_member.py#L30
The correct way to add a role to a service account is: getIamPolicy > setIamPolicy
First you need to get the policies then you will be able to set the policies, this process is called "binding".
Please use the following template to add roles to service accounts:
https://github.com/GoogleCloudPlatform/deploymentmanager-samples/tree/master/community/cloud-foundation/templates/iam_member
If you have further questions I would be glad to help you.

Creating Instance Group Manager fails without Editor role on service account

I've got a node.js application trying to create an Instance Group Manager. It's running on an instance with a service account attached to the instance with scopes compute-rw and cloud-platform. This service account has a role with the following permissions:
includedPermissions:
- compute.autoscalers.create
- compute.autoscalers.get
- compute.disks.create
- compute.images.get
- compute.images.useReadOnly
- compute.instanceGroupManagers.create
- compute.instanceGroupManagers.get
- compute.instanceGroupManagers.use
- compute.instanceTemplates.create
- compute.instanceTemplates.get
- compute.instanceTemplates.useReadOnly
- compute.instances.create
- compute.instances.setMetadata
- compute.instances.setTags
- compute.networks.get
- compute.subnetworks.get
- compute.subnetworks.use
Looking at the audit log for resource.type="gce_instance_group_manager" I can see in first log entry:
ProtoPayload.authorizationInfo:
- granted: true
permission: compute.instanceGroupManagers.create
resourceAttributes:
name: projects/my-project/zones/us-east1-b/instanceGroupManagers/resource-name
service: compute
type: compute.instanceGroupManagers
- granted: true
permission: compute.instanceTemplates.useReadOnly
resourceAttributes:
name: projects/my-project/global/instanceTemplates/resource-name
service: compute
type: compute.instanceTemplates
- granted: true
permission: compute.instances.create
resourceAttributes:
name: projects/my-project/zones/us-east1-b/instances/resource-name-0000
service: compute
type: compute.instances
- granted: true
permission: compute.disks.create
resourceAttributes:
name: projects/my-project/zones/us-east1-b/disks/resource-name-0000
service: compute
type: compute.disks
- granted: true
permission: compute.images.useReadOnly
resourceAttributes:
name: projects/my-project/global/images/resource-name-image
service: compute
type: compute.images
- granted: true
permission: compute.subnetworks.use
resourceAttributes:
name: projects/my-project/regions/us-east1/subnetworks/resource-name-subnet
service: compute
type: compute.subnetworks
- granted: true
permission: compute.instances.setMetadata
resourceAttributes:
name: projects/my-project/zones/us-east1-b/instances/resource-name-0000
service: compute
type: compute.instances
- granted: true
permission: compute.instances.setTags
resourceAttributes:
name: projects/my-project/zones/us-east1-b/instances/resource-name-0000
service: compute
type: compute.instances
I get 200 OK back with status: "PENDING" in body.
Only when looking through the audit logs do I see a log entry with status.message: INVALID_PARAMETER with no explanation and then another log entry with:
jsonPayload.error:
- code: SERVICE_ACCOUNT_ACCESS_DENIED
detail_message: ''
location: ''
When attaching the Editor role to the service account I can create the Instance Group Manager so there seem to be some permissions missing. The logs show no permissions that were not granted so what could be missing?
Raw logs
Turns out that the instanceTemplate attached service accounts to the instances. Because of that iam.serviceAccountUser role is required on the service account used by the instance creating the instance group manager.
In my case the service accounts are not needed so I removed it from the instance template and the permissions above work.