Skip to content

Commit 1cfe8d9

Browse files
authored
Add VERTEX_SA_JSON support in agent-splunk (#1093)
Allow agent-splunk to authenticate using a service account JSON string passed via the VERTEX_SA_JSON environment variable, enabling Alcove's credential injection to provide Vertex AI credentials directly instead of relying on Application Default Credentials (ADC). When VERTEX_SA_JSON is set, the project_id is extracted from the JSON automatically, making ANTHROPIC_VERTEX_PROJECT_ID optional. ADC remains the fallback when no service account JSON is provided. Assisted By: claude-opus-4.6
1 parent cd24b18 commit 1cfe8d9

3 files changed

Lines changed: 46 additions & 17 deletions

File tree

tools/agents/agent-splunk/anthropic-client/client.go

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package anthropicClient
22

33
import (
44
"bytes"
5+
"context"
56
"encoding/json"
67
"fmt"
78
"io"
@@ -16,9 +17,10 @@ import (
1617
// It intercepts HTTP requests meant for the Anthropic API and rewrites
1718
// them to target the Vertex AI endpoint, using gcloud credentials for auth.
1819
type VertexClient struct {
19-
ProjectID string
20-
Region string
21-
Model string
20+
ProjectID string
21+
Region string
22+
Model string
23+
SACredential []byte // Raw service account JSON; if set, used instead of ADC.
2224

2325
once sync.Once
2426
creds *google.Credentials
@@ -33,12 +35,17 @@ const (
3335
func (v *VertexClient) Do(req *http.Request) (*http.Response, error) {
3436
ctx := req.Context()
3537

36-
// run the function to get gcloud credentials only once and store/cache the credentials in
37-
// VertexClient struct (creds)
3838
v.once.Do(func() {
39-
creds, err := google.FindDefaultCredentials(ctx, GOOGLE_API_AUTH_URL)
39+
initCtx := context.Background()
40+
var creds *google.Credentials
41+
var err error
42+
if len(v.SACredential) > 0 {
43+
creds, err = google.CredentialsFromJSON(initCtx, v.SACredential, GOOGLE_API_AUTH_URL)
44+
} else {
45+
creds, err = google.FindDefaultCredentials(initCtx, GOOGLE_API_AUTH_URL)
46+
}
4047
if err != nil {
41-
v.initErr = fmt.Errorf("find default credentials: %w", err)
48+
v.initErr = fmt.Errorf("obtain credentials: %w", err)
4249
return
4350
}
4451
v.creds = creds

tools/agents/agent-splunk/main.go

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package main
22

33
import (
44
"context"
5+
"encoding/json"
56
"flag"
67
"fmt"
78
"log"
@@ -30,9 +31,27 @@ func run() error {
3031
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
3132
defer stop()
3233

34+
var saCredential []byte
35+
if saJSON := os.Getenv("VERTEX_SA_JSON"); saJSON != "" {
36+
saCredential = []byte(saJSON)
37+
fmt.Fprintf(os.Stderr, "[auth] using VERTEX_SA_JSON for Vertex AI authentication\n")
38+
}
39+
3340
projectID := os.Getenv("ANTHROPIC_VERTEX_PROJECT_ID")
41+
if projectID == "" && len(saCredential) > 0 {
42+
var sa struct {
43+
ProjectID string `json:"project_id"`
44+
}
45+
if err := json.Unmarshal(saCredential, &sa); err != nil {
46+
return fmt.Errorf("VERTEX_SA_JSON is not valid JSON: %w", err)
47+
}
48+
if sa.ProjectID == "" {
49+
return fmt.Errorf("VERTEX_SA_JSON does not contain a project_id field")
50+
}
51+
projectID = sa.ProjectID
52+
}
3453
if projectID == "" {
35-
return fmt.Errorf("ANTHROPIC_VERTEX_PROJECT_ID environment variable is required")
54+
return fmt.Errorf("ANTHROPIC_VERTEX_PROJECT_ID environment variable is required (or set VERTEX_SA_JSON with a service account that contains project_id)")
3655
}
3756

3857
region := os.Getenv("CLOUD_ML_REGION")
@@ -97,9 +116,10 @@ func run() error {
97116
switch *inputModel {
98117
case "claude-opus-4-6":
99118
model = models.Claude{
100-
Model: *inputModel,
101-
ProjectID: projectID,
102-
Region: region,
119+
Model: *inputModel,
120+
ProjectID: projectID,
121+
Region: region,
122+
SACredential: saCredential,
103123
}
104124
case "gemini-2.5-pro":
105125
model = models.Gemini{

tools/agents/agent-splunk/models/anthropic.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ import (
1010
)
1111

1212
type Claude struct {
13-
Model string
14-
ProjectID string
15-
Region string
13+
Model string
14+
ProjectID string
15+
Region string
16+
SACredential []byte
1617
}
1718

1819
func (claude Claude) ModelRun(ctx context.Context, cfg RunConfig) (string, error) {
@@ -22,9 +23,10 @@ func (claude Claude) ModelRun(ctx context.Context, cfg RunConfig) (string, error
2223
anthropic.WithModel(claude.Model),
2324
anthropic.WithToken("vertex-ai"),
2425
anthropic.WithHTTPClient(&anthropicClient.VertexClient{
25-
ProjectID: claude.ProjectID,
26-
Region: claude.Region,
27-
Model: claude.Model,
26+
ProjectID: claude.ProjectID,
27+
Region: claude.Region,
28+
Model: claude.Model,
29+
SACredential: claude.SACredential,
2830
}),
2931
)
3032
if err != nil {

0 commit comments

Comments
 (0)