programmatic way to provide access to a object in GCS bucket for multiple users - python-3.x

I have a list of users whom I want to provide read access to an object stored in my GCS Bucket.
I am able to do this task manually by adding one one user, but I want to do this programmatically.
Please guide me if there is any such way to do it.

If you are comfortable with Terraform and it's possible for you to use it, you can use the dedicated resource :
You can configure the users access as a variable in a map :
variables.tf file
variable "users_object_access" {
default = {
user1 = {
entity = "user-user1#gmail.com"
role = "READER"
}
user2 = {
entity = "user-user2#gmail.com"
role = "OWNER"
}
}
}
Then in the Terraform resource, you can use a foreach in your users access list configured previously.
main.tf file :
resource "google_storage_object_access_control" "public_rule" {
for_each = var.users_object_access
object = google_storage_bucket_object.object.output_name
bucket = google_storage_bucket.bucket.name
role = each.value["role"]
entity = each.value["entity"]
}
resource "google_storage_bucket" "bucket" {
name = "static-content-bucket"
location = "US"
}
resource "google_storage_bucket_object" "object" {
name = "public-object"
bucket = google_storage_bucket.bucket.name
source = "../static/img/header-logo.png"
}

If it's to one particular object in a bucket then it sounds like more of an ACL approach.
gsutil will make things easier. You have a couple of options depending on your specific needs. If those users already have authenticated Google accounts then you can use the authenticatedRead predefined ACL:
gsutil acl set authenticatedRead gs://BUCKET_NAME/OBJECT_NAME
This will gives the bucket or object owner OWNER permission, and gives all authenticated Google account holders READER permission.
Or, with ACL enabled, you can retrieve the ACL of that particular object, make some edits to the JSON file, and set the updated ACL back on the object.
Retrieve the ACL of the object:
sutil acl get gs://BUCKET_NAME/OBJECT_NAME > acl.txt
Then make the permission edits by adding the required users/groups, and apply the updated ACL back to the object:
gsutil acl set acl.txt gs://BUCKET_NAME/OBJECT_NAME
You can apply the updated ACL to a particular object, bucket, or pattern (all images, etc).

Related

Create new resources on muti-accounts on AWS?

I am building a small tool using Terraform to generate sandbox on AWS. I will be the owner of every new sandbox and each user will be added as an IAM user with appropriate rights.
The input file looks like this: users.auto.tfvars
sandboxs_manager = "pierre-alexandre.mousset"
dev_team_members = [
{ name = "brian.davids", is_enabled = true }, { name = "tom.hanks", is_enabled = true }]
Which is going to create 2 different AWS accounts:
pierre-alexandre.mousset+brian.davids#company.com
pierre-alexandre.mousset+tom.hanks#company.com
What I am now trying to achieve, is to create a simple S3 bucket on every new aws_organizations_account generated by Terraform.
This is how I am generating AWS accounts on my Terraform:
resource "aws_organizations_account" "this" {
for_each = local.all_user_names
name = "Dev Sandbox ${each.value}"
email = "${var.manager}+sbx_${each.value}#company.com"
role_name = "Administrator"
parent_id = var.sandbox_organizational_unit_id
}
Is there a way to loop over every id generated by aws_organizations_account to create a S3 bucket on each of those newly created account?
Based on this Github issue, I would need to use muti-provider which is not yet supported by Terraform and would probably look like this before to generate my s3 buckets:
provider "aws" {
for_each = local.aws_accounts
alias = each.value.aws_account_id
assume_role {
role_arn = "arn:aws:iam::${aws_organizations_account.this.id}:role/TerraformAccessRole"
}
}
Is there any way to deal with this?

Vault - Assign multiple aliases for one identity group

I've been trying to assign multiple group aliases, meaning, multiple AD groups in our company, into one identity group. So far we've had an identity group for each alias, and we realized that doesn't make sense, as they all carry the same policies.
We are using Terraform in order to maintain and provision our infrastructure.
This is my expected form:
resource "vault_identity_group" "saas-mfi" {
metadata = {
productname = "mfi"
}
name = "saas-mfi"
policies = [
"eaas-key",
"secret-store-mfi"
]
type = "external"
}
resource "vault_identity_group_alias" "alias_1" {
canonical_id = vault_identity_group.saas-mfi.id
mount_accessor = var.org_local_mount_accessor
name = "alias_1"
}
resource "vault_identity_group_alias" "alias_2" {
canonical_id = vault_identity_group.saas-mfi.id
mount_accessor = var.org_local_mount_accessor
name = "alias_2"
}
resource "vault_identity_group_alias" "alias_3" {
canonical_id = vault_identity_group.saas-mfi.id
mount_accessor = var.org_local_mount_accessor
name = "alias_3"
}
When I try to apply this configuration, I get the following error:
Error: Provider produced inconsistent result after apply
Of course, the issue does not stand with the provider. But it seems like one identity group can't have more than one alias to itself. Which is weird, as in the UI, there is a tab for identity groups called "Aliases", in plural.
If anybody has any information regarding this matter, I would really appreciate that.
I was trying to do the same thing but just came across the following paragraph in the documentation for identity:
External group serves as a mapping to a group that is outside of the identity store. External groups can have one (and only one) alias. This alias should map to a notion of group that is outside of the identity store.
From the section on External vs Internal Groups.

