|
1 | 1 | import csv |
| 2 | +import hashlib |
2 | 3 | from datetime import datetime |
3 | 4 | from datetime import timezone |
4 | 5 | from datetime import timedelta |
|
29 | 30 |
|
30 | 31 |
|
31 | 32 | class BritiveCli: |
32 | | - def __init__(self, tenant_name: str = None, token: str = None, silent: bool = False,passphrase: str = None, |
| 33 | + def __init__(self, tenant_name: str = None, token: str = None, silent: bool = False, passphrase: str = None, |
33 | 34 | federation_provider: str = None, from_helper_console_script: bool = False): |
34 | 35 | self.silent = silent |
35 | 36 | self.from_helper_console_script = from_helper_console_script |
@@ -168,6 +169,22 @@ def login(self, explicit: bool = False, browser: str = None): |
168 | 169 | if explicit and should_get_profiles: |
169 | 170 | self._set_available_profiles() # will handle calling cache_profiles() and construct_kube_config() |
170 | 171 |
|
| 172 | + # handle printing the banner |
| 173 | + self._display_banner() |
| 174 | + |
| 175 | + def _display_banner(self): |
| 176 | + if self.silent: |
| 177 | + return |
| 178 | + |
| 179 | + if not Cache().banner_expired(tenant=self.tenant_name): # if banner is not expired yet then nothing to do |
| 180 | + return |
| 181 | + |
| 182 | + # if we get here then we need to at least grab the banner and see if it has changed |
| 183 | + banner = self.b.banner() |
| 184 | + banner_changed = Cache().save_banner(tenant=self.tenant_name, banner=banner) |
| 185 | + if banner and banner_changed: |
| 186 | + self.print(f'*** {banner.get("messageType", "UNKNOWN")}: {banner.get("message", "<no message>")} ***') |
| 187 | + |
171 | 188 | def _update_sdk_user_agent(self): |
172 | 189 | # update the user agent to include the pybritive cli version |
173 | 190 | user_agent = self.b.session.headers.get('User-Agent') |
@@ -593,8 +610,10 @@ def checkin(self, profile, console): |
593 | 610 | transaction_id=transaction_id |
594 | 611 | ) |
595 | 612 |
|
596 | | - if application_type in ('aws', 'aws standalone'): |
| 613 | + if application_type in ['aws', 'aws standalone']: |
597 | 614 | self.clear_cached_aws_credentials(profile) |
| 615 | + if application_type in ['gcp']: |
| 616 | + self.clear_gcloud_auth_key_files(profile=profile) |
598 | 617 |
|
599 | 618 | def _checkout(self, profile_name, env_name, app_name, programmatic, blocktime, maxpolltime, justification): |
600 | 619 | try: |
@@ -649,7 +668,7 @@ def _split_profile_into_parts(self, profile): |
649 | 668 | def _extend_checkout(self, profile, console): |
650 | 669 | self.login() |
651 | 670 | parts = self._split_profile_into_parts(profile) |
652 | | - response = self.b.my_access.extend_checkout_by_name( |
| 671 | + self.b.my_access.extend_checkout_by_name( |
653 | 672 | profile_name=parts['profile'], |
654 | 673 | environment_name=parts['env'], |
655 | 674 | application_name=parts['app'], |
@@ -927,8 +946,49 @@ def request_withdraw(self, profile): |
927 | 946 | environment_id=ids['environment_id'] |
928 | 947 | ) |
929 | 948 |
|
930 | | - def clear_gcloud_auth_key_files(self): |
931 | | - self.config.clear_gcloud_auth_key_files() |
| 949 | + @staticmethod |
| 950 | + def build_gcloud_key_file_for_gcloudauthexec(profile: str): |
| 951 | + profile_hash = hashlib.sha256(string=profile.encode('utf-8')).hexdigest() |
| 952 | + return f'gcloudauthexec-{profile_hash}.json' |
| 953 | + |
| 954 | + def clear_gcloud_auth_key_files(self, profile: str = None): |
| 955 | + if profile: # we want to attempt a gcloud cli command |
| 956 | + import subprocess # lazy load as this will not always be needed |
| 957 | + |
| 958 | + # build the path to the key file in question |
| 959 | + key_file = self.build_gcloud_key_file_for_gcloudauthexec(profile=profile) |
| 960 | + path = Path(self.config.gcloud_key_file_path) / key_file |
| 961 | + |
| 962 | + if path.exists(): # we have a valid gcloudauthexec key file, so we know there was a checkout with this mode |
| 963 | + try: |
| 964 | + with open(str(path), 'r') as f: |
| 965 | + credentials = json.loads(f.read()) |
| 966 | + commands = [ |
| 967 | + 'gcloud', |
| 968 | + 'auth', |
| 969 | + 'revoke', |
| 970 | + credentials['client_email'], |
| 971 | + '--verbosity=error' |
| 972 | + ] |
| 973 | + self.debug(' '.join(commands)) |
| 974 | + subprocess.run(commands, check=True) |
| 975 | + |
| 976 | + gcloud_default_account = self.config.gcloud_default_account() |
| 977 | + |
| 978 | + if gcloud_default_account: |
| 979 | + commands = [ |
| 980 | + 'gcloud', |
| 981 | + 'config', |
| 982 | + 'set', |
| 983 | + 'account', |
| 984 | + gcloud_default_account, # no need for "" here as subprocess will properly escape |
| 985 | + '--verbosity=error' |
| 986 | + ] |
| 987 | + self.debug(' '.join(commands)) |
| 988 | + subprocess.run(commands, check=True) |
| 989 | + except Exception as e: |
| 990 | + self.print(f'could not reset gcloud CLI active account due to issue: {str(e)}') |
| 991 | + self.config.clear_gcloud_auth_key_files(profile=profile) |
932 | 992 |
|
933 | 993 | def api(self, method, parameters: dict, query=None): |
934 | 994 | self.login() |
|
0 commit comments