refactor(server): unify credential storage on Conductor's SecretsDAO#314
Conversation
Follow-up to #312 (already on main). Collapses AgentSpan's bespoke credential SPI into Conductor's SecretsDAO so the Credentials UI, credential resolution, env seeding, and Conductor's own ${workflow.secrets.NAME} substitution all read/write one interface. - Add CredentialsDAO extends com.netflix.conductor.dao.SecretsDAO (adds only listWithMeta() for the Credentials UI); remove the CredentialStoreProvider SPI. - AgentspanSecretsDAO becomes the encrypted store itself: AES-256-GCM over credentials_store via JDBC, with an atomic ON CONFLICT DO UPDATE upsert (fixes an earlier first-write race). Delete EncryptedDbCredentialStoreProvider. - Remove the OSS no-op masking layer (SecretOutputMasker SPI, NoOpSecretOutputMasker, CredentialMaskingResponseAdvice). - Rewire SecretController / CredentialResolutionService / CredentialEnvSeeder onto SecretsDAO / CredentialsDAO. - Build: bump conductor 3.32.0-rc.5 -> rc.6; order mavenLocal before Central; add micrometer-registry-prometheus; HTTP/LLM worker threads. Known issue (to be addressed separately): the agentspan.embedded default (false->true) and four @ConditionalOnProperty gates were flipped together, inverting the flag vs. its documentation. NativeSecretGatingTest and ProviderStatusEndpointTest fail as a result (both pass on main).
| ResponseEntity<?> err = validateKey(key); | ||
| if (err != null) return ResponseEntity.status(err.getStatusCode()).build(); | ||
| String value = storeProvider.get(key); | ||
| log.info("AUDIT get-secret: userId={} key={} found={}", currentUserId(), key, value != null); |
There was a problem hiding this comment.
All three operations - get, put, delete lost their audit lines, is this intentional?
|
Summary
Splits the server-module changes out of
feat/embedded-secrets-sdk-taskdefinto a standalone PR (the SDK/python-submodule changes are not included here).This is a follow-up to #312 (already on
main). It collapses AgentSpan's bespoke credential SPI into Conductor'sSecretsDAO, so the Credentials UI, credential resolution, env seeding, and Conductor's own${workflow.secrets.NAME}substitution all go through one interface.Changes
CredentialsDAO extends com.netflix.conductor.dao.SecretsDAO— adds onlylistWithMeta()(name + partial value + timestamps for the Credentials UI). Replaces theCredentialStoreProviderSPI.AgentspanSecretsDAObecomes the encrypted store itself — AES-256-GCM ([12-byte IV][ciphertext+tag]) over thecredentials_storetable viaNamedParameterJdbcTemplate, with an atomicON CONFLICT(user_id, name) DO UPDATEupsert (fixes an earlier UPDATE-then-INSERT first-write race).EncryptedDbCredentialStoreProvideris deleted.SecretOutputMaskerSPI,NoOpSecretOutputMasker, andCredentialMaskingResponseAdvice(all OSS no-ops).SecretController,CredentialResolutionService,CredentialEnvSeedernow depend onSecretsDAO/CredentialsDAOdirectly.