Terraform import on aws_s3_bucket asking me both acl=private and grants blocks

I used terraform import to link an aws_s3_bucket resources with the least parameters.
Since the bucket is in my state, it's allow me to reflect the real resource paramters (the first terraform apply failed, but it's intended).
I have some buckets with acl="private" which gave me errors and invite me to add some grants blocks. When i'm doing it, of course terraform gave me two ConflictWith errors since acl and grants cannont be used together.
But if for example i use a s3 bucket with the proper grants blocks, terraform invite me to add an acl="private" statement.
On the same time, I have a strange behavior with the force_destroy = false block. Which seems to be not detected.
Can somebody help me with me ? maybe i'm doing something wrong.
Thanks.
Code example:
resource "aws_s3_bucket" "s3-bucket-example" {
bucket = "s3-bucket-example"
force_destroy = false
grant {
permissions = [
"READ",
"READ_ACP",
"WRITE",
]
type = "Group"
uri = "http://acs.amazonaws.com/groups/s3/LogDelivery"
}
grant {
id = "xxxxxxxxxxxxxxx"
permissions = [
"FULL_CONTROL",
]
type = "CanonicalUser"
}
}
Result
# aws_s3_bucket.s3-bucket-jolivdi-acces will be updated in-place
~ resource "aws_s3_bucket" "s3-bucket-example" {
+ acl = "private"
+ force_destroy = false
id = "s3-bucket-example"
# (7 unchanged attributes hidden)
# (4 unchanged blocks hidden)
}
Your code is absolutely right and working fine.
I had checked the ACLs for the S3 bucket also. The permissions are perfectly applied as written in the terraform code.
If you still have any problems then please elaborate a bit in a comment.

COS access policies interface vs terraform

In interface I can go to COS Bucket Access Policies and easily assign policy that then looks more or less like:
Cloud Object Storage service
serviceInstance string equals foo-bar, resource string equals foo-bar-pcaps, resourceType string equals bucket
I'm struggling to find a way to do the same via terraform because whenever I try with the proper TF code like:
resource "ibm_iam_service_policy" "policy_pcaps" {
iam_service_id = ibm_iam_service_id.serviceID_pcaps.id
roles = ["Writer"]
resources {
service = "cloud-object-storage"
resource = ibm_cos_bucket.pcaps.id
}
}
I'm ending up with
Cloud Object Storage service
resource string equals crn:v1:bluemix:public:cloud-object-storage:global:a/27beaaea79a<redacted>34dd871b:8b124bc6-147c-47ba-bd47-<redacted>:bucket:foo-bar-pcaps:meta:rl:us-east
The problem is that the Writer policy that is required here does not work properly with that policy details.
How to achieve something similar to the first policy with Terraform?
Thanks
You can achieve this similar to this example Service Policy by using attributes.
I created a policy through the UI for Cloud Object Storage and specified the policy to contain a bucket name. Then I used:
ibmcloud iam access-group-policy GROUP_NAME POLICY_ID --output JSON
to get a better understanding of the policy.
With that I created this sample terraform snippet and tested it. It is creating the IAM access group + policy:
resource "ibm_iam_access_group" "accgrp_cos" {
name = "test_cos"
}
resource "ibm_iam_access_group_policy" "policy" {
access_group_id = ibm_iam_access_group.accgrp_cos.id
roles = ["Writer"]
resources {
service = "cloud-object-storage"
attributes = {
resourceType = "bucket"
resource = "tf-test-cos"
}
}
}

How can I create multiple iam users with console logins enabled with terraform

I need to be able to create multiple iam accounts for my developer group with console login enabled using terraform
It's a bit tricky since we have to use keybase when enabling login profiles in terraform. Is there a way to achieve this
variable "iam_users" {
description = "List of iam users that that needs to be created"
type = "list"
}
# values assigned in .tfvars file
iam_users = ["mahela","bhanuka","duminda"]
resource "aws_iam_user_login_profile" "login_profile" {
count = "${length(var.iam_users)}"
user = "${element(var.iam_users,count.index)}"
password_reset_required = true
pgp_key = "keybase:mahela"
}
I cannot get the output for this list of users from below code since count is define in the resource
output "password" {
value = "${aws_iam_user_login_profile.login_profile.encrypted_password}"
}
Do I have to use modules when creating users? with that help to get the output of encrypted password for each user?
Also do I have to use different keybase usernames for each user? this is going to be tricky again :(
When count is set in a resource block, references to that resource in other expressions produce a list of instance objects rather than a single instance object, and so you can't access the instance attributes directly.
If you wish to return a map from user to password then you can write an output expression like the following, assuming you're using Terraform 0.12 or later:
output "passwords" {
value = { for p in aws_iam_user_login_profile.login_profile : p.user => p.encrypted_password }
}
A Terraform 0.11-compatible variant of that would be something like the following:
output "passwords" {
value = "${zipmap(aws_iam_user_login_profile.login_profile.*.user, aws_iam_user_login_profile.login_profile.*.encrypted_password)}"
}

Resources