0
votes
exports.test = functions.https.onRequest(async (req, res) => {
  const file = await admin
    .storage()
    .bucket("XXX")
    .file("YYY");
  await file.makePublic();
  const url = await file.publicUrl();
});

I currently have images set up on Cloud Storage. Because I need to go through the Google Cloud Node.js client library to get access to these, the above code is my current setup. Unfortunately, when running this code, I get the following error:

{
  "error": {
    "code": 401,
    "message": "Anonymous caller does not have storage.objects.getIamPolicy access to the Google Cloud Storage object.",
    "errors": [
      {
        "message": "Anonymous caller does not have storage.objects.getIamPolicy access to the Google Cloud Storage object.",
        "domain": "global",
        "reason": "required",
        "locationType": "header",
        "location": "Authorization"
      }
    ]
  }
}

I'm a little confused because of the following from this (https://firebase.google.com/docs/storage/admin/start) Firebase reference:

You can use the bucket references returned by the Admin SDK in conjunction with the official Google Cloud Storage client libraries to upload, download, and modify content in the buckets associated with your Firebase projects. Note that you do not have to authenticate Google Cloud Storage libraries when using the Firebase Admin SDK. The bucket references returned by the Admin SDK are already authenticated with the credentials used to initialize your Firebase app.

Why do I have to worry about security rules then? More importantly, how do I fix this?

How I initialize the admin SDK:

const serviceAccount = require("./[my-project-name]-8a2aa8e3eedc.json");
admin.initializeApp({ credential: admin.credential.cert(serviceAccount) });

EDIT: added security rules and IAM roles. My security rules:

rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o/images {
    match /listings/{listingId}/{photo} {
      allow read, write: if true;
    }
    match /users/{userId}/{photo} {
      allow read: if true;
      allow write: if request.auth.uid == userId;
    }
  }
}

enter image description here

1
Could you add to the question your Storage Security rules? Also, does the Cloud Functions service account have any IAM storage permissions?Happy-Monad
@Happy-Monad Just updated with bothChris K

1 Answers

0
votes

While the Firebase Admin SDK is not subject to Storage Rules the service account attached to the function running the code still needs to have IAM Storage Permissions, these are separate things. Make sure that the service account for the function has the "Storage Object Admin" IAM role.

On another matter, when trying to reproduce the issue I found out that the method file.publicUrl() is not currently working so you would need to use the getSignedUrl method instead, which by the way is the recommended approach with regards to security concerns. Alternatively (though highly discouraged) you may handcraft the uri yourself.