diff --git a/changelog/23260.txt b/changelog/23260.txt
new file mode 100644
index 000000000..52de9b805
--- /dev/null
+++ b/changelog/23260.txt
@@ -0,0 +1,3 @@
+```release-note:improvement
+ui: Adds warning before downloading KV v2 secret values
+```
\ No newline at end of file
diff --git a/ui/lib/core/addon/components/download-button.js b/ui/lib/core/addon/components/download-button.js
index 49f17f8a5..45d4e3fbf 100644
--- a/ui/lib/core/addon/components/download-button.js
+++ b/ui/lib/core/addon/components/download-button.js
@@ -34,6 +34,7 @@ import { assert } from '@ember/debug';
* @param {function} [fetchData] - function that fetches data and returns download content
* @param {string} [extension='txt'] - file extension, the download service uses this to determine the mimetype
* @param {boolean} [stringify=false] - argument to stringify the data before passing to the File constructor
+ * @param {callback} [onSuccess] - callback from parent to invoke if download is successful
*/
export default class DownloadButton extends Component {
@@ -73,6 +74,9 @@ export default class DownloadButton extends Component {
try {
this.download.miscExtension(this.filename, this.content, this.extension);
this.flashMessages.info(`Downloading ${this.filename}`);
+ if (this.args.onSuccess) {
+ this.args.onSuccess();
+ }
} catch (error) {
this.flashMessages.danger(errorMessage(error, 'There was a problem downloading. Please try again.'));
}
diff --git a/ui/lib/core/addon/components/masked-input.hbs b/ui/lib/core/addon/components/masked-input.hbs
index c08edb9eb..551b9c4d7 100644
--- a/ui/lib/core/addon/components/masked-input.hbs
+++ b/ui/lib/core/addon/components/masked-input.hbs
@@ -35,15 +35,9 @@
{{/if}}
{{#if @allowDownload}}
-
-
-
+
{{/if}}
-
\ No newline at end of file
+
+
+{{! CONFIRM DOWNLOAD MODAL }}
+{{#if @allowDownload}}
+
+
+ This download is
+ unencrypted. Are you sure you want to download this secret data as plaintext?
+
+
+
+{{/if}}
\ No newline at end of file
diff --git a/ui/lib/core/addon/components/masked-input.js b/ui/lib/core/addon/components/masked-input.js
index 1729b95d2..ffae45c12 100644
--- a/ui/lib/core/addon/components/masked-input.js
+++ b/ui/lib/core/addon/components/masked-input.js
@@ -27,12 +27,14 @@ import autosize from 'autosize';
* @param name {String} - The key correlated to the value. Used for the download file name.
* @param [onChange=Callback] {Function|action} - Callback triggered on change, sends new value. Must set the value of @value
* @param [allowCopy=false] {bool} - Whether or not the input should render with a copy button.
+ * @param [allowDownload=false] {bool} - Renders a download button that prompts a confirmation modal to download the secret value
* @param [displayOnly=false] {bool} - Whether or not to display the value as a display only `pre` element or as an input.
*
*/
export default class MaskedInputComponent extends Component {
textareaId = 'textarea-' + guidFor(this);
@tracked showValue = false;
+ @tracked modalOpen = false;
constructor() {
super(...arguments);
diff --git a/ui/tests/index.html b/ui/tests/index.html
index b8c5799e9..37974a1f5 100644
--- a/ui/tests/index.html
+++ b/ui/tests/index.html
@@ -6,29 +6,27 @@