To complete this transfer, you need the 'storage.buckets.setIamPolicy' permission for the source bucket - google-cloud-storage

I am getting this error when trying to create a "transfer" to transfer the contents of one bucket in Google Cloud to another bucket in Google Cloud under the same owner:
To complete this transfer, you need the 'storage.buckets.setIamPolicy' permission for the source bucket. Ask the bucket's administrator to grant you the required permission and try again.
I have no idea what I'm supposed to do. I tried going to "Bucket -> Permissions -> Add Members -> myemail.com for Storage -> ...Admin" but I just keep getting "IAM policy update failed".
Please help on what to do to get this working so I can make my files publicly accessible.
I am using Node.js if that helps.
If I even try to fetch the photo and bypass it directly, I can't even do that :/
const { Storage } = require('#google-cloud/storage')
const storage = new Storage({
projectId: 'my-bucket'
})
const bucket = storage.bucket('my.bucket')
app.get('/photo/:photo.:ext', (req, res) => {
const remoteFile = bucket.file(`photo/${req.params.photo}.${req.params.ext}`)
remoteFile.createReadStream().pipe(res)
})
Can't do this either:
const opts = {
includeFiles: true
};
bucket.makePublic(opts, function(err, files) {
// `err`:
// The first error to occur, otherwise null.
//
// `files`:
// Array of files successfully made public in the bucket.
console.log(arguments)
});
Cannot get legacy ACLs for a bucket that has enabled Bucket Policy Only. Read more at https://cloud.google.com/storage/docs/bucket-policy-only.
$ gsutil iam ch allUsers:objectViewer gs://my.bucket
ServiceException: 401 Anonymous caller does not have storage.buckets.getIamPolicy access to my.bucket.

