@@ -9,15 +9,19 @@ import (
9
9
10
10
tfe "github.com/hashicorp/go-tfe"
11
11
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
12
+ "github.com/hashicorp/terraform-plugin-framework/path"
12
13
"github.com/hashicorp/terraform-plugin-framework/resource"
13
14
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
14
15
"github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault"
15
16
"github.com/hashicorp/terraform-plugin-framework/resource/schema/int64default"
17
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
16
18
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault"
17
19
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
18
20
"github.com/hashicorp/terraform-plugin-framework/types"
19
21
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
20
22
"github.com/hashicorp/terraform-plugin-log/tflog"
23
+ "github.com/hashicorp/terraform-provider-tfe/internal/provider/helpers"
24
+ "github.com/hashicorp/terraform-provider-tfe/internal/provider/planmodifiers"
21
25
)
22
26
23
27
const (
@@ -36,7 +40,7 @@ type resourceTFESAMLSettings struct {
36
40
}
37
41
38
42
// modelFromTFEAdminSAMLSettings builds a modelTFESAMLSettings struct from a tfe.AdminSAMLSetting value
39
- func modelFromTFEAdminSAMLSettings (v tfe.AdminSAMLSetting , privateKey types.String ) modelTFESAMLSettings {
43
+ func modelFromTFEAdminSAMLSettings (v tfe.AdminSAMLSetting , privateKey types.String , isWriteOnly bool ) modelTFESAMLSettings {
40
44
m := modelTFESAMLSettings {
41
45
ID : types .StringValue (v .ID ),
42
46
Enabled : types .BoolValue (v .Enabled ),
@@ -60,9 +64,16 @@ func modelFromTFEAdminSAMLSettings(v tfe.AdminSAMLSetting, privateKey types.Stri
60
64
SignatureSigningMethod : types .StringValue (v .SignatureSigningMethod ),
61
65
SignatureDigestMethod : types .StringValue (v .SignatureDigestMethod ),
62
66
}
67
+
63
68
if len (privateKey .String ()) > 0 {
64
69
m .PrivateKey = privateKey
65
70
}
71
+
72
+ // Don't retrieve values if write-only is being used. Unset the hmac key field before updating the state.
73
+ if isWriteOnly {
74
+ m .PrivateKey = types .StringValue ("" )
75
+ }
76
+
66
77
return m
67
78
}
68
79
@@ -187,6 +198,21 @@ func (r *resourceTFESAMLSettings) Schema(ctx context.Context, req resource.Schem
187
198
Optional : true ,
188
199
Computed : true ,
189
200
Sensitive : true ,
201
+ Validators : []validator.String {
202
+ stringvalidator .ConflictsWith (path .MatchRoot ("private_key_wo" )),
203
+ },
204
+ },
205
+ "private_key_wo" : schema.StringAttribute {
206
+ Description : "The private key in write-only mode used for request and assertion signing" ,
207
+ Optional : true ,
208
+ Sensitive : true ,
209
+ WriteOnly : true ,
210
+ Validators : []validator.String {
211
+ stringvalidator .ConflictsWith (path .MatchRoot ("private_key" )),
212
+ },
213
+ PlanModifiers : []planmodifier.String {
214
+ planmodifiers .NewReplaceForWriteOnlyStringValue ("private_key_wo" ),
215
+ },
190
216
},
191
217
"signature_signing_method" : schema.StringAttribute {
192
218
Description : fmt .Sprintf ("Signature Signing Method. Must be either `%s` or `%s`. Defaults to `%s`" , samlSignatureMethodSHA1 , samlSignatureMethodSHA256 , samlSignatureMethodSHA256 ),
@@ -225,13 +251,22 @@ func (r *resourceTFESAMLSettings) Read(ctx context.Context, req resource.ReadReq
225
251
return
226
252
}
227
253
254
+ tflog .Debug (ctx , "Reading SAML Settings" )
255
+
228
256
samlSettings , err := r .client .Admin .Settings .SAML .Read (ctx )
229
257
if err != nil {
230
258
resp .Diagnostics .AddError ("Error reading SAML Settings" , "Could not read SAML Settings, unexpected error: " + err .Error ())
231
259
return
232
260
}
233
261
234
- result := modelFromTFEAdminSAMLSettings (* samlSettings , m .PrivateKey )
262
+ isWriteOnly , diags := r .writeOnlyValueStore (resp .Private ).PriorValueExists (ctx )
263
+ resp .Diagnostics .Append (diags ... )
264
+ if diags .HasError () {
265
+ return
266
+ }
267
+
268
+ // update state
269
+ result := modelFromTFEAdminSAMLSettings (* samlSettings , m .PrivateKey , isWriteOnly )
235
270
diags = resp .State .Set (ctx , & result )
236
271
resp .Diagnostics .Append (diags ... )
237
272
}
@@ -245,14 +280,28 @@ func (r *resourceTFESAMLSettings) Create(ctx context.Context, req resource.Creat
245
280
return
246
281
}
247
282
283
+ var config modelTFESAMLSettings
284
+ diags = req .Config .Get (ctx , & config )
285
+ resp .Diagnostics .Append (diags ... )
286
+ if resp .Diagnostics .HasError () {
287
+ return
288
+ }
289
+
290
+ if ! config .PrivateKeyWO .IsNull () {
291
+ m .PrivateKey = config .PrivateKeyWO
292
+ }
293
+
248
294
tflog .Debug (ctx , "Create SAML Settings" )
249
295
samlSettings , err := r .updateSAMLSettings (ctx , m )
250
296
if err != nil {
251
297
resp .Diagnostics .AddError ("Error creating SAML Settings" , "Could not set SAML Settings, unexpected error: " + err .Error ())
252
298
return
253
299
}
254
300
255
- result := modelFromTFEAdminSAMLSettings (* samlSettings , m .PrivateKey )
301
+ result := modelFromTFEAdminSAMLSettings (* samlSettings , m .PrivateKey , ! config .PrivateKeyWO .IsNull ())
302
+ // Store the hashed write-only value in the private state
303
+ store := r .writeOnlyValueStore (resp .Private )
304
+ resp .Diagnostics .Append (store .SetPriorValue (ctx , config .PrivateKeyWO )... )
256
305
diags = resp .State .Set (ctx , & result )
257
306
resp .Diagnostics .Append (diags ... )
258
307
}
@@ -266,14 +315,33 @@ func (r *resourceTFESAMLSettings) Update(ctx context.Context, req resource.Updat
266
315
return
267
316
}
268
317
318
+ var config modelTFESAMLSettings
319
+ diags = req .Config .Get (ctx , & config )
320
+ resp .Diagnostics .Append (diags ... )
321
+ if resp .Diagnostics .HasError () {
322
+ return
323
+ }
324
+
325
+ if ! config .PrivateKeyWO .IsNull () {
326
+ m .PrivateKey = config .PrivateKeyWO
327
+ }
328
+
269
329
tflog .Debug (ctx , "Update SAML Settings" )
270
330
samlSettings , err := r .updateSAMLSettings (ctx , m )
271
331
if err != nil {
272
332
resp .Diagnostics .AddError ("Error updating SAML Settings" , "Could not set SAML Settings, unexpected error: " + err .Error ())
273
333
return
274
334
}
275
335
276
- result := modelFromTFEAdminSAMLSettings (* samlSettings , m .PrivateKey )
336
+ // Store the hashed write-only value in the private state
337
+ store := r .writeOnlyValueStore (resp .Private )
338
+ resp .Diagnostics .Append (store .SetPriorValue (ctx , config .PrivateKeyWO )... )
339
+ if resp .Diagnostics .HasError () {
340
+ return
341
+ }
342
+
343
+ result := modelFromTFEAdminSAMLSettings (* samlSettings , m .PrivateKey , ! config .PrivateKeyWO .IsNull ())
344
+ // Save data into Terraform state
277
345
diags = resp .State .Set (ctx , & result )
278
346
resp .Diagnostics .Append (diags ... )
279
347
}
@@ -321,7 +389,7 @@ func (r *resourceTFESAMLSettings) ImportState(ctx context.Context, req resource.
321
389
return
322
390
}
323
391
324
- result := modelFromTFEAdminSAMLSettings (* samlSettings , types .StringValue ("" ))
392
+ result := modelFromTFEAdminSAMLSettings (* samlSettings , types .StringValue ("" ), false )
325
393
diags := resp .State .Set (ctx , & result )
326
394
resp .Diagnostics .Append (diags ... )
327
395
}
@@ -363,3 +431,7 @@ func (r *resourceTFESAMLSettings) updateSAMLSettings(ctx context.Context, m mode
363
431
}
364
432
return s , nil
365
433
}
434
+
435
+ func (r * resourceTFESAMLSettings ) writeOnlyValueStore (private helpers.PrivateState ) * helpers.WriteOnlyValueStore {
436
+ return helpers .NewWriteOnlyValueStore (private , "private_key_wo" )
437
+ }
0 commit comments