Example #1
0
 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
Example #2
0
    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
Example #3
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')
Example #4
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')
Example #5
0
    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
Example #6
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')
Example #7
0
 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
Example #8
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
Example #9
0
 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
Example #10
0
 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
Example #11
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
Example #12
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))
Example #13
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))
Example #14
0
    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
Example #16
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)
Example #17
0
    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')
Example #18
0
    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')
Example #19
0
    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])
Example #20
0
    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")
Example #21
0
    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")
Example #22
0
    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()
Example #23
0
 def _print_to_error_file(self, statement):
     uni_print(statement, self._error_file)
Example #24
0
    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
Example #25
0
 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)
Example #26
0
 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')
Example #27
0
 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'))
Example #28
0
 def _print_to_out_file(self, statement):
     uni_print(statement, self._out_file)
Example #29
0
 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
Example #30
0
 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
Example #31
0
 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'))
Example #32
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
Example #33
0
 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)
Example #34
0
 def _print_to_error_file(self, statement):
     uni_print(statement, self._error_file)
Example #35
0
 def _print_to_out_file(self, statement):
     uni_print(statement, self._out_file)
Example #36
0
 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')
Example #37
0
 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