The error clearly indicates a missing permission on the Source bucket. I recommend you confirm that the Owner on the Source bucket has the Permission, storage.objects.getIamPolicy(IAM&admin --> IAM Menu --> Filter by the Owner's email address --> check the role on it). Then, you can check if the roles has that permission, storage.objects.getIamPolicy (go to IAM&admin -->Roles and then, search for specific role --> Click on it and it would show the list of assigned permission. Ensure that storage.objects.getIamPolicy is one of the permissions listed for the Role
Meanwhile, for you to be able to grant access to specific buckets, your account role must be a Storage Admin. So, if your account does not have that role, you would need someone that has that role to be able to grant access or have other control over the bucket

I expect you have found a solution to this on your own.
But for anyone getting the same error message i got this when trying to set up a transfer from the cloud console. I had done a transfer before between these two storage buckets and not changed the name of the transfer, so the second time trying this the suggested name was the same as the previous. I changed the transfer name to a unique one and that solved the issue for me.
No idea why i kept getting this error message as permissions was not part of the problem.

Related

How can I access a file of storage with dart Google Storage API

I'm trying to get information of a file that is inside of a folder in Google cloud Storage (not firebase storage). But the API of it in Dart language is not complete, it doesn't have a function to show the blob (file) information like we have in python same API. I just need to access the name of the file. Here's my code:
var credentials = auth.ServiceAccountCredentials.fromJson({
"type": "service_account",
...
});
List<String> scopes = []..addAll(Storage.SCOPES);
var client = await auth.clientViaServiceAccount(credentials, scopes);
var storage = Storage(client, "project_name");
var bucket = storage.bucket("Bucket_name");
var list = await bucket.read("folder_name/");
list.forEach((element) {
print(element.toString());
});
It has a lot of options like toList(),toSet(), asBroadcastStream() and etc. But any of these return me what I need. Some ones just return a empty list, that doesn't make sence for me.
Anyways, if someone know how to read data from a folder of GCP storage, please anwser me. Sorry for my english and Thanks!
The API docs: https://pub.dev/documentation/gcloud/latest/gcloud.storage/gcloud.storage-library.html
For you backend, you can use bucket.list(prefix: "folder_name/","") as described in the documentation:
Listing operates like a directory listing, despite the object namespace being flat. Unless delimiter is specified, the character / is being used to separate object names into directory components. To list objects recursively, the delimiter can be set to empty string.
For the front end, forget this! You can't provide a service account key file in your frontend! If you share the secret publicly, it's like if you set your bucket public!
So, for this, you need to have a backend that authenticated the user and generate a signed URL to read and write inside the bucket.
bucket.read() gets the contents of individual objects. If you want to get the object names, use bucket.list().

Service Account for google sheets returns not found

I am trying to read a spreadsheet using a service account (I cannot use OAuth, which works, since the process will be running on a server to periodically check sheet data)
I tried several approaches. If I follow the example using oauth I can see the sheet values. However, I need the run the script without any GUI on the background.
I have found this tutorial https://github.com/juampynr/google-spreadsheet-reader
I have created a projec, service account, added viewer role, shared the spreadsheet with the service account email. Generated the key.
It seems that the test program can connect to the google services but the moment it request the spreadsheet the end result is "404 not found".
require 'vendor/autoload.php';
$service_account_file = '/secrets/readsheetmar2019-08b737d1c1cb._portfolio_test.json';
$spreadsheet_id = '1TAWybckPrnWlQxBZh0ScDsFOvftwi2dvTBNGarSdY30';
$spreadsheet_range = '';
putenv('GOOGLE_APPLICATION_CREDENTIALS=' . $service_account_file);
$client = new Google_Client();
$client->useApplicationDefaultCredentials();
$client->addScope(Google_Service_Sheets::SPREADSHEETS_READONLY);
$client->fetchAccessTokenWithAssertion();
$service = new Google_Service_Sheets($client);
//added by me
if ($client->isAccessTokenExpired()) {
print "expired\n";
}else{
print "not expired\n";
}
$result = $service->spreadsheets_values->get($spreadsheet_id, $spreadsheet_range);
var_dump($result->getValues());
Error:PHP Fatal error: Uncaught exception 'Google_Service_Exception' with message '
Error 404 (Not Found)!!1
When the access token retrieved by OAuth2 is used, the Spreadsheet of $spreadsheet_id = '1TAWybckPrnWlQxBZh0ScDsFOvftwi2dvTBNGarSdY30'; can retrieve the values.
When the access token retrieved by Service Account is used, Error 404 (Not Found)!!1 is returned.
If my understanding is correct, please confirm the following points.
Confirmation points:
As a test run, please set the range $spreadsheet_range = '';.
For example, it's $spreadsheet_range = 'Sheet1'.
If the error message of The caller does not have permission is returned, please confirm as follows.
Whether the Spreadsheet of 1TAWybckPrnWlQxBZh0ScDsFOvftwi2dvTBNGarSdY30 is sharing the email of Service Account.
If you didn't share the Service Account to the Spreadsheet, please share the email of client_email in the file of readsheetmar2019-08b737d1c1cb._portfolio_test.json to the Spreadsheet you want to access.
If the error message of Google Sheets API has not been used in project ### before or it is disabled. is returned, please enable Sheets API.
If this was not the solution for your issue, I apologize.

AADSTS50034: The user account Microsoft.AzureAD.Telemetry.Diagnostics.PII does not exist in the xxx.onmicrosoft.com directory

I am trying to use graph.microsft.com apis for user invinting to the AD account.
I was able to invite but when try to get the token using
https://login.microsoftonline.com/xxxx.onmicrosoft.com/oauth2/token i am getting the above error.
I am using this key along with other required keys in the header.
[{"key":"resource","value":"https://graph.microsoft.com","description":""}]
Can you please let me know what is the issue?
Complete log.
{
"error": "invalid_grant",
"error_description": "AADSTS50034: The user account Microsoft.AzureAD.Telemetry.Diagnostics.PII does not exist in the xxxxx.onmicrosoft.com directory. To sign into this application, the account must be added to the directory.\r\nTrace ID: 5537uiy4b-4473-4cfb-b45c-1281f61e2100\r\nCorrelation ID: 8121era7-8df4-47d5-8cc5-3d2f8371029b0\r\nTimestamp: 2019-02-26 11:04:46Z",
"error_codes": [
50034
],
"timestamp": "2019-02-26 11:04:46Z",
"trace_id": "5537db4b-4473-4cfb-b45c-1281f61e2100",
"correlation_id": "812138a7-8df4-47d5-8cc5-3d2f8a1029b0"
}
On my side, I ever encountered this error. For this error, you need to check the user account that you used, the user type must be member in your Azure AD tenant, cannot be guest.

How to get the current user using jsonwebtoken in Sails.js?

I've been working with Sails since couple of weeks ago, I came from Rails and I don't have any experience working with Node.js.
Now I'm trying to make a robust token authentication using jsonwebtoken.
https://github.com/auth0/node-jsonwebtoken
I followed this guide http://thesabbir.com/how-to-use-json-web-token-authentication-with-sails-js/ and everything worked fine.
I'm able to make a sign up, sign in and then use the token correctly for different actions.
Now, there are some actions where I'd like to use the login user,
something like devise current_user helper.
For example, when creating a comment, this comment should belongs to the current user.
Using Sabbir Ahmed guide, in the line 33 from the isAuthorized.js policy the token gets decrypted so I can get the current user id from there.
So, my question is, what should be the best way to get the current user and be able to use it later in some controller?
For example I tried something like:
# isAuthorized.js line 34, after getting decrypted token
User.findOne({id: token.id}).exec(function findOneCB(err, found){
currentUser = found;
});
But, on this way, because this is an async action I can't use this currentUser in a controller.
I want to store the current user in order to be able to use it later in some controller without repeated the same code in each controller, something like a helper or maybe a service.
The trick is where you place the next(). Since you are making an async call, the control should only be transferred to next policy/ controller once the database action is competed.
You should modify the policy to:
User.findOne({id: token.id}).exec(function findOneCB(err, found){
if(err) next(err);
req.currentUser = found;
next();
});
And you should be able to access the user details in controllers that use isAuthorized policy via req.currentUser
If by
For example, when creating a comment, this comment should belongs to the current user.
what you mean is certain attributes like username, and country etc, rather than querying the database after verification, what you can choose to do is to send these additional attributes to jwToken.issue in api/controllers/UsersController.js
eg.
jwToken.issue({
id: user.id,
username: user.name,
country: user.country
})
How that helps is, you can keep api/policies/isAuthorized.js as is, and in all the controllers that you use in the future, you can access the payload values from as
token.username or token.country
Instead of having to query the database again, thereby saving you valuable response time.
Beware however, of the data you choose to send in the token (you could also send {user:user} if you want to) however, as the secret key or hashing is not required to decrypt the payload as you can figure # jwt.io , you might want to exercise restraint.

MembershipReboot with IdentityServer v3

I am having trouble extracting UserAccount properties from MembershipReboot in conjunction with Thinktecture IdentityServer. I have both up and running using the Sample repo here: https://github.com/identityserver/IdentityServer3.MembershipReboot
When I request the "openid profile" scope in an Implicit Grant Flow, I am missing a lot of the user account fields such as "given_name, middle_name", etc from the id_token and response from the userinfo endpoint. I understand this is because they need to be assigned in the GetClaimsFromAccount function.
I can see the requestedClaims come into the GetProfileDataAsync() function in the MembershipRebootUserService class and if I hover over the instance of TAccount in GetClaimsFromAccount I can see the Firstname, Lastname, etc properties appearing in the CustomUser dynamic proxy but I can't for the life of me work out how to access them and copy them into the claims collection?
More Info:
I suspect the issue is with this line:
claims.AddRange(userAccountService.MapClaims(account));
It looks like this should be converting the user account properties into claims but I dont get any back.
The way I understand it works is you add an option to your Scope object to return all of the claims for a user. IncludeAllClaimsForUser is the key property.
e.g.
new Scope
{
Enabled = true,
Name = "roles",
Type = ScopeType.Identity,
IncludeAllClaimsForUser = true,
Claims = new List<ScopeClaim>
{
new ScopeClaim("role")
}
}
My request includes the role property as well. This pulled back all the claims for the user from MR for me. My example is with Implicit flow btw.