Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions internal/destregistry/providers/destgcppubsub/destgcppubsub.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,23 @@ func (d *GCPPubSubDestination) resolveMetadata(ctx context.Context, destination
return nil, nil, err
}

// Validate service_account_json is valid JSON (if not using emulator endpoint)
serviceAccountJSON := destination.Credentials["service_account_json"]
endpoint := destination.Config["endpoint"]

// Only validate JSON if we're not using an emulator endpoint and service_account_json is provided
if endpoint == "" && serviceAccountJSON != "" {
var jsonCheck map[string]interface{}
if err := json.Unmarshal([]byte(serviceAccountJSON), &jsonCheck); err != nil {
return nil, nil, destregistry.NewErrDestinationValidation([]destregistry.ValidationErrorDetail{
{
Field: "credentials.service_account_json",
Type: "format",
},
})
}
}

return &GCPPubSubDestinationConfig{
ProjectID: destination.Config["project_id"],
Topic: destination.Config["topic"],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,42 @@ func TestValidate(t *testing.T) {
credentials: map[string]string{
"service_account_json": "not-valid-json",
},
wantErr: false, // We don't validate JSON structure anymore, Google SDK will handle it
wantErr: true,
errContains: "credentials.service_account_json",
},
{
name: "invalid JSON in service_account_json - but passes with emulator endpoint",
config: map[string]string{
"project_id": "my-project",
"topic": "my-topic",
"endpoint": "http://localhost:8085",
},
credentials: map[string]string{
"service_account_json": "not-valid-json",
},
wantErr: false, // Emulator doesn't require valid JSON
},
{
name: "valid service account JSON with complete structure",
config: map[string]string{
"project_id": "my-project",
"topic": "my-topic",
},
credentials: map[string]string{
"service_account_json": `{
"type": "service_account",
"project_id": "my-project",
"private_key_id": "key123",
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIE...\n-----END PRIVATE KEY-----\n",
"client_email": "my-service@my-project.iam.gserviceaccount.com",
"client_id": "123456789",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/my-service%40my-project.iam.gserviceaccount.com"
}`,
},
wantErr: false,
},
{
name: "valid with all optional fields",
Expand Down
3 changes: 1 addition & 2 deletions spec-sdk-tests/tests/destinations/gcp-pubsub.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,8 +214,7 @@ describe('GCP Pub/Sub Destinations - Contract Tests (SDK-based validation)', ()
}
});

// TODO: Re-enable this test once the backend validates the contents of the serviceAccountJson.
it.skip('should reject creation with invalid serviceAccountJson', async () => {
it('should reject creation with invalid serviceAccountJson', async () => {
let errorThrown = false;
try {
await client.createDestination({
Expand Down