feat: Add generic Core gRPC proxy and BMC credential endpoints#2477
feat: Add generic Core gRPC proxy and BMC credential endpoints#2477kfelternv wants to merge 2 commits into
Conversation
|
Auto-sync is disabled for draft pull requests in this repository. Workflows must be run manually. Contributors can view more details about this message here. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Enterprise Run ID: 📒 Files selected for processing (4)
🚧 Files skipped from review as they are similar to previous changes (4)
Summary by CodeRabbit
WalkthroughIntroduces a generic Temporal-based gRPC proxy infrastructure that routes REST API calls to on-site NICo Core gRPC methods with AES-encrypted secret redaction in Temporal history. Implements a new ChangesGeneric Core gRPC Proxy with BMC Credential Endpoint
Sequence DiagramsequenceDiagram
participant Client
participant SetBMCCredentialHandler
participant ExecuteCoreGRPC
participant TemporalCloud as Temporal (Cloud)
participant InvokeCoreGRPCOnSite as InvokeCoreGRPCOnSite Activity
participant CoreGrpcClient
rect rgba(70, 130, 180, 0.5)
note over SetBMCCredentialHandler: Authorization & Validation
Client->>SetBMCCredentialHandler: PUT /org/:orgName/nico/credential/bmc
SetBMCCredentialHandler->>SetBMCCredentialHandler: Validate APIBMCCredentialRequest
SetBMCCredentialHandler->>SetBMCCredentialHandler: authorizeSite → ProviderAdminRole + siteId check
end
rect rgba(60, 179, 113, 0.5)
note over ExecuteCoreGRPC,TemporalCloud: Secret redaction + Temporal dispatch
SetBMCCredentialHandler->>ExecuteCoreGRPC: forge.Forge/CreateCredential, req, secretKey, "password"
ExecuteCoreGRPC->>ExecuteCoreGRPC: protojson encode → RedactSecrets → AES encrypt
ExecuteCoreGRPC->>TemporalCloud: start InvokeCoreGRPC(coreproxy.Request{redactedJSON, encryptedSecrets})
end
rect rgba(210, 105, 30, 0.5)
note over InvokeCoreGRPCOnSite,CoreGrpcClient: On-site secret restore + gRPC call
TemporalCloud->>InvokeCoreGRPCOnSite: execute activity
InvokeCoreGRPCOnSite->>InvokeCoreGRPCOnSite: AES decrypt + MergeSecrets → full reqJSON
InvokeCoreGRPCOnSite->>CoreGrpcClient: InvokeJSON(ctx, CreateCredential, fullReqJSON)
CoreGrpcClient-->>InvokeCoreGRPCOnSite: respJSON
InvokeCoreGRPCOnSite-->>TemporalCloud: coreproxy.Response
end
TemporalCloud-->>ExecuteCoreGRPC: coreproxy.Response
ExecuteCoreGRPC-->>SetBMCCredentialHandler: HTTP 200
SetBMCCredentialHandler-->>Client: HTTP 204 No Content
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
thossain-nv
left a comment
There was a problem hiding this comment.
Thanks for the great implementation @kfelternv! I’ll go through this as soon as I can and leave some notes.
a17f8ff to
732e3e0
Compare
|
@coderabbitai review |
✅ Action performedReview finished.
|
🔍 Container Scan Summary
Per-CVE detail lives in the per-service |
|
🌿 Preview your docs: https://nvidia-preview-pull-request-2477.docs.buildwithfern.com/infra-controller |
🔐 TruffleHog Secret Scan✅ No secrets or credentials found! Your code has been scanned for 700+ types of secrets and credentials. All clear! 🎉 🕐 Last updated: 2026-06-18 18:25:58 UTC | Commit: 732e3e0 |
c1ef376 to
56b13c7
Compare
3ce7963 to
517006d
Compare
|
/ok to test 6682b6e |
Summary (AI Assisted PR Description to add detail and links to code)
This PR adds a generic Temporal-backed Core gRPC proxy for REST API operations that need to call on-site NICo Core methods. The first consumer is
PUT /v2/org/{org}/nico/credential/bmc, which stores site-wide or per-BMC root credentials by forwarding a typedforge.Forge/CreateCredentialrequest to the site.Why
Today, each REST operation that needs to reach NICo Core tends to grow its own workflow, activity, request type, and site-side plumbing. This PR adds one shared internal transport for curated REST handlers: handlers still own auth, validation, request shaping, and API design, but the cloud-to-site Temporal hop is generic. The shared contract lives in
coreproxy.The BMC credential endpoint needs this path because the REST API must accept an administrative secret, validate it, and deliver it to on-site Core without recording the password in Temporal history.
Design
The new
coreproxypackage defines the shared workflow contract:FullMethod: the Core gRPC method to invoke, for example/forge.Forge/CreateCredential.RequestJSON: the typed protobuf request encoded as protojson, with configured secret fields replaced by[REDACTED].EncryptedSecrets: an encrypted sidecar containing only the redacted secret fields.ResponseJSON: the Core gRPC response encoded as protojson.ExecuteCoreGRPCis the cloud-side helper. It accepts an already validated protobuf request, converts it to protojson, redacts requested secret fields, and encrypts those fields before starting the workflow. This follows the existing site-bound Temporal secret pattern used by OTP rotation: the cloud workflow encrypts the new OTP withEncryptData(..., site.ID.String())before callingExecuteWorkflow("RotateTemporalCertAccessOTP", ...), and the site-agent decrypts it withDecryptData(..., ManagerAccess.Conf.EB.Temporal.ClusterID)before writing it into the local bootstrap secret.ExecuteCoreGRPCapplies that same pattern to a generic secret sidecar, then starts the sharedInvokeCoreGRPCworkflow on the site task queue.On site, the registered
InvokeCoreGRPCworkflow runs one activity,InvokeCoreGRPCOnSite. The activity decryptsEncryptedSecrets, merges the secret fields back into the request JSON, and then invokes Core throughInvokeJSON, which resolves the requested unaryforge.Forgemethod, dynamically builds the request/response messages, invokes Core over the existing gRPC client, and returns the response as protojson.The site-agent registers the shared workflow and activity through the Core gRPC manager in
RegisterSubscriber.Secret Handling
The proxy does not encrypt the whole request. It splits the payload so non-secret request fields remain readable for Temporal debugging, while sensitive fields such as
passwordare removed fromRequestJSONand carried only inEncryptedSecrets. The redaction and merge behavior is implemented byRedactSecretsandMergeSecrets.For the BMC credential endpoint, the handler calls the proxy with
passwordas the secret field, so the Temporal-visible request contains[REDACTED]instead of the credential password. That call is inSetBMCCredentialHandler.Handle.BMC Credential Endpoint
Adds
PUT /v2/org/{org}/nico/credential/bmcfor Provider Admin users.The handler:
authorizeSite.siteIdand confirms the site belongs to the org's infrastructure provider inauthorizeSite.APIBMCCredentialRequest.Validate.CredentialCreationRequestthroughToProto.forge.Forge/CreateCredentialthroughExecuteCoreGRPC.204 No Contenton success.Supported credential kinds are defined in
bmccredential.go:macAddress.The route is registered in
routes.goand documented in the OpenAPI spec withBMCCredentialRequest.Testing
EncryptData/DecryptDatatests cover the encryption primitive.coreproxytests cover secret redaction, empty/no-op redaction, and merge round trips.bmccredential_test.go.core_proxy_test.go.routes_test.go.