11import io
2+ import time
3+
24from britive .britive import Britive
35from .helpers .config import ConfigManager
46from .helpers .credentials import FileCredentialManager , EncryptedFileCredentialManager
@@ -240,15 +242,17 @@ def _get_app_type(self, application_id):
240242 return profile ['app_type' ]
241243 raise click .ClickException (f'Application { application_id } not found' )
242244
243- def __get_cloud_credential_printer (self , app_type , console , mode , profile , silent , credentials ):
245+ def __get_cloud_credential_printer (self , app_type , console , mode , profile , silent , credentials ,
246+ aws_credentials_file ):
244247 if app_type in ['AWS' , 'AWS Standalone' ]:
245248 return printer .AwsCloudCredentialPrinter (
246249 console = console ,
247250 mode = mode ,
248251 profile = profile ,
249252 credentials = credentials ,
250253 silent = silent ,
251- cli = self
254+ cli = self ,
255+ aws_credentials_file = aws_credentials_file
252256 )
253257 if app_type in ['Azure' ]:
254258 return printer .AzureCloudCredentialPrinter (
@@ -285,12 +289,34 @@ def checkin(self, profile):
285289 application_name = app_name
286290 )
287291
288- def checkout (self , alias , blocktime , console , justification , mode , maxpolltime , profile , passphrase ):
289- # first check if this is a profile alias
290- profile_or_alias = alias or profile
292+ def _checkout (self , profile_name , env_name , app_name , programmatic , blocktime , maxpolltime , justification ):
293+ try :
294+ self .login ()
295+ return self .b .my_access .checkout_by_name (
296+ profile_name = profile_name ,
297+ environment_name = env_name ,
298+ application_name = app_name ,
299+ programmatic = programmatic ,
300+ include_credentials = True ,
301+ wait_time = blocktime ,
302+ max_wait_time = maxpolltime ,
303+ justification = justification
304+ )
305+ except exceptions .ApprovalRequiredButNoJustificationProvided :
306+ raise click .ClickException ('approval required and no justification provided.' )
307+ except ValueError as e :
308+ raise click .BadParameter (str (e ))
309+
310+ @staticmethod
311+ def _should_check_force_renew (app , force_renew , console ):
312+ return app in ['AWS' , 'AWS Standalone' ] and force_renew and not console
291313
314+ def checkout (self , alias , blocktime , console , justification , mode , maxpolltime , profile , passphrase ,
315+ force_renew , aws_credentials_file ):
292316 credentials = None
293317 app_type = None
318+ credential_process_creds_found = False
319+ response = None
294320
295321 if mode == 'awscredentialprocess' :
296322 self .silent = True # the aws credential process CANNOT output anything other than the expected JSON
@@ -299,59 +325,68 @@ def checkout(self, alias, blocktime, console, justification, mode, maxpolltime,
299325 # if not simply return those credentials
300326 # if they are expired
301327 app_type = 'AWS' # just hardcode as we know for sure this is for AWS
302- credentials = Cache (passphrase = passphrase ).get_awscredentialprocess (profile_name = profile_or_alias )
328+ credentials = Cache (passphrase = passphrase ).get_awscredentialprocess (profile_name = alias or profile )
303329 if credentials :
304330 expiration_timestamp_str = credentials ['expirationTime' ].replace ('Z' , '' )
305331 expires = datetime .fromisoformat (expiration_timestamp_str )
306332 now = datetime .utcnow ()
307333 if now >= expires : # check to ensure the credentials are still valid, if not, set to None and get new
308334 credentials = None
335+ else :
336+ credential_process_creds_found = True
309337
310- if not credentials : # nothing found via aws credential process or not aws credential process mode
311- self .login ()
312- profile = self .config .profile_aliases .get (profile , profile )
313- parts = profile .split ('/' )
314- if len (parts ) != 3 :
315- raise click .ClickException ('Provided profile string does not have the required 3 parts.' )
316- app_name = parts [0 ]
317- env_name = parts [1 ]
318- profile_name = parts [2 ]
338+ profile_real = self .config .profile_aliases .get (profile , profile )
339+ parts = profile_real .split ('/' )
340+ if len (parts ) != 3 :
341+ raise click .ClickException ('Provided profile string does not have the required 3 parts.' )
319342
320- try :
321- response = self .b .my_access .checkout_by_name (
322- profile_name = profile_name ,
323- environment_name = env_name ,
324- application_name = app_name ,
325- programmatic = False if console else True ,
326- include_credentials = True ,
327- wait_time = blocktime ,
328- max_wait_time = maxpolltime ,
329- justification = justification
330- )
343+ # create this params once so we can use it multiple places
344+ params = {
345+ 'profile_name' : parts [2 ],
346+ 'env_name' : parts [1 ],
347+ 'app_name' : parts [0 ],
348+ 'programmatic' : False if console else True ,
349+ 'blocktime' : blocktime ,
350+ 'maxpolltime' : maxpolltime ,
351+ 'justification' : justification
352+ }
353+
354+ if not credential_process_creds_found : # nothing found via aws cred process or not aws cred process mode
355+ response = self ._checkout (** params )
356+ app_type = self ._get_app_type (response ['appContainerId' ])
357+ credentials = response ['credentials' ]
358+
359+ # this handles the --force-renew flag
360+ # lets check to see if the we should checkin this profile first and check it out again
361+ if self ._should_check_force_renew (app_type , force_renew , console ):
362+ expiration = datetime .fromisoformat (credentials ['expirationTime' ].replace ('Z' , '' ))
363+ now = datetime .utcnow ()
364+ diff = (expiration - now ).total_seconds () / 60.0
365+ if diff < force_renew : # time to checkin the profile so we can refresh creds
366+ self .print ('checking in the profile to get renewed credentials....standby' )
367+ self .checkin (profile = profile_real )
368+ response = self ._checkout (** params )
369+ credential_process_creds_found = False # need to write new creds to cache
331370 credentials = response ['credentials' ]
332- app_type = self ._get_app_type (response ['appContainerId' ])
333- except exceptions .ApprovalRequiredButNoJustificationProvided :
334- raise click .ClickException ('approval required and no justification provided.' )
335- except ValueError as e :
336- raise click .BadParameter (str (e ))
337-
338- if alias : # do this down here so we know that the profile is valid and a checkout was successful
339- self .config .save_profile_alias (alias = alias , profile = profile )
340- if mode == 'awscredentialprocess' :
341- Cache (passphrase = passphrase ).save_awscredentialprocess (
342- profile_name = profile_or_alias ,
343- credentials = credentials
344- )
345371
346- cc_printer = self .__get_cloud_credential_printer (
372+ if alias : # do this down here so we know that the profile is valid and a checkout was successful
373+ self .config .save_profile_alias (alias = alias , profile = profile )
374+
375+ if mode == 'awscredentialprocess' and not credential_process_creds_found :
376+ Cache (passphrase = passphrase ).save_awscredentialprocess (
377+ profile_name = alias or profile ,
378+ credentials = credentials
379+ )
380+
381+ self .__get_cloud_credential_printer (
347382 app_type ,
348383 console ,
349384 mode ,
350- profile_or_alias ,
385+ alias or profile ,
351386 self .silent ,
352- credentials
353- )
354- cc_printer .print ()
387+ credentials ,
388+ aws_credentials_file
389+ ) .print ()
355390
356391 def import_existing_npm_config (self ):
357392 profile_aliases = self .config .import_global_npm_config ()
0 commit comments