Skip to content

Commit 0bf2552

Browse files
jaymclaude
andcommitted
Make wif.service_account_email optional for GCP-family resources
Service account impersonation is an optional step for GCP workload identity federation - customers can also grant the identity pool's principal direct access to the resource. Only send the field to the server when it is set, and map an empty server response back to null in state so an unset value does not churn in subsequent plans. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 1c7a3c0 commit 0bf2552

6 files changed

Lines changed: 40 additions & 18 deletions

File tree

docs/resources/export_bigquery.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,7 @@ Optional:
6262
Required:
6363

6464
- `audience` (String) WIF audience URL for GCP workload identity federation.
65-
- `service_account_email` (String) GCP service account email impersonated via workload identity federation.
65+
66+
Optional:
67+
68+
- `service_account_email` (String) Optional GCP service account email to impersonate via workload identity federation.

docs/resources/export_gcs_bucket.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,7 @@ Optional:
6969
Required:
7070

7171
- `audience` (String) WIF audience URL for GCP workload identity federation.
72-
- `service_account_email` (String) GCP service account email impersonated via workload identity federation.
72+
73+
Optional:
74+
75+
- `service_account_email` (String) Optional GCP service account email to impersonate via workload identity federation.

docs/resources/integration_gcp.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,10 @@ Optional:
100100
Required:
101101

102102
- `audience` (String) WIF audience URL for GCP workload identity federation.
103-
- `service_account_email` (String) GCP service account email impersonated via workload identity federation.
103+
104+
Optional:
105+
106+
- `service_account_email` (String) Optional GCP service account email to impersonate via workload identity federation.
104107

105108
## Import
106109

internal/provider/export_bigquery.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,9 @@ func (m BigQueryExportResourceModel) GetConfigurationOptions() *mondoov1.Bigquer
6363

6464
if m.Credentials != nil && m.Credentials.Wif != nil {
6565
opts.WifAudience = mondoov1.NewStringPtr(mondoov1.String(m.Credentials.Wif.Audience.ValueString()))
66-
opts.WifServiceAccountEmail = mondoov1.NewStringPtr(mondoov1.String(m.Credentials.Wif.ServiceAccountEmail.ValueString()))
66+
if !m.Credentials.Wif.ServiceAccountEmail.IsNull() && !m.Credentials.Wif.ServiceAccountEmail.IsUnknown() {
67+
opts.WifServiceAccountEmail = mondoov1.NewStringPtr(mondoov1.String(m.Credentials.Wif.ServiceAccountEmail.ValueString()))
68+
}
6769
}
6870

