Skip to content

Conversation

@inlined
Copy link
Member

@inlined inlined commented Mar 24, 2025

Part of the new work to encourage the use of test secrets in the emulator.

Unfortunately there is no general API to figure out whether an email address is a service account, user, or group. Fortunately, IAM will return an error with a clear message on what type of principal the secret was on error so we can brute force our way to success ¯_(ツ)_/¯

@inlined inlined requested a review from taeold March 24, 2025 16:33
@inlined inlined force-pushed the inlined.grantaccess-user branch from 89a7a5b to 57f26df Compare March 24, 2025 16:51
@inlined inlined requested review from annajowang and mathu97 March 24, 2025 18:13
}

/**
* Grants the following users or grouips access to the provided secret.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Grants the following users or grouips access to the provided secret.
* Grants the following users or groups access to the provided secret.

existingBindings = (await gcsm.getIamPolicy({ projectId, name: secretName })).bindings || [];
} catch (err: unknown) {
throw new FirebaseError(
`Failed to get IAM bindings on secret: ${secretName}. Ensure you have the permissions to do so and try again.`,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if we link to https://cloud.google.com/secret-manager/docs/manage-access-to-secrets#required-roles to guide the users a little more here?

I'd love to link to a Firebase doc, but seems like we don't have a doc.

)
.option("-l, --location <location>", "backend location", "-")
.option("-b, --backend <backend>", "backend name")
.option("-u, --emails <emails>", "comma delmited list user or group emails")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Want to update the short flag too or keep it?

Suggested change
.option("-u, --emails <emails>", "comma delmited list user or group emails")
.option("-e, --emails <emails>", "comma delmited list user or group emails")

)
.option("-l, --location <location>", "backend location", "-")
.option("-b, --backend <backend>", "backend name")
.option("-u, --emails <emails>", "comma delmited list user or group emails")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
.option("-u, --emails <emails>", "comma delmited list user or group emails")
.option("-u, --emails <emails>", "comma delimited list user or group emails")

const accounts = secrets.toMulti(secrets.serviceAccountsForBackend(projectNumber, backend));

await secrets.grantSecretAccess(projectId, projectNumber, secretName, accounts);
await Promise.all(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer Promise.allSettled?

.description("grant service accounts permissions to the provided secret")
export const command = new Command("apphosting:secrets:grantaccess <secretNames>")
.description(
"grant service accounts permissions to the provided secret(s). Can pass one or more secrets, separated by a comma",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"grant service accounts permissions to the provided secret(s). Can pass one or more secrets, separated by a comma",
"grant service accounts or users permissions to the provided secret(s). Can pass one or more secrets, separated by a comma",

const accounts = secrets.toMulti(secrets.serviceAccountsForBackend(projectNumber, backend));

await Promise.all(
await Promise.allSettled(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wanna explicitly handle errors here?

Or we could just go back to using Promise.all() instead... 🤷🏼

e.g.

const results = await Promise.allSettled(
  secretList.map((secretName) => 
    secrets.grantSecretAccess(projectId, projectNumber, secretName, accounts)
  )
);

const failures = results.filter(result => result.status === 'rejected');
if (failures.length > 0) {
  throw new Error(`Failed to grant access to ${failures.length}/${results.length} secrets`);
 }

@inlined inlined merged commit 9018326 into master Mar 24, 2025
52 of 55 checks passed
@inlined inlined deleted the inlined.grantaccess-user branch March 24, 2025 18:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants