saidixith002 opened a new pull request, #259:
URL: https://github.com/apache/polaris-tools/pull/259
# Pluggable `CredentialWriter` for principal credentials
## Motivation
`polaris-synchronizer` currently logs newly generated/rotated principal
credentials (`clientId` / `clientSecret`) as **plaintext** directly via slf4j,
in two places:
- `create-omnipotent-principal` — a one-shot banner logged after creating
the omnipotent principal.
- `sync-polaris --sync-principals` — logs credentials for **every**
principal created or overwritten on the target during a sync.
This means secrets always land wherever the logger happens to be configured
(console, log file, log aggregator, CI output, etc.), with no way to redirect
them somewhere safer, and no way to plug in an organization-specific secrets
backend without editing tool internals.
## What changed
Introduces a small, pluggable `CredentialWriter` abstraction — mirroring the
existing `ETagManager` / `ETagManagerFactory` pattern already used in this
module for ETag storage — so credential output is configurable instead of
hardcoded.
- **`CredentialWriter`** (`api/.../access/CredentialWriter.java`): generic
interface (`initialize(properties)`, `writeCredentials(...)`, `AutoCloseable`)
so the destination is decoupled from the tool.
- **`ConsoleCredentialWriter`** (default): reproduces the existing banner
output byte-for-byte — **no behavior change** for existing invocations.
- **`JsonFileCredentialWriter`**: writes credentials as JSON Lines (one
object per principal, flushed immediately) to a file created with owner-only
(`rw-------`) permissions, since it holds plaintext secrets. Supports `append`
for accumulating across runs.
- **`CredentialWriterFactory`**: `CONSOLE` / `FILE` / `CUSTOM` types, with
`CUSTOM` reflectively loading a user-supplied classname — so a future backend
(e.g. a secrets manager) can be added with **zero changes** to this repo, no
new CLI flags required.
- Wired into both `create-omnipotent-principal` and `sync-polaris` via two
new options: `--credential-output-type` (default `CONSOLE`) and
`--credential-output-properties`.
- `PolarisSynchronizer.syncPrincipals()` no longer routes secrets through
`clientLogger` — progress logging (`"Created principal X on target."`) and
credential output are now fully separated.
## Backward compatibility
Default `--credential-output-type=CONSOLE` on both commands preserves the
exact current banner text, logger name, log level, and placement in program
flow. No behavior changes for existing invocations unless the new flags are
explicitly used.
## Testing
- New unit tests: `CredentialWriterFactoryTest`,
`JsonFileCredentialWriterTest` (JSON Lines format, append vs. overwrite
semantics, POSIX file permission enforcement).
- `./gradlew :polaris-synchronizer-api:test :polaris-synchronizer-cli:test`
passes.
- Manually verified end-to-end against two local Apache Polaris instances
(docker-compose, source + target):
- `create-omnipotent-principal` with default `CONSOLE` output — banner
unchanged.
- `create-omnipotent-principal --credential-output-type FILE` — file
created with `600` permissions, valid JSON line with correct
`clientId`/`clientSecret`.
- `sync-polaris --sync-principals --credential-output-type FILE` — output
file accumulates one JSON line per synced principal; confirmed no
`clientSecret` values appear anywhere in `clientLogger` output.
- `--credential-output-type CUSTOM` with a classname — confirmed the
reflective loading path works.
## Checklist
- [x] Existing tests pass
- [x] New tests added for new functionality
- [x] Documentation (`README.md`) updated with new flags and examples
- [x] No behavior change for existing invocations (verified manually)
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]