@@ -268,6 +268,65 @@ def prompt_expiration_time(
268
268
return expiration_seconds
269
269
270
270
271
+ def prompt_expires_at (
272
+ default : Optional [datetime ] = None ,
273
+ ) -> Optional [datetime ]:
274
+ """Prompt the user for an expiration timestamp.
275
+
276
+ Args:
277
+ default: The default expiration time.
278
+
279
+ Returns:
280
+ The expiration time provided by the user.
281
+ """
282
+ if default is None :
283
+ confirm = click .confirm (
284
+ "Are the credentials you configured temporary? If so, you'll be asked "
285
+ "to provide an expiration time in the next step." ,
286
+ default = False ,
287
+ )
288
+ if not confirm :
289
+ return None
290
+
291
+ while True :
292
+ default_str = ""
293
+ if default is not None :
294
+ seconds = int ((default - datetime .utcnow ()).total_seconds ())
295
+ default_str = (
296
+ f" [{ str (default )} i.e. in "
297
+ f"{ seconds_to_human_readable (seconds )} ]"
298
+ )
299
+
300
+ expires_at = click .prompt (
301
+ "Please enter the exact UTC date and time when the credentials "
302
+ f"will expire e.g. '2023-12-31 23:59:59'{ default_str } " ,
303
+ type = click .DateTime (),
304
+ default = default ,
305
+ show_default = False ,
306
+ )
307
+
308
+ assert expires_at is not None
309
+ assert isinstance (expires_at , datetime )
310
+ if expires_at < datetime .utcnow ():
311
+ cli_utils .warning (
312
+ "The expiration time must be in the future. Please enter a "
313
+ "later date and time."
314
+ )
315
+ continue
316
+
317
+ seconds = int ((expires_at - datetime .utcnow ()).total_seconds ())
318
+
319
+ confirm = click .confirm (
320
+ f"Credentials will be valid until { str (expires_at )} UTC (i.e. "
321
+ f"in { seconds_to_human_readable (seconds )} . Keep this value?" ,
322
+ default = True ,
323
+ )
324
+ if confirm :
325
+ break
326
+
327
+ return expires_at
328
+
329
+
271
330
@service_connector .command (
272
331
"register" ,
273
332
context_settings = {"ignore_unknown_options" : True },
@@ -367,6 +426,16 @@ def prompt_expiration_time(
367
426
required = False ,
368
427
type = str ,
369
428
)
429
+ @click .option (
430
+ "--expires-at" ,
431
+ "expires_at" ,
432
+ help = "The exact UTC date and time when the credentials configured for this "
433
+ "connector will expire. Takes the form 'YYYY-MM-DD HH:MM:SS'. This is only "
434
+ "required if you are configuring a service connector with expiring "
435
+ "credentials." ,
436
+ required = False ,
437
+ type = click .DateTime (),
438
+ )
370
439
@click .option (
371
440
"--expires-skew-tolerance" ,
372
441
"expires_skew_tolerance" ,
@@ -444,6 +513,7 @@ def register_service_connector(
444
513
resource_type : Optional [str ] = None ,
445
514
resource_id : Optional [str ] = None ,
446
515
auth_method : Optional [str ] = None ,
516
+ expires_at : Optional [datetime ] = None ,
447
517
expires_skew_tolerance : Optional [int ] = None ,
448
518
expiration_seconds : Optional [int ] = None ,
449
519
no_verify : bool = False ,
@@ -463,6 +533,8 @@ def register_service_connector(
463
533
resource_type: The type of resource to connect to.
464
534
resource_id: The ID of the resource to connect to.
465
535
auth_method: The authentication method to use.
536
+ expires_at: The exact UTC date and time when the credentials configured
537
+ for this connector will expire.
466
538
expires_skew_tolerance: The tolerance, in seconds, allowed when
467
539
determining when the credentials configured for or generated by
468
540
this connector will expire.
@@ -495,8 +567,6 @@ def register_service_connector(
495
567
# Parse the given labels
496
568
parsed_labels = cast (Dict [str , str ], cli_utils .get_parsed_labels (labels ))
497
569
498
- expires_at : Optional [datetime ] = None
499
-
500
570
if interactive :
501
571
# Get the list of available service connector types
502
572
connector_types = client .list_service_connector_types (
@@ -764,6 +834,9 @@ def register_service_connector(
764
834
default = auth_method_spec .default_expiration_seconds ,
765
835
)
766
836
837
+ # Prompt for the time when the credentials will expire
838
+ expires_at = prompt_expires_at (expires_at )
839
+
767
840
try :
768
841
# Validate the connector configuration and fetch all available
769
842
# resources that are accessible with the provided configuration
@@ -781,6 +854,7 @@ def register_service_connector(
781
854
auth_method = auth_method ,
782
855
resource_type = resource_type ,
783
856
configuration = config_dict ,
857
+ expires_at = expires_at ,
784
858
expires_skew_tolerance = expires_skew_tolerance ,
785
859
expiration_seconds = expiration_seconds ,
786
860
auto_configure = False ,
@@ -1176,6 +1250,14 @@ def describe_service_connector(
1176
1250
required = False ,
1177
1251
type = str ,
1178
1252
)
1253
+ @click .option (
1254
+ "--expires-at" ,
1255
+ "expires_at" ,
1256
+ help = "The time at which the credentials configured for this connector "
1257
+ "will expire." ,
1258
+ required = False ,
1259
+ type = click .DateTime (),
1260
+ )
1179
1261
@click .option (
1180
1262
"--expires-skew-tolerance" ,
1181
1263
"expires_skew_tolerance" ,
@@ -1244,6 +1326,7 @@ def update_service_connector(
1244
1326
resource_type : Optional [str ] = None ,
1245
1327
resource_id : Optional [str ] = None ,
1246
1328
auth_method : Optional [str ] = None ,
1329
+ expires_at : Optional [datetime ] = None ,
1247
1330
expires_skew_tolerance : Optional [int ] = None ,
1248
1331
expiration_seconds : Optional [int ] = None ,
1249
1332
no_verify : bool = False ,
@@ -1264,6 +1347,8 @@ def update_service_connector(
1264
1347
resource_type: The type of resource to connect to.
1265
1348
resource_id: The ID of the resource to connect to.
1266
1349
auth_method: The authentication method to use.
1350
+ expires_at: The time at which the credentials configured for this
1351
+ connector will expire.
1267
1352
expires_skew_tolerance: The tolerance, in seconds, allowed when
1268
1353
determining when the credentials configured for or generated by
1269
1354
this connector will expire.
@@ -1425,6 +1510,9 @@ def update_service_connector(
1425
1510
or auth_method_spec .default_expiration_seconds ,
1426
1511
)
1427
1512
1513
+ # Prompt for the time when the credentials will expire
1514
+ expires_at = prompt_expires_at (expires_at or connector .expires_at )
1515
+
1428
1516
try :
1429
1517
# Validate the connector configuration and fetch all available
1430
1518
# resources that are accessible with the provided configuration
@@ -1442,6 +1530,7 @@ def update_service_connector(
1442
1530
# should be removed in the update if not set here
1443
1531
resource_type = resource_type or "" ,
1444
1532
configuration = config_dict ,
1533
+ expires_at = expires_at ,
1445
1534
# Use zero value to indicate that the expiration time
1446
1535
# should be removed in the update if not set here
1447
1536
expiration_seconds = expiration_seconds or 0 ,
@@ -1534,6 +1623,7 @@ def update_service_connector(
1534
1623
# should be removed in the update if not set here
1535
1624
resource_id = resource_id or "" ,
1536
1625
description = description ,
1626
+ expires_at = expires_at ,
1537
1627
# Use empty string to indicate that the expiration time
1538
1628
# should be removed in the update if not set here
1539
1629
expiration_seconds = expiration_seconds or 0 ,
0 commit comments