Enable opt-in Google Workspace accounts for maintainers
Adds a google config with provisionUser to the MAINTAINERS role. Runtime provisioning already gates on firstName/lastName/googleEmailPrefix, so maintainers opt in by sending a PR adding those fields to their entry in users.ts. Missing fields means no account is created. Relaxes the validator and tests to treat missing GWS fields as implicit opt-out rather than a hard error, so existing maintainers do not need skipGoogleUserProvisioning set up front. Also documents the opt-in flow in the README.
This commit is contained in:
parent
c96a52bb95
commit
9ecc452da6
4 changed files with 23 additions and 10 deletions
18
README.md
18
README.md
|
|
@ -11,6 +11,24 @@ Infrastructure as Code for managing access to MCP community resources using Pulu
|
||||||
- **GitHub Teams**: Automatically syncs team memberships in the MCP GitHub organization
|
- **GitHub Teams**: Automatically syncs team memberships in the MCP GitHub organization
|
||||||
- **Google Workspace Groups**: Automatically syncs group memberships for @modelcontextprotocol.io email accounts
|
- **Google Workspace Groups**: Automatically syncs group memberships for @modelcontextprotocol.io email accounts
|
||||||
- **Email Groups**: Groups with `isEmailGroup: true` accept emails from anyone (including external users) and notify all members. External posts are moderated for security.
|
- **Email Groups**: Groups with `isEmailGroup: true` accept emails from anyone (including external users) and notify all members. External posts are moderated for security.
|
||||||
|
- **Google Workspace User Accounts**: Provisions @modelcontextprotocol.io accounts for members of roles with `provisionUser: true`
|
||||||
|
|
||||||
|
### Opting in to a Google Workspace account (maintainers)
|
||||||
|
|
||||||
|
If you're a maintainer and want an `@modelcontextprotocol.io` account, open a PR adding the following fields to your entry in [`src/config/users.ts`](src/config/users.ts):
|
||||||
|
|
||||||
|
```ts
|
||||||
|
{
|
||||||
|
github: 'your-github-username',
|
||||||
|
// ...
|
||||||
|
firstName: 'Your',
|
||||||
|
lastName: 'Name',
|
||||||
|
googleEmailPrefix: 'yourname', // -> yourname@modelcontextprotocol.io
|
||||||
|
memberOf: [ROLE_IDS.MAINTAINERS /* , ... */],
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
Once merged, Pulumi provisions the account. An admin will share your initial password (retrievable via `pulumi stack output --show-secrets newGWSUserPasswords`).
|
||||||
|
|
||||||
## Deployment
|
## Deployment
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -99,7 +99,7 @@ test('googleEmailPrefix values are unique', () => {
|
||||||
return prefixes.length === new Set(prefixes).size;
|
return prefixes.length === new Set(prefixes).size;
|
||||||
});
|
});
|
||||||
|
|
||||||
test('ProvisionUser members are explicit: fields present or skip flag set', () => {
|
test('skipGoogleUserProvisioning is only used in provisionUser roles and without fields', () => {
|
||||||
const provisionRoleIds = new Set(ROLES.filter((r) => r.google?.provisionUser).map((r) => r.id));
|
const provisionRoleIds = new Set(ROLES.filter((r) => r.google?.provisionUser).map((r) => r.id));
|
||||||
return MEMBERS.every((member) => {
|
return MEMBERS.every((member) => {
|
||||||
const inProvisionRole = member.memberOf.some((id) => provisionRoleIds.has(id));
|
const inProvisionRole = member.memberOf.some((id) => provisionRoleIds.has(id));
|
||||||
|
|
@ -110,7 +110,7 @@ test('ProvisionUser members are explicit: fields present or skip flag set', () =
|
||||||
member.lastName &&
|
member.lastName &&
|
||||||
member.googleEmailPrefix
|
member.googleEmailPrefix
|
||||||
);
|
);
|
||||||
return hasProvisioningFields !== !!member.skipGoogleUserProvisioning;
|
return !(hasProvisioningFields && member.skipGoogleUserProvisioning);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -154,13 +154,6 @@ console.log('Validating Google Workspace user provisioning fields...');
|
||||||
);
|
);
|
||||||
hasErrors = true;
|
hasErrors = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inProvisionUserRole && !hasProvisioningFields && !member.skipGoogleUserProvisioning) {
|
|
||||||
console.error(
|
|
||||||
`ERROR: Member "${memberId}" is in a provisionUser role but is missing Google user fields. Add fields or set skipGoogleUserProvisioning: true`
|
|
||||||
);
|
|
||||||
hasErrors = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,9 @@ export const ROLES: readonly Role[] = [
|
||||||
id: ROLE_IDS.MAINTAINERS,
|
id: ROLE_IDS.MAINTAINERS,
|
||||||
description: 'General maintainers',
|
description: 'General maintainers',
|
||||||
discord: { role: 'maintainers (synced)' },
|
discord: { role: 'maintainers (synced)' },
|
||||||
// Discord only - general maintainer role
|
// GWS user accounts are opt-in: maintainers add firstName/lastName/googleEmailPrefix
|
||||||
|
// to their entry in users.ts via PR to get an @modelcontextprotocol.io account
|
||||||
|
google: { group: 'maintainers', provisionUser: true },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: ROLE_IDS.DOCS_MAINTAINERS,
|
id: ROLE_IDS.DOCS_MAINTAINERS,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue