-
Notifications
You must be signed in to change notification settings - Fork 0
Ux 457/sj/impersonation role sync script #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Implements a new CLI/tooling layer to migrate/sync Redpanda Cloud roles (and their principals/ACLs) to dataplane (Core) clusters, plus supporting pagination, interceptors, and typed ACL/role utilities.
- Adds generic pagination utilities and comprehensive tests.
- Introduces Cloud and Dataplane API clients, migration logic (IdentityMigrator), and CLI with ACL configuration.
- Provides retry/auth interceptors, CI workflow, and documentation (README, env example, ACL TOML).
Reviewed Changes
Copilot reviewed 20 out of 27 changed files in this pull request and generated 12 comments.
Show a summary per file
File | Description |
---|---|
src/utils/pagination.ts | Generic pagination helpers with accumulation strategies. |
src/utils/pagination.test.ts | Unit tests covering pagination behaviors. |
src/types/index.ts | Exposes core domain types and config interfaces. |
src/types/acl-config.ts | Strongly typed ACL configuration schema. |
src/sync-role.ts | Migration/sync orchestration of roles, principals, and ACL application. |
src/sync-role.test.ts | Tests for migrator cluster selection and basic migration paths. |
src/interceptors.ts | Auth and retry interceptors for ConnectRPC. |
src/interceptors.test.ts | Unit tests for interceptor behavior and combinations. |
src/clients/dataplane-client.ts | Dataplane client for roles, ACL creation, and membership sync. |
src/clients/cloud-client.ts | Cloud client for clusters, roles, bindings, users, SAs, with pagination usage. |
src/cli.ts | CLI command definitions, flag parsing, interactive prompts, ACL confirmation. |
src/index.ts | Library entrypoint exports. |
package.json | Project metadata, scripts, dependencies, build targets. |
biome.json | Linting/formatting configuration. |
acls.toml | ACL definition (currently only admin role). |
README.md | Comprehensive usage and operations documentation. |
.github/workflows/ci.yml | CI tasks for lint, test, build integrity. |
.env.example | Environment variable template. |
.bunfig.toml / .npmrc | Tooling and registry configuration. |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
src/clients/cloud-client.ts
Outdated
async getRoleBindings(): Promise<RoleBinding[]> { | ||
try { | ||
return paginateToArray( | ||
{ filter: { roleName: 'Admin' } }, | ||
(request) => this.roleBindingClient.listRoleBindings(request), | ||
(response) => response.roleBindings, | ||
{ requestName: 'Role bindings' } | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method hard‑codes a filter for roleName 'Admin', so downstream logic (e.g., getRolesWithPrincipals expecting Admin, Writer, Reader) will never see bindings for Writer or Reader. Remove or parameterize this filter (or fetch unfiltered) so all target roles are discoverable.
Copilot uses AI. Check for mistakes.
src/sync-role.ts
Outdated
console.log('📋 Target roles for migration:'); | ||
const targetRoles = ['Admin', 'Writer', 'Reader']; | ||
targetRoles.forEach((role) => { | ||
console.log(` - ${role}`); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The targetRoles array is only used for logging and not for filtering or validation; this can cause misleading output if upstream discovery fails to include some roles. Either enforce filtering based on this list or remove it to avoid implying those roles were considered in the actual migration loop.
Copilot uses AI. Check for mistakes.
[roles.admin] | ||
description = "Full administrative access to all cluster resources" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only the admin role is defined here, but the codebase (e.g., migration and discovery logic) references Writer and Reader roles; absence will trigger warnings and skip ACL creation for those roles. Either add writer/reader sections or adjust docs and logic to reflect that only admin ACLs are currently supported.
Copilot uses AI. Check for mistakes.
resource_name = "*" | ||
resource_pattern_type = "LITERAL" | ||
operation = "ALL" | ||
permission_type = "ALLOW" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only the admin role is defined here, but the codebase (e.g., migration and discovery logic) references Writer and Reader roles; absence will trigger warnings and skip ACL creation for those roles. Either add writer/reader sections or adjust docs and logic to reflect that only admin ACLs are currently supported.
permission_type = "ALLOW" | |
permission_type = "ALLOW" | |
host = "*" | |
[roles.writer] | |
description = "Write access to topics and groups" | |
[[roles.writer.acls]] | |
resource_type = "TOPIC" | |
resource_name = "*" | |
resource_pattern_type = "LITERAL" | |
operation = "WRITE" | |
permission_type = "ALLOW" | |
host = "*" | |
[[roles.writer.acls]] | |
resource_type = "GROUP" | |
resource_name = "*" | |
resource_pattern_type = "LITERAL" | |
operation = "WRITE" | |
permission_type = "ALLOW" | |
host = "*" | |
[roles.reader] | |
description = "Read access to topics and groups" | |
[[roles.reader.acls]] | |
resource_type = "TOPIC" | |
resource_name = "*" | |
resource_pattern_type = "LITERAL" | |
operation = "READ" | |
permission_type = "ALLOW" | |
host = "*" | |
[[roles.reader.acls]] | |
resource_type = "GROUP" | |
resource_name = "*" | |
resource_pattern_type = "LITERAL" | |
operation = "READ" | |
permission_type = "ALLOW" |
Copilot uses AI. Check for mistakes.
messages.push(` 👤 Principal: RedpandaRole:__redpanda_cloud_role_${roleType}`); | ||
messages.push(` 📊 Total ACL entries: ${roleConfig.acls.length}`); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The principal displayed assumes the internal prefixed role name; ensure README and user guidance clarify this generated principal format, especially since the user supplies unprefixed role names (Admin/Writer/Reader). If mismatch is intentional, add a short clarification in the CLI help output.
Copilot uses AI. Check for mistakes.
console.log(`📤 Syncing membership for role: ${roleName}`); | ||
console.log(' Target principals:', principals); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duplicate logging of 'Target principals:' (lines 133 and 146) adds noise; remove one occurrence.
Copilot uses AI. Check for mistakes.
); | ||
const normalizedTargetMembers = new Set(principals); | ||
|
||
console.log(' Target principals:', principals); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duplicate logging of 'Target principals:' (lines 133 and 146) adds noise; remove one occurrence.
console.log(' Target principals:', principals); |
Copilot uses AI. Check for mistakes.
"main": "src/index.ts", | ||
"bin": { | ||
"redpanda-migration": "./redpanda-migration" | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The declared bin path ./redpanda-migration does not correspond to any generated artifact (build scripts output unified-identity-toolkit* in out/*) and main points to TypeScript sources without a build pipeline for consumers. Provide a compiled JS entry (e.g., dist/index.js), align bin to an existing file (or add a wrapper script), or adjust build scripts to produce the declared binary name at project root.
Copilot uses AI. Check for mistakes.
package.json
Outdated
"build": "npm run build:linux", | ||
"build:js": "bun build --target node --sourcemap --bundle --outdir dist src/cli.ts", | ||
"build:linux": "mkdir -p out/linux && bun build --compile --minify --sourcemap --target bun-linux-x64 src/cli.ts --outfile out/linux/unified-identity-toolkit", | ||
"build:macos": "mkdir -p out/macos && bun build --compile --minify --sourcemap --target bun-darwin-x64 src/cli.ts --outfile out/macos/unified-identity-toolkit", | ||
"build:windows": "mkdir -p out/windows && bun build --compile --minify --sourcemap --target bun-windows-x64 src/cli.ts --outfile out/windows/unified-identity-toolkit.exe", | ||
"build:all": "npm run build:linux && npm run build:macos && npm run build:windows", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The declared bin path ./redpanda-migration does not correspond to any generated artifact (build scripts output unified-identity-toolkit* in out/*) and main points to TypeScript sources without a build pipeline for consumers. Provide a compiled JS entry (e.g., dist/index.js), align bin to an existing file (or add a wrapper script), or adjust build scripts to produce the declared binary name at project root.
"build": "npm run build:linux", | |
"build:js": "bun build --target node --sourcemap --bundle --outdir dist src/cli.ts", | |
"build:linux": "mkdir -p out/linux && bun build --compile --minify --sourcemap --target bun-linux-x64 src/cli.ts --outfile out/linux/unified-identity-toolkit", | |
"build:macos": "mkdir -p out/macos && bun build --compile --minify --sourcemap --target bun-darwin-x64 src/cli.ts --outfile out/macos/unified-identity-toolkit", | |
"build:windows": "mkdir -p out/windows && bun build --compile --minify --sourcemap --target bun-windows-x64 src/cli.ts --outfile out/windows/unified-identity-toolkit.exe", | |
"build:all": "npm run build:linux && npm run build:macos && npm run build:windows", | |
"build": "npm run build:linux && npm run build:bin", | |
"build:js": "bun build --target node --sourcemap --bundle --outdir dist src/cli.ts", | |
"build:linux": "mkdir -p out/linux && bun build --compile --minify --sourcemap --target bun-linux-x64 src/cli.ts --outfile out/linux/unified-identity-toolkit", | |
"build:macos": "mkdir -p out/macos && bun build --compile --minify --sourcemap --target bun-darwin-x64 src/cli.ts --outfile out/macos/unified-identity-toolkit", | |
"build:windows": "mkdir -p out/windows && bun build --compile --minify --sourcemap --target bun-windows-x64 src/cli.ts --outfile out/windows/unified-identity-toolkit.exe", | |
"build:all": "npm run build:linux && npm run build:macos && npm run build:windows", | |
"build:bin": "cp out/linux/unified-identity-toolkit ./redpanda-migration", |
Copilot uses AI. Check for mistakes.
README.md
Outdated
- **Linux**: `redpanda-toolkit-linux` | ||
- **macOS**: `redpanda-toolkit-macos` | ||
- **Windows**: `redpanda-toolkit-windows.exe` | ||
|
||
Make the binary executable (Linux/macOS): | ||
```bash | ||
chmod +x redpanda-toolkit-linux |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Binary names here do not match build outputs (unified-identity-toolkit* in package.json scripts) or the declared npm bin (redpanda-migration). Update the README or rename build artifacts for consistency to prevent user confusion.
- **Linux**: `redpanda-toolkit-linux` | |
- **macOS**: `redpanda-toolkit-macos` | |
- **Windows**: `redpanda-toolkit-windows.exe` | |
Make the binary executable (Linux/macOS): | |
```bash | |
chmod +x redpanda-toolkit-linux | |
- **Linux**: `unified-identity-toolkit-linux` | |
- **macOS**: `unified-identity-toolkit-macos` | |
- **Windows**: `unified-identity-toolkit-windows.exe` | |
Make the binary executable (Linux/macOS): | |
```bash | |
chmod +x unified-identity-toolkit-linux |
Copilot uses AI. Check for mistakes.
24d1607
to
8552ca2
Compare
.github/workflows/ci.yml
Outdated
|
||
steps: | ||
- name: Checkout code | ||
uses: actions/checkout@v4 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can also use @v5. it was released 2 months ago
f0b1267
to
59a5175
Compare
.npmrc
Outdated
# Enable package-lock generation | ||
package-lock=true No newline at end of file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this? We use yarn.lock
already it seems, I think this setting is for package-lock.json
specifically.
"check": "biome check .", | ||
"check:fix": "biome check --write .", | ||
"type-check": "tsc --noEmit", | ||
"clean": "rm -rf dist out" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we need to support different arch, we can consider using rimraf
package.json
Outdated
"node": ">=18.0.0" | ||
}, | ||
"scripts": { | ||
"build": "npm run build:linux", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe use bun
everywhere instead of npm
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think in subsequent PRs we could consider moving this to inkjs (React for CLIs)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I thought about it, but today, it's very simple.
* Unit tests for ConnectRPC interceptors | ||
*/ | ||
|
||
import { beforeEach, describe, expect, jest, test } from 'bun:test'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really cool you could manage to get bun:test
working, it improved a lot recently.
@@ -0,0 +1,13 @@ | |||
# Redpanda Cloud API Token (required) | |||
# Get this bearer token from your Redpanda Cloud organization settings | |||
REDPANDA_CLOUD_API_TOKEN=your-cloud-api-bearer-token-here |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be useful if you could set up a service account credentials, since tokens expire
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tought about it bt wanted to keep it small and simple initially
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are we versioning this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, it will be semver with tags, for next PR
/** | ||
* Convenience function for paginating into an array | ||
*/ | ||
export async function paginateToArray< |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Weird name, ListAllPages maybe?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can also paginate to Map hehe
src/utils/pagination.ts
Outdated
let pageCount = 0; | ||
let totalResults = 0; | ||
|
||
do { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This got to be the frist time I see a do
implemented in ts
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
x2
"build:macos": "mkdir -p out/macos && bun build --compile --minify --sourcemap --target bun-darwin-x64 src/cli.ts --outfile out/macos/unified-identity-toolkit", | ||
"build:windows": "mkdir -p out/windows && bun build --compile --minify --sourcemap --target bun-windows-x64 src/cli.ts --outfile out/windows/unified-identity-toolkit.exe", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do you need this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe windows is not important, but I want to have completeness, what's the concern?
src/utils/pagination.ts
Outdated
let pageCount = 0; | ||
let totalResults = 0; | ||
|
||
do { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
x2
{ | ||
name: 'Admin - Full administrative access to cluster', | ||
value: 'Admin', | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
don't you need the reader and writer options here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Initially I want to focus only on the Admin Role, but eventually yes .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Basic bun setup with ci and bun well known configurations Signed-off-by: santiago <[email protected]>
59a5175
to
617d200
Compare
Install bun dependencies, make sure all necessary deps are installed Signed-off-by: santiago <[email protected]>
617d200
to
e3ec89c
Compare
implement simple sync cli for redpada roles Signed-off-by: santiago <[email protected]>
Basic testing for the cli Signed-off-by: santiago <[email protected]>
Signed-off-by: santiago <[email protected]>
Implement JS bundle so the execution of the cli is very simple Signed-off-by: santiago <[email protected]>
e3ec89c
to
bafeccd
Compare
Implement Cli for reconciling redpanda roles based on controlplane roles