def _handle_multiple_accounts(self, accounts): available_accounts_msg = ( 'There are {} AWS accounts available to you.\n') uni_print(available_accounts_msg.format(len(accounts))) selected_account = self._selector(accounts, display_account) sso_account_id = selected_account['accountId'] return sso_account_id
def _run_main(self, parsed_args, parsed_globals): self._unset_session_profile() start_url = self._prompt_for_start_url() sso_region = self._prompt_for_sso_region() sso_token = do_sso_login( self._session, sso_region, start_url, token_cache=self._sso_token_cache, ) # Construct an SSO client to explore the accounts / roles client_config = Config( signature_version=UNSIGNED, region_name=sso_region, ) sso = self._session.create_client('sso', config=client_config) sso_account_id = self._prompt_for_account(sso, sso_token) sso_role_name = self._prompt_for_role(sso, sso_token, sso_account_id) # General CLI configuration self._prompt_for_cli_default_region() self._prompt_for_cli_output_format() profile_name = self._prompt_for_profile(sso_account_id, sso_role_name) usage_msg = ('\nTo use this profile, specify the profile name using ' '--profile, as shown:\n\n' 'aws s3 ls --profile {}\n') uni_print(usage_msg.format(profile_name)) self._write_new_config(profile_name) return 0
def test_encoding_statement_fails_are_replaced(self): buf = io.BytesIO() out = io.TextIOWrapper(buf, encoding='ascii') utils.uni_print(u'SomeChars\u2713\u2714OtherChars', out) # We replace the characters that can't be encoded # with '?'. self.assertEqual(buf.getvalue(), b'SomeChars??OtherChars')
def _run_main(self, parsed_args, parsed_globals): client_factory = STSClientFactory(self._session) sts_client = client_factory.get_sts_client( region_name=parsed_globals.region, role_arn=parsed_args.role_arn ) token = TokenGenerator(sts_client).get_token(parsed_args.cluster_name) # By default STS signs the url for 15 minutes so we are creating a # rfc3339 timestamp with expiration in 14 minutes as part of the token, which # is used by some clients (client-go) who will refresh the token after 14 mins token_expiration = self.get_expiration_time() full_object = { "kind": "ExecCredential", "apiVersion": self.discover_api_version(), "spec": {}, "status": { "expirationTimestamp": token_expiration, "token": token, }, } uni_print(json.dumps(full_object)) uni_print('\n') return 0
def _run_main(self, parsed_args, parsed_globals, token_generator=None): if token_generator is None: token_generator = TokenGenerator(self._session) token = token_generator.get_token( parsed_args.cluster_name, parsed_args.role_arn, parsed_globals.region, ) # By default STS signs the url for 15 minutes so we are creating a # rfc3339 timestamp with expiration in 14 minutes as part of the token, which # is used by some clients (client-go) who will refresh the token after 14 mins token_expiration = self.get_expiration_time() full_object = { "kind": "ExecCredential", "apiVersion": "client.authentication.k8s.io/v1alpha1", "spec": {}, "status": { "expirationTimestamp": token_expiration, "token": token } } uni_print(json.dumps(full_object)) uni_print('\n')
def _run_main(self, parsed_args, parsed_globals): sso_config = self._get_sso_config() do_sso_login(session=self._session, sso_region=sso_config['sso_region'], start_url=sso_config['sso_start_url'], force_refresh=True) success_msg = 'Successully logged into Start URL: %s\n' uni_print(success_msg % sso_config['sso_start_url']) return 0
def _prompt_for_account(self, sso, sso_token): accounts = self._get_all_accounts(sso, sso_token)['accountList'] if not accounts: raise RuntimeError('No AWS accounts are available to you.') if len(accounts) == 1: sso_account_id = self._handle_single_account(accounts) else: sso_account_id = self._handle_multiple_accounts(accounts) uni_print('Using the account ID {}\n'.format(sso_account_id)) self._new_values['sso_account_id'] = sso_account_id return sso_account_id
def _prompt_for_role(self, sso, sso_token, sso_account_id): roles = self._get_all_roles(sso, sso_token, sso_account_id)['roleList'] if not roles: error_msg = 'No roles are available for the account {}' raise RuntimeError(error_msg.format(sso_account_id)) if len(roles) == 1: sso_role_name = self._handle_single_role(roles) else: sso_role_name = self._handle_multiple_roles(roles) uni_print('Using the role name "{}"\n'.format(sso_role_name)) self._new_values['sso_role_name'] = sso_role_name return sso_role_name
def _run_main(self, parsed_args, parsed_globals): rds = self._session.create_client( 'rds', region_name=parsed_globals.region, endpoint_url=parsed_globals.endpoint_url, verify=parsed_globals.verify_ssl) token = rds.generate_db_auth_token(DBHostname=parsed_args.hostname, Port=parsed_args.port, DBUsername=parsed_args.username) uni_print(token) uni_print('\n') return 0
def _run_main(self, parsed_args, parsed_globals): rds = self._session.create_client( 'rds', parsed_globals.region, parsed_globals.endpoint_url, parsed_globals.verify_ssl ) token = rds.generate_db_auth_token( DBHostname=parsed_args.hostname, Port=parsed_args.port, DBUsername=parsed_args.username ) uni_print(token) uni_print('\n') return 0
def warn_of_missing_dependencies(): """ Check the dependencies of the kubectl configuration generated by update-kubeconfig to see if any are missing. If they are missing, print a warning with information on how to download the missing dependency Currently dependent on: aws-iam-authenticator """ if not check_for_binary(AUTH_BIN): uni_print("Warning: {0} is not installed properly or is not in your path.\n" "Refer to the AWS Documentation to download it at " "https://docs.aws.amazon.com/eks/latest/userguide/configure-kubectl.html\n".format(AUTH_BIN))
def login(self, dry_run=False): try: source_to_url_dict = self._get_source_to_url_dict() except OSError as ex: if ex.errno == errno.ENOENT: raise ValueError(self._TOOL_NOT_FOUND_MESSAGE % 'nuget') raise ex nuget_index_url = self._NUGET_INDEX_URL_FMT.format( endpoint=self.repository_endpoint) source_name, already_exists = self._get_source_name( nuget_index_url, source_to_url_dict) if already_exists: command = self._get_command('update', nuget_index_url, source_name) source_configured_message = self._SOURCE_UPDATED_MESSAGE else: command = self._get_command('add', nuget_index_url, source_name) source_configured_message = self._SOURCE_ADDED_MESSAGE if dry_run: dry_run_command = ' '.join([str(cd) for cd in command]) uni_print(dry_run_command) uni_print('\n') return try: self.subprocess_utils.check_output( command, stderr=self.subprocess_utils.PIPE) except subprocess.CalledProcessError as e: uni_print('Failed to update the NuGet.Config\n') raise e uni_print(source_configured_message % source_name) self._write_success_message('nuget')
def _run_main(self, parsed_args, parsed_globals): """Call to run the commands""" self._cluster_name = parsed_args.cluster_name self._namespace = parsed_args.namespace self._role_name = parsed_args.role_name self._region = get_region(self._session, parsed_globals) self._endpoint_url = parsed_args.iam_endpoint self._dry_run = parsed_args.dry_run result = self._update_role_trust_policy(parsed_globals) uni_print(result) uni_print("\n") return 0
def __call__(self, userCode, verificationUri, verificationUriComplete, **kwargs): opening_msg = ( 'Attempting to automatically open the SSO authorization page in ' 'your default browser.\nIf the browser does not open or you wish ' 'to use a different device to authorize this request, open the ' 'following URL:\n' '\n%s\n' '\nThen enter the code:\n' '\n%s\n') uni_print(opening_msg % (verificationUri, userCode), self._outfile) if self._open_browser: try: return self._open_browser(verificationUriComplete) except Exception: LOG.debug('Failed to open browser:', exc_info=True)
def _run_main(self, parsed_args, parsed_globals): token_generator = TokenGenerator(parsed_globals.region) token = token_generator.get_token(parsed_args.cluster_name, parsed_args.role_arn) full_object = { "kind": "ExecCredential", "apiVersion": "client.authentication.k8s.io/v1alpha1", "spec": {}, "status": { "token": token } } uni_print(json.dumps(full_object)) uni_print('\n')
def _run_main(self, parsed_args, parsed_globals): token_generator = TokenGenerator(parsed_globals.region) token = token_generator.get_token( parsed_args.cluster_name, parsed_args.role_arn ) full_object = { "kind": "ExecCredential", "apiVersion": "client.authentication.k8s.io/v1alpha1", "spec": {}, "status": { "token": token } } uni_print(json.dumps(full_object)) uni_print('\n')
def _run_main(self, parsed_args, parsed_globals): client = EKSClient(self._session, parsed_args.name, parsed_args.role_arn, parsed_globals) new_cluster_dict = client.get_cluster_entry() new_user_dict = client.get_user_entry() config_selector = KubeconfigSelector(os.environ.get("KUBECONFIG", ""), parsed_args.kubeconfig) config = config_selector.choose_kubeconfig(new_cluster_dict["name"]) updating_existing = config.has_cluster(new_cluster_dict["name"]) appender = KubeconfigAppender() new_context_dict = appender.insert_cluster_user_pair( config, new_cluster_dict, new_user_dict, parsed_args.alias) if parsed_args.dry_run: uni_print(config.dump_content()) else: writer = KubeconfigWriter() writer.write_kubeconfig(config) if updating_existing: uni_print("Updated context {0} in {1}\n".format( new_context_dict["name"], config.path)) else: uni_print("Added new context {0} to {1}\n".format( new_context_dict["name"], config.path)) if parsed_args.verbose: self._display_entries( [new_context_dict, new_user_dict, new_cluster_dict])
def _display_entries(self, entries): """ Display entries in yaml format :param entries: a list of OrderedDicts to be printed :type entries: list """ uni_print("Entries:\n\n") for entry in entries: uni_print(ordered_yaml_dump(entry)) uni_print("\n")
def _run_main(self, parsed_args, parsed_globals): client = EKSClient(self._session, parsed_args.name, parsed_args.role_arn, parsed_globals) new_cluster_dict = client.get_cluster_entry() new_user_dict = client.get_user_entry() config_selector = KubeconfigSelector( os.environ.get("KUBECONFIG", ""), parsed_args.kubeconfig ) config = config_selector.choose_kubeconfig( new_cluster_dict["name"] ) updating_existing = config.has_cluster(new_cluster_dict["name"]) appender = KubeconfigAppender() new_context_dict = appender.insert_cluster_user_pair(config, new_cluster_dict, new_user_dict, parsed_args.alias) if parsed_args.dry_run: uni_print(config.dump_content()) else: writer = KubeconfigWriter() writer.write_kubeconfig(config) if updating_existing: uni_print("Updated context {0} in {1}\n".format( new_context_dict["name"], config.path )) else: uni_print("Added new context {0} to {1}\n".format( new_context_dict["name"], config.path )) if parsed_args.verbose: self._display_entries([ new_context_dict, new_user_dict, new_cluster_dict ]) warn_of_missing_dependencies()
def _print_to_error_file(self, statement): uni_print(statement, self._error_file)
def discover_api_version(self): """ Parses the KUBERNETES_EXEC_INFO environment variable and returns the API version. If the environment variable is malformed or invalid, return the v1beta1 response and print a message to stderr. If the v1alpha1 API is specified explicitly, a message is printed to stderr with instructions to update. :return: The client authentication API version :rtype: string """ # At the time Kubernetes v1.29 is released upstream (approx Dec 2023), # "v1beta1" will be removed. At or around that time, EKS will likely # support v1.22 through v1.28, in which client API version "v1beta1" # will be supported by all EKS versions. fallback_api_version = BETA_API error_prefixes = { "error": "Error parsing", "empty": "Empty", } exec_info_raw = os.environ.get("KUBERNETES_EXEC_INFO", "") if not exec_info_raw: # All kube clients should be setting this, but client-go clients # (kubectl, kubelet, etc) < 1.20 were not setting this if the API # version defined in the kubeconfig was not v1alpha1. # # This was changed in kubernetes/kubernetes#95489 so that # KUBERNETES_EXEC_INFO is always provided return fallback_api_version try: exec_info = json.loads(exec_info_raw) except json.JSONDecodeError: # The environment variable was malformed uni_print( ERROR_MSG_TPL.format( error_prefixes["error"], fallback_api_version, ), sys.stderr, ) uni_print("\n", sys.stderr) return fallback_api_version api_version_raw = exec_info.get("apiVersion") if api_version_raw in FULLY_SUPPORTED_API_VERSIONS: return api_version_raw elif api_version_raw in DEPRECATED_API_VERSIONS: uni_print(DEPRECATION_MSG_TPL.format(api_version_raw), sys.stderr) uni_print("\n", sys.stderr) return api_version_raw else: uni_print( UNRECOGNIZED_MSG_TPL.format(fallback_api_version), sys.stderr, ) uni_print("\n", sys.stderr) return fallback_api_version
def _clear_progress_if_no_more_expected_transfers(self, **kwargs): if self._progress_length and not self._has_remaining_progress(): uni_print(self._adjust_statement_padding(''), self._out_file)
def test_encoding_with_encoding_none(self): '''When the output of the aws command is being piped, the `encoding` attribute of `sys.stdout` is `None`.''' out = MockPipedStdout() utils.uni_print(u'SomeChars\u2713\u2714OtherChars', out) self.assertEqual(out.getvalue(), b'SomeChars??OtherChars')
def test_out_file_with_encoding_attribute(self): buf = io.BytesIO() out = io.TextIOWrapper(buf, encoding='utf-8') utils.uni_print(u'\u2713', out) self.assertEqual(buf.getvalue(), u'\u2713'.encode('utf-8'))
def _print_to_out_file(self, statement): uni_print(statement, self._out_file)
def _handle_multiple_roles(self, roles): available_roles_msg = 'There are {} roles available to you.\n' uni_print(available_roles_msg.format(len(roles))) role_names = [r['roleName'] for r in roles] sso_role_name = self._selector(role_names) return sso_role_name
def _run_main(self, parsed_args, parsed_globals): for profile in self._session.available_profiles: uni_print('%s\n' % profile, out_file=self._out_stream) return 0
def _handle_single_account(self, accounts): sso_account_id = accounts[0]['accountId'] single_account_msg = ('The only AWS account available to you is: {}\n') uni_print(single_account_msg.format(sso_account_id)) return sso_account_id
def _handle_single_role(self, roles): sso_role_name = roles[0]['roleName'] available_roles_msg = 'The only role available to you is: {}\n' uni_print(available_roles_msg.format(sso_role_name)) return sso_role_name