6971
return opts
@@ -155,8 +157,8 @@ func (r *ExportBigQueryResource) Schema(ctx context.Context, req resource.Schema
155157
Required: true,
156158
},
157159
"service_account_email": schema.StringAttribute{
158-
MarkdownDescription: "GCP service account email impersonated via workload identity federation.",
159-
Required: true,
160+
MarkdownDescription: "Optional GCP service account email to impersonate via workload identity federation.",
161+
Optional: true,
160162
},
161163
},
162164
},
@@ -305,7 +307,7 @@ func (r *ExportBigQueryResource) Read(ctx context.Context, req resource.ReadRequ
305307
data.WifSubject = types.StringValue(opts.WifSubject)
306308
if data.Credentials != nil && data.Credentials.Wif != nil {
307309
data.Credentials.Wif.Audience = types.StringValue(opts.WifAudience)
308-
data.Credentials.Wif.ServiceAccountEmail = types.StringValue(opts.WifServiceAccountEmail)
310+
data.Credentials.Wif.ServiceAccountEmail = stringOrNull(opts.WifServiceAccountEmail)
309311
}
310312
// Note: We don't update service_account_key to avoid showing sensitive data
311313

@@ -375,7 +377,7 @@ func (r *ExportBigQueryResource) ImportState(ctx context.Context, req resource.I
375377
model.Credentials = &exportBigQueryCredentialsWrapper{
376378
Wif: &gcpWifCredentialModel{
377379
Audience: types.StringValue(opts.WifAudience),
378-
ServiceAccountEmail: types.StringValue(opts.WifServiceAccountEmail),
380+
ServiceAccountEmail: stringOrNull(opts.WifServiceAccountEmail),
379381
},
380382
}
381383
}

internal/provider/export_gcs_bucket.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,9 @@ func (m ExportGcsBucketResourceModel) GetConfigurationOptions() *mondoov1.GcsBuc
7373

7474
if m.Credential.Wif != nil {
7575
opts.WifAudience = mondoov1.NewStringPtr(mondoov1.String(m.Credential.Wif.Audience.ValueString()))
76-
opts.WifServiceAccountEmail = mondoov1.NewStringPtr(mondoov1.String(m.Credential.Wif.ServiceAccountEmail.ValueString()))
76+
if !m.Credential.Wif.ServiceAccountEmail.IsNull() && !m.Credential.Wif.ServiceAccountEmail.IsUnknown() {
77+
opts.WifServiceAccountEmail = mondoov1.NewStringPtr(mondoov1.String(m.Credential.Wif.ServiceAccountEmail.ValueString()))
78+
}
7779
}
7880

7981
return opts
@@ -185,8 +187,8 @@ func (r *ExportGcsBucketResource) Schema(ctx context.Context, req resource.Schem
185187
Required: true,
186188
},
187189
"service_account_email": schema.StringAttribute{
188-
MarkdownDescription: "GCP service account email impersonated via workload identity federation.",
189-
Required: true,
190+
MarkdownDescription: "Optional GCP service account email to impersonate via workload identity federation.",
191+
Optional: true,
190192
},
191193
},
192194
Validators: []validator.Object{
@@ -331,7 +333,7 @@ func (r *ExportGcsBucketResource) Read(ctx context.Context, req resource.ReadReq
331333
data.WifSubject = types.StringValue(opts.WifSubject)
332334
if data.Credential.Wif != nil {
333335
data.Credential.Wif.Audience = types.StringValue(opts.WifAudience)
334-
data.Credential.Wif.ServiceAccountEmail = types.StringValue(opts.WifServiceAccountEmail)
336+
data.Credential.Wif.ServiceAccountEmail = stringOrNull(opts.WifServiceAccountEmail)
335337
}
336338

337339
// Save updated data into Terraform state
@@ -402,7 +404,7 @@ func (r *ExportGcsBucketResource) ImportState(ctx context.Context, req resource.
402404
if opts.WifAudience != "" {
403405
model.Credential.Wif = &gcpWifCredentialModel{
404406
Audience: types.StringValue(opts.WifAudience),
405-
ServiceAccountEmail: types.StringValue(opts.WifServiceAccountEmail),
407+
ServiceAccountEmail: stringOrNull(opts.WifServiceAccountEmail),
406408
}
407409
}
408410

internal/provider/integration_gcp_resource.go

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,13 @@ type gcpWifCredentialModel struct {
5858
ServiceAccountEmail types.String `tfsdk:"service_account_email"`
5959
}
6060

61+
func stringOrNull(s string) types.String {
62+
if s == "" {
63+
return types.StringNull()
64+
}
65+
return types.StringValue(s)
66+
}
67+
6168
func (m integrationGcpResourceModel) GetConfigurationOptions() *mondoov1.GcpConfigurationOptionsInput {
6269
opts := &mondoov1.GcpConfigurationOptionsInput{
6370
ProjectId: mondoov1.NewStringPtr(mondoov1.String(m.ProjectId.ValueString())),
@@ -70,7 +77,9 @@ func (m integrationGcpResourceModel) GetConfigurationOptions() *mondoov1.GcpConf
7077

7178
if m.Credential.Wif != nil {
7279
opts.WifAudience = mondoov1.NewStringPtr(mondoov1.String(m.Credential.Wif.Audience.ValueString()))
73-
opts.WifServiceAccountEmail = mondoov1.NewStringPtr(mondoov1.String(m.Credential.Wif.ServiceAccountEmail.ValueString()))
80+
if !m.Credential.Wif.ServiceAccountEmail.IsNull() && !m.Credential.Wif.ServiceAccountEmail.IsUnknown() {
81+
opts.WifServiceAccountEmail = mondoov1.NewStringPtr(mondoov1.String(m.Credential.Wif.ServiceAccountEmail.ValueString()))
82+
}
7483
}
7584

7685
return opts
@@ -140,8 +149,8 @@ func (r *integrationGcpResource) Schema(ctx context.Context, req resource.Schema
140149
Required: true,
141150
},
142151
"service_account_email": schema.StringAttribute{
143-
MarkdownDescription: "GCP service account email impersonated via workload identity federation.",
144-
Required: true,
152+
MarkdownDescription: "Optional GCP service account email to impersonate via workload identity federation.",
153+
Optional: true,
145154
},
146155
},
147156
Validators: []validator.Object{
@@ -270,7 +279,7 @@ func (r *integrationGcpResource) Read(ctx context.Context, req resource.ReadRequ
270279
data.WifSubject = types.StringValue(opts.WifSubject)
271280
if data.Credential.Wif != nil {
272281
data.Credential.Wif.Audience = types.StringValue(opts.WifAudience)
273-
data.Credential.Wif.ServiceAccountEmail = types.StringValue(opts.WifServiceAccountEmail)
282+
data.Credential.Wif.ServiceAccountEmail = stringOrNull(opts.WifServiceAccountEmail)
274283
}
275284

276285
// Save updated data into Terraform state
@@ -352,7 +361,7 @@ func (r *integrationGcpResource) ImportState(ctx context.Context, req resource.I
352361
if opts.WifAudience != "" {
353362
model.Credential.Wif = &gcpWifCredentialModel{
354363
Audience: types.StringValue(opts.WifAudience),
355-
ServiceAccountEmail: types.StringValue(opts.WifServiceAccountEmail),
364+
ServiceAccountEmail: stringOrNull(opts.WifServiceAccountEmail),
356365
}
357366
}
358367

0 commit comments

Comments
 (0)