Example #1
0
    def edit(self) -> None:
        """
        Allows a user to define a PS name and add or edit a parameter at that location. Uses NPYscreen editor.
        """
        key = Input.input('Please input a PS Name: ',
                          completer=self._config_completer)

        try:
            value, desc = self._ssm.get_parameter_with_description(key)
            edit_app = EditApp(key, value, desc)
            edit_app.run()

            value, desc = edit_app.value_box.value, edit_app.description_box.value
            log.info(f"Edited value: {value} - description: {desc}")

            is_secret = Input.is_secret()
            parameter_type, kms_id = SSM_SECURE_STRING if is_secret else SSM_STRING, None
            if is_secret:
                valid_keys = self._config_view.get_authorized_kms_keys()
                if len(valid_keys) > 1:
                    key_name = Input.select_kms_key(valid_keys)
                else:
                    key_name = valid_keys[0]

                kms_id = self._config_view.get_authorized_key_id(
                    key_name, self.run_env)

            if not self._utils.is_valid_input(key, f"Parameter name", True) \
                    or not self._utils.is_valid_input(value, key, True):
                self._utils.error_exit(
                    "Invalid input detected, please resolve the issue and retry."
                )

            self._ssm.set_parameter(key,
                                    value,
                                    desc,
                                    parameter_type,
                                    key_id=kms_id)
            print(f"{self.c.fg_gr}{key} saved successfully.{self.c.rs}")
        except ClientError as e:
            if "AccessDeniedException" == e.response['Error']['Code']:
                denied = "AccessDeniedException" == e.response['Error']['Code']
                if denied and "AWSKMS; Status Code: 400;" in e.response[
                        'Error']['Message']:
                    print(
                        f"\n{self.c.fg_rd}You do not have access to decrypt the value of: {key}{self.c.rs}"
                    )
                elif denied:
                    print(
                        f"\n{self.c.fg_rd}You do not have access to Parameter: {key}{self.c.rs}"
                    )
                else:
                    raise
            else:
                self._utils.error_exit(
                    f"{self.c.fg_rd}Exception caught attempting to add config: {e}{self.c.rs}"
                )
Example #2
0
    def put_param(self, key=None, loop=False, display_hints=True) -> None:
        """
        Allows a user to define a PS name and add a new parameter at that named location. User will be prompted for a
        value, desc, and whether or not the parameter is a secret. If (Y) is selected for the secret, will encrypt the
        value with the appropriately mapped KMS key with the user's role.

        :param key: If specified, the user will be prompted for the specified key. Otherwise the user will be prompted
                    to specify the PS key to set.
        :param loop: Whether or not to continually loop and continue prompting the user for more keys.
        :param display_hints: Whether or not to display "Hints" to the user. You may want to turn this off if you are
                              looping and constantly calling put_param with a specified key.
        """

        value, desc, notify, put_another = True, None, False, True

        if display_hints:
            self._out.print(
                f"[[Hint:]] To upload a file's contents, pass in `file:///path/to/your/file` "
                f"in the value prompt.")

        while put_another:
            try:

                if not key:
                    lexer = PygmentsLexer(
                        FigLexer
                    ) if self.context.defaults.colors_enabled else None
                    style = style_from_pygments_cls(
                        FiggyPygment
                    ) if self.context.defaults.colors_enabled else None
                    key = Input.input(
                        'Please input a PS Name: ',
                        completer=self._config_view.get_config_completer(),
                        lexer=lexer,
                        style=style)
                    if self.parameter_is_existing_dir(key):
                        self._out.warn(
                            f'You attempted to store parameter named: {key},'
                            f' but it already exists in ParameterStore as a directory: {key}/'
                        )
                        key = None
                        continue

                if self._source_key:
                    plain_key = '/'.join(key.strip('/').split('/')[2:])
                    source_key = f'{self._source_key}/{plain_key}'
                    orig_value, orig_description = self._get.get_val_and_desc(
                        source_key)
                else:
                    orig_description = ''
                    orig_value = ''

                value = Input.input(f"Please input a value for {key}: ",
                                    default=orig_value if orig_value else '')

                if value.lower().startswith(self._FILE_PREFIX):
                    value = Utils.load_file(
                        value.replace(self._FILE_PREFIX, ""))

                existing_desc = self._ssm.get_description(key)
                desc = Input.input(
                    f"Please input an optional description: ",
                    optional=True,
                    default=existing_desc if existing_desc else
                    orig_description if orig_description else '')

                is_secret = Input.is_secret()
                parameter_type, kms_id = SSM_SECURE_STRING if is_secret else SSM_STRING, None
                if is_secret:
                    valid_keys = self._config_view.get_authorized_kms_keys()
                    if len(valid_keys) > 1:
                        key_name = Input.select_kms_key(valid_keys)
                    else:
                        key_name = valid_keys[0]

                    kms_id = self._config_view.get_authorized_key_id(
                        key_name, self.run_env)

                notify = True

                self._ssm.set_parameter(key,
                                        value,
                                        desc,
                                        parameter_type,
                                        key_id=kms_id)
                if key not in self._config_view.get_config_completer().words:
                    self._config_view.get_config_completer().words.append(key)

            except ClientError as e:
                if "AccessDeniedException" == e.response['Error']['Code']:
                    self._out.error(
                        f"\n\nYou do not have permissions to add config values at the path: [[{key}]]"
                    )
                    self._out.warn(
                        f"Your role of {self.context.role} may add keys under the following namespaces: "
                        f"{self._config_view.get_authorized_namespaces()}")
                    self._out.print(
                        f"Error message: {e.response['Error']['Message']}")
                else:
                    self._out.error(
                        f"Exception caught attempting to add config: {e}")

            print()
            if loop:
                to_continue = input(f"\nAdd another? (y/N): ")
                put_another = True if to_continue.lower() == 'y' else False
                key = None
            else:
                put_another = False