mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-10-29 17:52:32 +00:00
Glimmerize Transit Key Actions (#25365)
* wip, all actions wired up, not finished or tested. * move the rotate action to it's own component to clarify scope * clean up and refresh component on queryParam change without forcing a refresh from component as before * solve issue of carrying over props we want to keep * clean up and add clearProps action * transit key actions passing * update assert and doc * remove unecessary changes * Address pr comments * replace perform in submit action and instead pass it in as perform * address claire's pr comments * welp * trying to rearrange closer to original * addressing pr comments * move things around * pr comments * remove ciphertext when last action was rewrap * add args and istruncated and isfullwidth
This commit is contained in:
27
ui/app/components/transit-form-show.js
Normal file
27
ui/app/components/transit-form-show.js
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Copyright (c) HashiCorp, Inc.
|
||||
* SPDX-License-Identifier: BUSL-1.1
|
||||
*/
|
||||
|
||||
import Component from '@glimmer/component';
|
||||
import { service } from '@ember/service';
|
||||
import { action } from '@ember/object';
|
||||
import errorMessage from 'vault/utils/error-message';
|
||||
|
||||
export default class TransitFormShow extends Component {
|
||||
@service store;
|
||||
@service router;
|
||||
@service flashMessages;
|
||||
|
||||
@action async rotateKey() {
|
||||
const { backend, id } = this.args.key;
|
||||
try {
|
||||
await this.store.adapterFor('transit-key').keyAction('rotate', { backend, id });
|
||||
this.flashMessages.success('Key rotated.');
|
||||
// must refresh to see the updated versions, a model refresh does not trigger the change.
|
||||
await this.router.refresh();
|
||||
} catch (e) {
|
||||
this.flashMessages.danger(errorMessage(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,8 +7,5 @@ import Component from '@glimmer/component';
|
||||
import { tracked } from '@glimmer/tracking';
|
||||
|
||||
export default class ExportComponent extends Component {
|
||||
@tracked
|
||||
wrapTTL = null;
|
||||
@tracked
|
||||
exportVersion = false;
|
||||
@tracked exportVersion = false;
|
||||
}
|
||||
|
||||
134
ui/app/components/transit-key-actions.hbs
Normal file
134
ui/app/components/transit-key-actions.hbs
Normal file
@@ -0,0 +1,134 @@
|
||||
{{!
|
||||
Copyright (c) HashiCorp, Inc.
|
||||
SPDX-License-Identifier: BUSL-1.1
|
||||
~}}
|
||||
|
||||
<div {{did-update this.updateProps @selectedAction}}>
|
||||
<MessageError @errorMessage={{this.errors}} />
|
||||
|
||||
{{#if (eq @selectedAction "encrypt")}}
|
||||
<TransitKeyAction::Encrypt
|
||||
@key={{@key}}
|
||||
@param={{this.props.param}}
|
||||
@context={{this.props.context}}
|
||||
@nonce={{this.props.nonce}}
|
||||
@bits={{this.props.bits}}
|
||||
@key_version={{this.props.key_version}}
|
||||
@encodedBase64={{this.props.encodedBase64}}
|
||||
@toggleEncodeBase64={{this.toggleEncodeBase64}}
|
||||
@plaintext={{this.props.plaintext}}
|
||||
@ciphertext={{this.props.ciphertext}}
|
||||
@doSubmit={{perform this.doSubmit}}
|
||||
@isModalActive={{this.isModalActive}}
|
||||
data-test-transit-action={{@selectedAction}}
|
||||
/>
|
||||
{{else if (eq @selectedAction "decrypt")}}
|
||||
<TransitKeyAction::Decrypt
|
||||
@key={{@key}}
|
||||
@ciphertext={{this.props.ciphertext}}
|
||||
@context={{this.props.context}}
|
||||
@nonce={{this.props.nonce}}
|
||||
@isModalActive={{this.isModalActive}}
|
||||
@plaintext={{this.props.plaintext}}
|
||||
@doSubmit={{perform this.doSubmit}}
|
||||
data-test-transit-action={{@selectedAction}}
|
||||
/>
|
||||
{{else if (eq @selectedAction "datakey")}}
|
||||
<TransitKeyAction::Datakey
|
||||
@key={{@key}}
|
||||
@param={{this.props.param}}
|
||||
@context={{this.props.context}}
|
||||
@nonce={{this.props.nonce}}
|
||||
@bits={{this.props.bits}}
|
||||
@plaintext={{this.props.plaintext}}
|
||||
@ciphertext={{this.props.ciphertext}}
|
||||
@doSubmit={{perform this.doSubmit}}
|
||||
@isModalActive={{this.isModalActive}}
|
||||
data-test-transit-action={{@selectedAction}}
|
||||
/>
|
||||
{{else if (eq @selectedAction "rewrap")}}
|
||||
<TransitKeyAction::Rewrap
|
||||
@key={{@key}}
|
||||
@param={{this.props.param}}
|
||||
@context={{this.props.context}}
|
||||
@nonce={{this.props.nonce}}
|
||||
@key_version={{this.props.key_version}}
|
||||
@ciphertext={{this.props.ciphertext}}
|
||||
@isModalActive={{this.isModalActive}}
|
||||
@doSubmit={{perform this.doSubmit}}
|
||||
data-test-transit-action={{@selectedAction}}
|
||||
/>
|
||||
{{else if (eq @selectedAction "hmac")}}
|
||||
<TransitKeyAction::Hmac
|
||||
@key={{@key}}
|
||||
@trackedInput={{this.props.input}}
|
||||
@algorithm={{this.props.algorithm}}
|
||||
@key_version={{this.props.key_version}}
|
||||
@encodedBase64={{this.props.encodedBase64}}
|
||||
@toggleEncodeBase64={{this.toggleEncodeBase64}}
|
||||
@hmac={{this.props.hmac}}
|
||||
@isModalActive={{this.isModalActive}}
|
||||
@doSubmit={{perform this.doSubmit}}
|
||||
data-test-transit-action={{@selectedAction}}
|
||||
/>
|
||||
{{else if (eq @selectedAction "verify")}}
|
||||
<TransitKeyAction::Verify
|
||||
@key={{@key}}
|
||||
@trackedInput={{this.props.input}}
|
||||
@signature={{this.props.signature}}
|
||||
@signature_algorithm={{this.props.signature_algorithm}}
|
||||
@hmac={{this.props.hmac}}
|
||||
@hash_algorithm={{this.props.hash_algorithm}}
|
||||
@context={{this.props.context}}
|
||||
@prehashed={{this.props.prehashed}}
|
||||
@encodedBase64={{this.props.encodedBase64}}
|
||||
@verification={{this.props.verification}}
|
||||
@valid={{this.props.valid}}
|
||||
@toggleEncodeBase64={{this.toggleEncodeBase64}}
|
||||
@keyIsRSA={{this.keyIsRSA}}
|
||||
@isModalActive={{this.isModalActive}}
|
||||
@doSubmit={{perform this.doSubmit}}
|
||||
@submitIsRunning={{this.doSubmit.isRunning}}
|
||||
@clearSpecificProps={{this.clearSpecificProps}}
|
||||
data-test-transit-action={{@selectedAction}}
|
||||
/>
|
||||
{{else if (eq @selectedAction "sign")}}
|
||||
<TransitKeyAction::Sign
|
||||
@key={{@key}}
|
||||
@trackedInput={{this.props.input}}
|
||||
@hash_algorithm={{this.props.hash_algorithm}}
|
||||
@signature={{this.props.signature}}
|
||||
@signature_algorithm={{this.props.signature_algorithm}}
|
||||
@key_version={{this.props.key_version}}
|
||||
@context={{this.props.context}}
|
||||
@prehashed={{this.props.prehashed}}
|
||||
@encodedBase64={{this.props.encodedBase64}}
|
||||
@toggleEncodeBase64={{this.toggleEncodeBase64}}
|
||||
@isModalActive={{this.isModalActive}}
|
||||
@doSubmit={{perform this.doSubmit}}
|
||||
@submitIsRunning={{this.doSubmit.isRunning}}
|
||||
data-test-transit-action={{@selectedAction}}
|
||||
/>
|
||||
{{else if (or (eq @selectedAction "export") (eq @key.supportedActions.firstObject "export"))}}
|
||||
<TransitKeyAction::Export
|
||||
@key={{@key}}
|
||||
@keys={{this.props.keys}}
|
||||
@trackedInput={{this.props.input}}
|
||||
@hash_algorithm={{this.props.hash_algorithm}}
|
||||
@signature={{this.props.signature}}
|
||||
@signature_algorithm={{this.props.signature_algorithm}}
|
||||
@key_version={{this.props.key_version}}
|
||||
@context={{this.props.context}}
|
||||
@prehashed={{this.props.prehashed}}
|
||||
@encodedBase64={{this.props.encodedBase64}}
|
||||
@exportKeyType={{this.props.exportKeyType}}
|
||||
@exportKeyVersion={{this.props.exportKeyVersion}}
|
||||
@wrappedToken={{this.props.wrappedToken}}
|
||||
@wrappedTTL={{this.props.wrappedTTL}}
|
||||
@toggleEncodeBase64={{this.toggleEncodeBase64}}
|
||||
@isModalActive={{this.isModalActive}}
|
||||
@doSubmit={{perform this.doSubmit}}
|
||||
data-test-transit-action="export"
|
||||
/>
|
||||
{{/if}}
|
||||
</div>
|
||||
@@ -3,15 +3,31 @@
|
||||
* SPDX-License-Identifier: BUSL-1.1
|
||||
*/
|
||||
|
||||
import { assign } from '@ember/polyfills';
|
||||
import { copy } from 'ember-copy';
|
||||
import { assert } from '@ember/debug';
|
||||
import Component from '@glimmer/component';
|
||||
import { service } from '@ember/service';
|
||||
import Component from '@ember/component';
|
||||
import { set, get, computed } from '@ember/object';
|
||||
import { action } from '@ember/object';
|
||||
import { assert } from '@ember/debug';
|
||||
import { tracked } from '@glimmer/tracking';
|
||||
import { task } from 'ember-concurrency';
|
||||
import { waitFor } from '@ember/test-waiters';
|
||||
import { encodeString } from 'vault/utils/b64';
|
||||
import errorMessage from 'vault/utils/error-message';
|
||||
|
||||
const TRANSIT_PARAMS = {
|
||||
/**
|
||||
* @module TransitKeyActions
|
||||
* TransitKeyActions component handles the actions a user can take on a transit key model. The model and props are updated on every tab change
|
||||
*
|
||||
* @example
|
||||
* <TransitKeyActions
|
||||
* @key={{this.model}}
|
||||
* @selectedAction="hmac"
|
||||
* />
|
||||
*
|
||||
* @param {string} selectedAction - This is the query param "action" value. Ex: hmac, verify, decrypt, etc. The only time this param can be empty is if a user is exporting a key
|
||||
* @param {object} key - This is the transit key model.
|
||||
*/
|
||||
|
||||
const STARTING_TRANSIT_PROPS = {
|
||||
hash_algorithm: 'sha2-256',
|
||||
algorithm: 'sha2-256',
|
||||
signature_algorithm: 'pss',
|
||||
@@ -35,161 +51,101 @@ const TRANSIT_PARAMS = {
|
||||
exportKeyType: null,
|
||||
exportKeyVersion: null,
|
||||
wrappedToken: null,
|
||||
wrappedTTL: '30m',
|
||||
valid: null,
|
||||
plaintextOriginal: null,
|
||||
didDecode: false,
|
||||
verification: 'Signature',
|
||||
};
|
||||
const PARAMS_FOR_ACTION = {
|
||||
|
||||
const PROPS_TO_KEEP = {
|
||||
encrypt: ['plaintext', 'context', 'nonce', 'key_version'],
|
||||
decrypt: ['ciphertext', 'context', 'nonce'],
|
||||
sign: ['input', 'hash_algorithm', 'key_version', 'prehashed', 'signature_algorithm'],
|
||||
verify: ['input', 'hmac', 'signature', 'hash_algorithm', 'prehashed'],
|
||||
hmac: ['input', 'algorithm', 'key_version'],
|
||||
encrypt: ['plaintext', 'context', 'nonce', 'key_version'],
|
||||
decrypt: ['ciphertext', 'context', 'nonce'],
|
||||
rewrap: ['ciphertext', 'context', 'nonce', 'key_version'],
|
||||
datakey: [],
|
||||
};
|
||||
|
||||
const SUCCESS_MESSAGE_FOR_ACTION = {
|
||||
sign: 'Signed your data',
|
||||
sign: 'Signed your data.',
|
||||
// the verify action doesn't trigger a success message
|
||||
hmac: 'Created your hash output',
|
||||
encrypt: 'Created a wrapped token for your data',
|
||||
decrypt: 'Decrypted the data from your token',
|
||||
rewrap: 'Created a new token for your data',
|
||||
datakey: 'Generated your key',
|
||||
export: 'Exported your key',
|
||||
hmac: 'Created your hash output.',
|
||||
encrypt: 'Created a wrapped token for your data.',
|
||||
decrypt: 'Decrypted the data from your token.',
|
||||
rewrap: 'Created a new token for your data.',
|
||||
datakey: 'Generated your key.',
|
||||
export: 'Exported your key.',
|
||||
};
|
||||
export default Component.extend(TRANSIT_PARAMS, {
|
||||
store: service(),
|
||||
flashMessages: service(),
|
||||
|
||||
// public attrs
|
||||
selectedAction: null,
|
||||
key: null,
|
||||
isModalActive: false,
|
||||
export default class TransitKeyActions extends Component {
|
||||
@service store;
|
||||
@service flashMessages;
|
||||
@service router;
|
||||
|
||||
onRefresh() {},
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
// TODO figure out why get is needed here Ember Upgrade
|
||||
// eslint-disable-next-line ember/no-get
|
||||
if (this.selectedAction) {
|
||||
return;
|
||||
@tracked isModalActive = false;
|
||||
@tracked errors = null;
|
||||
@tracked props = { ...STARTING_TRANSIT_PROPS }; // Shallow copy of the object. We don't want to mutate the original.
|
||||
|
||||
constructor() {
|
||||
super(...arguments);
|
||||
assert('@key is required for TransitKeyActions components', this.args.key);
|
||||
|
||||
if (this.firstSupportedAction === 'export' || this.args.selectedAction === 'export') {
|
||||
this.props.exportKeyType = this.args.key.exportKeyTypes[0];
|
||||
this.props.exportKeyVersion = this.args.key.validKeyVersions.lastObject;
|
||||
}
|
||||
// eslint-disable-next-line ember/no-get
|
||||
set(this, 'selectedAction', get(this, 'key.supportedActions.firstObject'));
|
||||
assert('`key` is required for `' + this.toString() + '`.', this.getModelInfo());
|
||||
},
|
||||
}
|
||||
|
||||
didReceiveAttrs() {
|
||||
this._super(...arguments);
|
||||
this.checkAction();
|
||||
if (this.selectedAction === 'export') {
|
||||
this.setExportKeyDefaults();
|
||||
}
|
||||
},
|
||||
|
||||
setExportKeyDefaults() {
|
||||
const exportKeyType = this.key.exportKeyTypes.firstObject;
|
||||
const exportKeyVersion = this.key.validKeyVersions.lastObject;
|
||||
this.setProperties({
|
||||
exportKeyType,
|
||||
exportKeyVersion,
|
||||
});
|
||||
},
|
||||
|
||||
keyIsRSA: computed('key.type', function () {
|
||||
const type = this.key.type;
|
||||
get keyIsRSA() {
|
||||
const { type } = this.args.key;
|
||||
return type === 'rsa-2048' || type === 'rsa-3072' || type === 'rsa-4096';
|
||||
}),
|
||||
}
|
||||
|
||||
getModelInfo() {
|
||||
const model = this.key || this.backend;
|
||||
if (!model) {
|
||||
return null;
|
||||
}
|
||||
const backend = model.backend || model.id;
|
||||
const id = model.id;
|
||||
|
||||
return {
|
||||
backend,
|
||||
id,
|
||||
};
|
||||
},
|
||||
|
||||
checkAction() {
|
||||
const currentAction = this.selectedAction;
|
||||
const oldAction = this.oldSelectedAction;
|
||||
|
||||
this.resetParams(oldAction, currentAction);
|
||||
set(this, 'oldSelectedAction', currentAction);
|
||||
},
|
||||
|
||||
resetParams(oldAction, action) {
|
||||
const params = copy(TRANSIT_PARAMS);
|
||||
let paramsToKeep;
|
||||
const clearWithoutCheck =
|
||||
!oldAction ||
|
||||
// don't save values from datakey
|
||||
oldAction === 'datakey' ||
|
||||
// can rewrap signatures — using that as a ciphertext later would be problematic
|
||||
(oldAction === 'rewrap' && !this.key.supportsEncryption);
|
||||
|
||||
if (!clearWithoutCheck && action) {
|
||||
paramsToKeep = PARAMS_FOR_ACTION[action];
|
||||
}
|
||||
|
||||
if (paramsToKeep) {
|
||||
paramsToKeep.forEach((param) => delete params[param]);
|
||||
}
|
||||
//resets params still left in the object to defaults
|
||||
this.clearErrors();
|
||||
this.setProperties(params);
|
||||
if (action === 'export') {
|
||||
this.setExportKeyDefaults();
|
||||
}
|
||||
},
|
||||
|
||||
handleError(e) {
|
||||
this.set('errors', e.errors);
|
||||
},
|
||||
|
||||
clearErrors() {
|
||||
this.set('errors', null);
|
||||
},
|
||||
|
||||
triggerSuccessMessage(action) {
|
||||
const message = SUCCESS_MESSAGE_FOR_ACTION[action];
|
||||
if (!message) return;
|
||||
this.flashMessages.success(message);
|
||||
},
|
||||
get firstSupportedAction() {
|
||||
return this.args.key.supportedActions[0];
|
||||
}
|
||||
|
||||
handleSuccess(resp, options, action) {
|
||||
let props = {};
|
||||
if (resp && resp.data) {
|
||||
if (action === 'export' && resp.data.keys) {
|
||||
const { keys, type, name } = resp.data;
|
||||
resp.data.keys = { keys, type, name };
|
||||
}
|
||||
props = assign({}, props, resp.data);
|
||||
this.props = { ...this.props, ...resp.data };
|
||||
|
||||
// While we do not pass ciphertext as a value to the JsonEditor, so that navigating from rewrap to decrypt will not show ciphertext in the editor, we still want to clear it from the props after rewrapping.
|
||||
if (action === 'rewrap' && !this.args.key.supportsEncryption) {
|
||||
this.props.ciphertext = null;
|
||||
}
|
||||
}
|
||||
if (options.wrapTTL) {
|
||||
props = assign({}, props, { wrappedToken: resp.wrap_info.token });
|
||||
this.props = { ...this.props, ...{ wrappedToken: resp.wrap_info.token } };
|
||||
}
|
||||
if (!this.isDestroyed && !this.isDestroying) {
|
||||
this.toggleProperty('isModalActive');
|
||||
this.setProperties(props);
|
||||
this.isModalActive = true;
|
||||
// verify doesn't trigger a success message
|
||||
if (this.args.selectedAction !== 'verify') {
|
||||
this.flashMessages.success(SUCCESS_MESSAGE_FOR_ACTION[action]);
|
||||
}
|
||||
if (action === 'rotate') {
|
||||
this.onRefresh();
|
||||
}
|
||||
this.triggerSuccessMessage(action);
|
||||
},
|
||||
}
|
||||
|
||||
@action updateProps() {
|
||||
this.errors = null;
|
||||
// There are specific props we want to carry over from the previous tab.
|
||||
// Ex: carrying over this.props.context from the encrypt tab to the decrypt tab, but not carrying over this.props.plaintext.
|
||||
// To do this, we make a new object that contains the old this.props key/values from the previous tab that we want to keep. We then merge that new object into the STARTING_TRANSIT_PROPS object to come up with our new this.props tracked property.
|
||||
// This action is passed to did-update in the component.
|
||||
const transferredProps = PROPS_TO_KEEP[this.args.selectedAction]?.reduce(
|
||||
(obj, key) => ({ ...obj, [key]: this.props[key] }),
|
||||
{}
|
||||
);
|
||||
this.props = { ...STARTING_TRANSIT_PROPS, ...transferredProps };
|
||||
}
|
||||
|
||||
compactData(data) {
|
||||
const type = this.key.type;
|
||||
const isRSA = type === 'rsa-2048' || type === 'rsa-3072' || type === 'rsa-4096';
|
||||
return Object.keys(data).reduce((result, key) => {
|
||||
if (key === 'signature_algorithm' && !isRSA) {
|
||||
if (key === 'signature_algorithm' && !this.keyIsRSA) {
|
||||
return result;
|
||||
}
|
||||
if (data[key]) {
|
||||
@@ -197,51 +153,45 @@ export default Component.extend(TRANSIT_PARAMS, {
|
||||
}
|
||||
return result;
|
||||
}, {});
|
||||
},
|
||||
}
|
||||
|
||||
actions: {
|
||||
onActionChange(action) {
|
||||
set(this, 'selectedAction', action);
|
||||
this.checkAction();
|
||||
},
|
||||
@action toggleEncodeBase64() {
|
||||
this.props.encodedBase64 = !this.props.encodedBase64;
|
||||
}
|
||||
|
||||
onClear() {
|
||||
this.resetParams(null, this.selectedAction);
|
||||
},
|
||||
@action clearSpecificProps(arrayToClear) {
|
||||
arrayToClear.forEach((prop) => (this.props[prop] = null));
|
||||
}
|
||||
|
||||
clearParams(params) {
|
||||
const arr = Array.isArray(params) ? params : [params];
|
||||
arr.forEach((param) => this.set(param, null));
|
||||
},
|
||||
|
||||
doSubmit(data, options = {}, maybeEvent) {
|
||||
const event = options.type === 'submit' ? options : maybeEvent;
|
||||
if (event) {
|
||||
event.preventDefault();
|
||||
@task
|
||||
@waitFor
|
||||
*doSubmit(data, options = {}, maybeEvent) {
|
||||
this.errors = null;
|
||||
const event = options.type === 'submit' ? options : maybeEvent;
|
||||
if (event) {
|
||||
event.preventDefault();
|
||||
}
|
||||
const { backend, id } = this.args.key;
|
||||
const action = this.args.selectedAction || this.firstSupportedAction;
|
||||
const { ...formData } = data || {};
|
||||
if (!this.props.encodedBase64) {
|
||||
if (action === 'encrypt' && !!formData.plaintext) {
|
||||
formData.plaintext = encodeString(formData.plaintext);
|
||||
}
|
||||
const { backend, id } = this.getModelInfo();
|
||||
const action = this.selectedAction;
|
||||
const { encodedBase64, ...formData } = data || {};
|
||||
if (!encodedBase64) {
|
||||
if (action === 'encrypt' && !!formData.plaintext) {
|
||||
formData.plaintext = encodeString(formData.plaintext);
|
||||
}
|
||||
if ((action === 'hmac' || action === 'verify' || action === 'sign') && !!formData.input) {
|
||||
formData.input = encodeString(formData.input);
|
||||
}
|
||||
if ((action === 'hmac' || action === 'verify' || action === 'sign') && !!formData.input) {
|
||||
formData.input = encodeString(formData.input);
|
||||
}
|
||||
const payload = formData ? this.compactData(formData) : null;
|
||||
this.setProperties({
|
||||
errors: null,
|
||||
result: null,
|
||||
});
|
||||
this.store
|
||||
}
|
||||
const payload = formData ? this.compactData(formData) : null;
|
||||
|
||||
try {
|
||||
const resp = yield this.store
|
||||
.adapterFor('transit-key')
|
||||
.keyAction(action, { backend, id, payload }, options)
|
||||
.then(
|
||||
(resp) => this.handleSuccess(resp, options, action),
|
||||
(...errArgs) => this.handleError(...errArgs)
|
||||
);
|
||||
},
|
||||
},
|
||||
});
|
||||
.keyAction(action, { backend, id, payload }, options);
|
||||
|
||||
this.handleSuccess(resp, options, action);
|
||||
} catch (e) {
|
||||
this.errors = errorMessage(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,8 +47,17 @@
|
||||
{{#if (not-eq @tab "actions")}}
|
||||
<Toolbar>
|
||||
<ToolbarActions>
|
||||
{{#if (eq @tab "versions")}}
|
||||
<TransitKeyActions @key={{@key}} @selectedAction="rotate" @capabilities={{@capabilities}} @onRefresh={{@refresh}} />
|
||||
{{#if (and (eq @tab "versions") @key.canRotate)}}
|
||||
<ConfirmAction
|
||||
@buttonText="Rotate encryption key"
|
||||
class="toolbar-button"
|
||||
@buttonColor="secondary"
|
||||
@confirmTitle="Rotate this key?"
|
||||
@confirmMessage="After rotation, all key actions will default to using the newest version of the key."
|
||||
@modalColor="warning"
|
||||
@onConfirmAction={{this.rotateKey}}
|
||||
data-test-transit-key-rotate
|
||||
/>
|
||||
{{/if}}
|
||||
{{#if (eq @mode "show")}}
|
||||
{{#if (or @capabilities.canUpdate @capabilities.canDelete)}}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
SPDX-License-Identifier: BUSL-1.1
|
||||
~}}
|
||||
|
||||
<form onsubmit={{action @doSubmit (hash param=@param context=@context nonce=@nonce bits=@bits)}}>
|
||||
<form {{on "submit" (fn @doSubmit (hash param=@param context=@context nonce=@nonce bits=@bits))}} ...attributes>
|
||||
<div class="box is-sideless is-fullwidth is-marginless">
|
||||
<NamespaceReminder @mode="perform" @noun="datakey creation" />
|
||||
<div class="content has-bottom-margin-l">
|
||||
@@ -78,7 +78,7 @@
|
||||
Copy your generated key
|
||||
</M.Header>
|
||||
<M.Body>
|
||||
{{#if (eq @param "plaintext")}}
|
||||
{{#if @plaintext}}
|
||||
<h2 class="has-text-weight-semibold is-6">Plaintext</h2>
|
||||
<p class="sub-text">Plaintext is base64 encoded</p>
|
||||
<Hds::Copy::Snippet
|
||||
@@ -86,6 +86,8 @@
|
||||
@textToCopy={{@plaintext}}
|
||||
@color="secondary"
|
||||
@container="#transit-datakey-modal"
|
||||
@isFullWidth={{true}}
|
||||
@isTruncated={{true}}
|
||||
@onError={{(fn
|
||||
(set-flash-message "Clipboard copy failed. Please make sure the browser Clipboard API is allowed." "danger")
|
||||
)}}
|
||||
@@ -96,6 +98,8 @@
|
||||
@textToCopy={{@ciphertext}}
|
||||
@color="secondary"
|
||||
@container="#transit-datakey-modal"
|
||||
@isFullWidth={{true}}
|
||||
@isTruncated={{true}}
|
||||
@onError={{(fn
|
||||
(set-flash-message "Clipboard copy failed. Please make sure the browser Clipboard API is allowed." "danger")
|
||||
)}}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
SPDX-License-Identifier: BUSL-1.1
|
||||
~}}
|
||||
|
||||
<form onsubmit={{action @doSubmit (hash ciphertext=@ciphertext context=@context nonce=@nonce)}}>
|
||||
<form {{on "submit" (fn @doSubmit (hash ciphertext=@ciphertext context=@context nonce=@nonce))}} ...attributes>
|
||||
<div class="box is-sideless is-fullwidth is-marginless">
|
||||
<div class="content has-bottom-margin-l">
|
||||
<p>You can decrypt ciphertext using <code>{{@key.name}}</code> as the encryption key.</p>
|
||||
@@ -12,7 +12,7 @@
|
||||
<div id="ciphertext-control" class="control">
|
||||
<JsonEditor
|
||||
@title="Ciphertext"
|
||||
@valueUpdated={{action (mut @ciphertext)}}
|
||||
@valueUpdated={{fn (mut @ciphertext)}}
|
||||
@mode="ruby"
|
||||
@data-test-transit-input="ciphertext"
|
||||
/>
|
||||
@@ -60,11 +60,13 @@
|
||||
</M.Header>
|
||||
<M.Body>
|
||||
<h2 class="has-text-weight-semibold is-6">Plaintext</h2>
|
||||
<p class="sub-text">Plaintext is base64 encoded</p>
|
||||
<p class="sub-text">Plaintext is base64 encoded.</p>
|
||||
<Hds::Copy::Snippet
|
||||
@textToCopy={{@plaintext}}
|
||||
@color="secondary"
|
||||
@container="#transit-decrypt-modal"
|
||||
@isFullWidth={{true}}
|
||||
@isTruncated={{true}}
|
||||
@onError={{(fn
|
||||
(set-flash-message "Clipboard copy failed. Please make sure the browser Clipboard API is allowed." "danger")
|
||||
)}}
|
||||
|
||||
@@ -4,30 +4,34 @@
|
||||
~}}
|
||||
|
||||
<form
|
||||
onsubmit={{action
|
||||
@doSubmit
|
||||
(hash plaintext=@plaintext context=@context nonce=@nonce key_version=@key_version encodedBase64=@encodedBase64)
|
||||
}}
|
||||
{{on "submit" (fn @doSubmit (hash plaintext=@plaintext context=@context nonce=@nonce key_version=@key_version))}}
|
||||
...attributes
|
||||
>
|
||||
<div class="box is-sideless is-fullwidth is-marginless">
|
||||
<NamespaceReminder @mode="perform" @noun="encryption" />
|
||||
<div class="content has-bottom-margin-l">
|
||||
<p>You can encrypt plaintext data using <code>{{@key.name}}</code> as the encryption key.</p>
|
||||
</div>
|
||||
<KeyVersionSelect @key={{@key}} @onVersionChange={{action (mut @key_version)}} @key_version={{@key_version}} />
|
||||
<KeyVersionSelect @key={{@key}} @onVersionChange={{fn (mut @key_version)}} @key_version={{@key_version}} />
|
||||
<div class="field">
|
||||
<div id="plaintext-control" class="control is-relative">
|
||||
<JsonEditor
|
||||
@title="Plaintext"
|
||||
@value={{@plaintext}}
|
||||
@valueUpdated={{action (mut @plaintext)}}
|
||||
@valueUpdated={{fn (mut @plaintext)}}
|
||||
@mode="ruby"
|
||||
@data-test-transit-input="plaintext"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<Input @type="checkbox" id="encodedBase64" @checked={{@encodedBase64}} data-test-transit-input="encodedBase64" />
|
||||
<Input
|
||||
@type="checkbox"
|
||||
id="encodedBase64"
|
||||
@checked={{@encodedBase64}}
|
||||
{{on "change" @toggleEncodeBase64}}
|
||||
data-test-transit-input="encodedBase64"
|
||||
/>
|
||||
<label for="encodedBase64">This data is already encoded in base64</label>
|
||||
</div>
|
||||
{{#if @key.derived}}
|
||||
@@ -78,6 +82,8 @@
|
||||
@textToCopy={{@ciphertext}}
|
||||
@color="secondary"
|
||||
@container="#transit-encrypt-modal"
|
||||
@isFullWidth={{true}}
|
||||
@isTruncated={{true}}
|
||||
@onError={{(fn
|
||||
(set-flash-message "Clipboard copy failed. Please make sure the browser Clipboard API is allowed." "danger")
|
||||
)}}
|
||||
|
||||
@@ -4,11 +4,15 @@
|
||||
~}}
|
||||
|
||||
<form
|
||||
onsubmit={{action
|
||||
@doSubmit
|
||||
(hash param=(compact (array @exportKeyType (if this.exportVersion @exportKeyVersion))))
|
||||
(hash wrapTTL=this.wrapTTL)
|
||||
{{on
|
||||
"submit"
|
||||
(fn
|
||||
@doSubmit
|
||||
(hash param=(compact (array @exportKeyType (if this.exportVersion @exportKeyVersion))))
|
||||
(hash wrapTTL=@wrappedTTL)
|
||||
)
|
||||
}}
|
||||
...attributes
|
||||
>
|
||||
<div class="box is-sideless is-fullwidth is-marginless">
|
||||
<div class="content">
|
||||
@@ -55,7 +59,7 @@
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
<WrapTtl @onChange={{action (mut this.wrapTTL)}} />
|
||||
<WrapTtl @onChange={{fn (mut @wrappedTTL)}} />
|
||||
</div>
|
||||
<div class="field is-grouped box is-fullwidth is-bottomless">
|
||||
<div class="control">
|
||||
@@ -70,12 +74,14 @@
|
||||
</M.Header>
|
||||
<M.Body>
|
||||
<h2 class="title is-6">Wrapped key</h2>
|
||||
{{#if this.wrapTTL}}
|
||||
{{#if @wrappedTTL}}
|
||||
<Hds::Copy::Snippet
|
||||
class="has-bottom-margin-m"
|
||||
@textToCopy={{@wrappedToken}}
|
||||
@color="secondary"
|
||||
@container="#transit-export-modal"
|
||||
@isFullWidth={{true}}
|
||||
@isTruncated={{true}}
|
||||
@onError={{(fn
|
||||
(set-flash-message "Clipboard copy failed. Please make sure the browser Clipboard API is allowed." "danger")
|
||||
)}}
|
||||
|
||||
@@ -3,12 +3,7 @@
|
||||
SPDX-License-Identifier: BUSL-1.1
|
||||
~}}
|
||||
|
||||
<form
|
||||
onsubmit={{action
|
||||
@doSubmit
|
||||
(hash input=@input algorithm=@algorithm key_version=@key_version encodedBase64=@encodedBase64)
|
||||
}}
|
||||
>
|
||||
<form {{on "submit" (fn @doSubmit (hash input=@trackedInput algorithm=@algorithm key_version=@key_version))}} ...attributes>
|
||||
<div class="box is-sideless is-fullwidth is-marginless">
|
||||
<NamespaceReminder @mode="perform" @noun="HMAC creation" />
|
||||
<div class="content has-bottom-margin-l">
|
||||
@@ -18,14 +13,20 @@
|
||||
as the named key.
|
||||
</p>
|
||||
</div>
|
||||
<KeyVersionSelect @key={{@key}} @onVersionChange={{action (mut @key_version)}} @key_version={{@key_version}} />
|
||||
<KeyVersionSelect @key={{@key}} @onVersionChange={{fn (mut @key_version)}} @key_version={{@key_version}} />
|
||||
<div class="field">
|
||||
<div id="input-control" class="control is-relative">
|
||||
<JsonEditor @title="Input" @valueUpdated={{action (mut @input)}} @mode="ruby" @data-test-transit-input="input" />
|
||||
<JsonEditor @title="Input" @valueUpdated={{fn (mut @trackedInput)}} @mode="ruby" @data-test-transit-input="input" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<Input @type="checkbox" id="encodedBase64" @checked={{@encodedBase64}} data-test-transit-input="encodedBase64" />
|
||||
<Input
|
||||
@type="checkbox"
|
||||
id="encodedBase64"
|
||||
@checked={{@encodedBase64}}
|
||||
{{on "change" @toggleEncodeBase64}}
|
||||
data-test-transit-input="encodedBase64"
|
||||
/>
|
||||
<label for="encodedBase64">This data is already encoded in base64</label>
|
||||
</div>
|
||||
<div class="field">
|
||||
@@ -60,6 +61,8 @@
|
||||
@textToCopy={{@hmac}}
|
||||
@color="secondary"
|
||||
@container="#transit-hmac-modal"
|
||||
@isFullWidth={{true}}
|
||||
@isTruncated={{true}}
|
||||
@onError={{(fn
|
||||
(set-flash-message "Clipboard copy failed. Please make sure the browser Clipboard API is allowed." "danger")
|
||||
)}}
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
SPDX-License-Identifier: BUSL-1.1
|
||||
~}}
|
||||
|
||||
<form onsubmit={{action @doSubmit (hash ciphertext=@ciphertext context=@context nonce=@nonce key_version=@key_version)}}>
|
||||
<form
|
||||
{{on "submit" (fn @doSubmit (hash ciphertext=@ciphertext context=@context nonce=@nonce key_version=@key_version))}}
|
||||
...attributes
|
||||
>
|
||||
<div class="box is-sideless is-fullwidth is-marginless">
|
||||
<NamespaceReminder @mode="perform" @noun="rewrap" />
|
||||
<div class="content has-bottom-margin-l">
|
||||
@@ -13,10 +16,10 @@
|
||||
as the encryption key.
|
||||
</p>
|
||||
</div>
|
||||
<KeyVersionSelect @key={{@key}} @onVersionChange={{action (mut @key_version)}} @key_version={{@key_version}} />
|
||||
<KeyVersionSelect @key={{@key}} @onVersionChange={{fn (mut @key_version)}} @key_version={{@key_version}} />
|
||||
<div class="field">
|
||||
<div class="control is-expanded">
|
||||
<JsonEditor @title="Ciphertext" @valueUpdated={{action (mut @ciphertext)}} @mode="ruby" />
|
||||
<JsonEditor @title="Ciphertext" @valueUpdated={{fn (mut @ciphertext)}} @mode="ruby" />
|
||||
</div>
|
||||
</div>
|
||||
{{#if @key.derived}}
|
||||
@@ -72,6 +75,8 @@
|
||||
@textToCopy={{@ciphertext}}
|
||||
@color="secondary"
|
||||
@container="#transit-rewrap-modal"
|
||||
@isFullWidth={{true}}
|
||||
@isTruncated={{true}}
|
||||
@onError={{(fn
|
||||
(set-flash-message "Clipboard copy failed. Please make sure the browser Clipboard API is allowed." "danger")
|
||||
)}}
|
||||
|
||||
@@ -4,18 +4,22 @@
|
||||
~}}
|
||||
|
||||
<form
|
||||
onsubmit={{action
|
||||
@doSubmit
|
||||
(hash
|
||||
input=@input
|
||||
hash_algorithm=@hash_algorithm
|
||||
signature_algorithm=@signature_algorithm
|
||||
key_version=@key_version
|
||||
context=@context
|
||||
prehashed=@prehashed
|
||||
encodedBase64=@encodedBase64
|
||||
{{on
|
||||
"submit"
|
||||
(fn
|
||||
@doSubmit
|
||||
(hash
|
||||
input=@trackedInput
|
||||
hash_algorithm=@hash_algorithm
|
||||
signature_algorithm=@signature_algorithm
|
||||
key_version=@key_version
|
||||
context=@context
|
||||
prehashed=@prehashed
|
||||
encodedBase64=@encodedBase64
|
||||
)
|
||||
)
|
||||
}}
|
||||
...attributes
|
||||
>
|
||||
<div class="box is-sideless is-fullwidth is-marginless">
|
||||
<NamespaceReminder @mode="perform" @noun="signing" />
|
||||
@@ -26,20 +30,26 @@
|
||||
as the encryption key and the specified hash algorithm.
|
||||
</p>
|
||||
</div>
|
||||
<KeyVersionSelect @key={{@key}} @onVersionChange={{action (mut @key_version)}} @key_version={{@key_version}} />
|
||||
<KeyVersionSelect @key={{@key}} @onVersionChange={{fn (mut @key_version)}} @key_version={{@key_version}} />
|
||||
<div class="field">
|
||||
<div class="control is-relative">
|
||||
<JsonEditor
|
||||
@title="Input"
|
||||
@value={{@input}}
|
||||
@valueUpdated={{action (mut @input)}}
|
||||
@value={{@trackedInput}}
|
||||
@valueUpdated={{fn (mut @trackedInput)}}
|
||||
@mode="ruby"
|
||||
@data-test-transit-input="input"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<Input @type="checkbox" id="encodedBase64" @checked={{@encodedBase64}} data-test-transit-input="encodedBase64" />
|
||||
<Input
|
||||
@type="checkbox"
|
||||
id="encodedBase64"
|
||||
@checked={{@encodedBase64}}
|
||||
{{on "change" @toggleEncodeBase64}}
|
||||
data-test-transit-input="encodedBase64"
|
||||
/>
|
||||
<label for="encodedBase64">This data is already encoded in base64</label>
|
||||
</div>
|
||||
{{#if @key.derived}}
|
||||
@@ -114,7 +124,7 @@
|
||||
</div>
|
||||
<div class="field is-grouped box is-fullwidth is-bottomless">
|
||||
<div class="control">
|
||||
<Hds::Button @text="Sign" @icon={{if @loading "loading"}} type="submit" disabled={{@loading}} />
|
||||
<Hds::Button @text="Sign" @icon={{if @submitIsRunning "loading"}} type="submit" disabled={{@submitIsRunning}} />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@@ -129,6 +139,8 @@
|
||||
@textToCopy={{@signature}}
|
||||
@color="secondary"
|
||||
@container="#transit-sign-modal"
|
||||
@isFullWidth={{true}}
|
||||
@isTruncated={{true}}
|
||||
@onError={{(fn
|
||||
(set-flash-message "Clipboard copy failed. Please make sure the browser Clipboard API is allowed." "danger")
|
||||
)}}
|
||||
|
||||
@@ -4,19 +4,23 @@
|
||||
~}}
|
||||
|
||||
<form
|
||||
onsubmit={{action
|
||||
@doSubmit
|
||||
(hash
|
||||
input=@input
|
||||
signature=@signature
|
||||
signature_algorithm=@signature_algorithm
|
||||
hmac=@hmac
|
||||
hash_algorithm=@hash_algorithm
|
||||
context=@context
|
||||
prehashed=@prehashed
|
||||
encodedBase64=@encodedBase64
|
||||
{{on
|
||||
"submit"
|
||||
(fn
|
||||
@doSubmit
|
||||
(hash
|
||||
input=@trackedInput
|
||||
signature=@signature
|
||||
signature_algorithm=@signature_algorithm
|
||||
hmac=@hmac
|
||||
hash_algorithm=@hash_algorithm
|
||||
context=@context
|
||||
prehashed=@prehashed
|
||||
encodedBase64=@encodedBase64
|
||||
)
|
||||
)
|
||||
}}
|
||||
...attributes
|
||||
>
|
||||
<div class="box is-sideless is-fullwidth is-marginless">
|
||||
<div class="content has-bottom-margin-l">
|
||||
@@ -26,15 +30,21 @@
|
||||
<div class="control is-relative">
|
||||
<JsonEditor
|
||||
@title="Input"
|
||||
@value={{@input}}
|
||||
@valueUpdated={{action (mut @input)}}
|
||||
@value={{@trackedInput}}
|
||||
@valueUpdated={{fn (mut @trackedInput)}}
|
||||
@mode="ruby"
|
||||
@data-test-transit-input="input"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<Input @type="checkbox" id="encodedBase64" @checked={{@encodedBase64}} data-test-transit-input="encodedBase64" />
|
||||
<Input
|
||||
@type="checkbox"
|
||||
id="encodedBase64"
|
||||
@checked={{@encodedBase64}}
|
||||
{{on "change" @toggleEncodeBase64}}
|
||||
data-test-transit-input="encodedBase64"
|
||||
/>
|
||||
<label for="encodedBase64">This data is already encoded in base64</label>
|
||||
</div>
|
||||
{{#if (and @key.supportsSigning @key.derived (not @hmac))}}
|
||||
@@ -64,7 +74,7 @@
|
||||
id="verification"
|
||||
onchange={{queue
|
||||
(action (mut @verification) value="target.value")
|
||||
(action @clearParams (array "hmac" "signature"))
|
||||
(fn @clearSpecificProps (array "hmac" "signature"))
|
||||
}}
|
||||
>
|
||||
{{#each (array "Signature" "HMAC") as |type|}}
|
||||
@@ -145,18 +155,13 @@
|
||||
{{#if (or (and @verification (eq @verification "HMAC")) @hmac)}}
|
||||
<div class="field is-flex-column is-flex-grow-1">
|
||||
<div class="control is-flex-column is-flex-grow-1">
|
||||
<JsonEditor @title="HMAC" @value={{@hmac}} @valueUpdated={{action (mut @hmac)}} @mode="ruby" />
|
||||
<JsonEditor @title="HMAC" @value={{@hmac}} @valueUpdated={{fn (mut @hmac)}} @mode="ruby" />
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="field is-flex-column is-flex-grow-1">
|
||||
<div class="control is-flex-column is-flex-grow-1">
|
||||
<JsonEditor
|
||||
@title="Signature"
|
||||
@value={{@signature}}
|
||||
@valueUpdated={{action (mut @signature)}}
|
||||
@mode="ruby"
|
||||
/>
|
||||
<JsonEditor @title="Signature" @value={{@signature}} @valueUpdated={{fn (mut @signature)}} @mode="ruby" />
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
@@ -165,7 +170,7 @@
|
||||
{{else}}
|
||||
<div class="field">
|
||||
<div class="control">
|
||||
<JsonEditor @title="HMAC" @value={{@hmac}} @valueUpdated={{action (mut @hmac)}} @mode="ruby" />
|
||||
<JsonEditor @title="HMAC" @value={{@hmac}} @valueUpdated={{fn (mut @hmac)}} @mode="ruby" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
@@ -186,7 +191,7 @@
|
||||
</div>
|
||||
<div class="field is-grouped box is-fullwidth is-bottomless">
|
||||
<div class="control">
|
||||
<Hds::Button @text="Verify" @icon={{if @loading "loading"}} type="submit" disabled={{@loading}} />
|
||||
<Hds::Button @text="Verify" @icon={{if @submitIsRunning "loading"}} type="submit" disabled={{@submitIsRunning}} />
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
{{!
|
||||
Copyright (c) HashiCorp, Inc.
|
||||
SPDX-License-Identifier: BUSL-1.1
|
||||
~}}
|
||||
|
||||
{{#if (eq this.selectedAction "rotate")}}
|
||||
{{#if this.key.canRotate}}
|
||||
<ConfirmAction
|
||||
@buttonText="Rotate encryption key"
|
||||
class="toolbar-button"
|
||||
@buttonColor="secondary"
|
||||
@confirmTitle="Rotate this key?"
|
||||
@confirmMessage="After rotation, all key actions will default to using the newest version of the key."
|
||||
@modalColor="warning"
|
||||
@onConfirmAction={{action "doSubmit"}}
|
||||
data-test-transit-key-rotate
|
||||
/>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
<MessageError @errors={{this.errors}} />
|
||||
{{#if this.selectedAction}}
|
||||
<div data-test-transit-action={{this.selectedAction}}>
|
||||
{{! template-lint-disable no-passed-in-event-handlers }}
|
||||
{{component
|
||||
(concat "transit-key-action/" this.selectedAction)
|
||||
key=this.key
|
||||
keys=this.keys
|
||||
keyIsRSA=this.keyIsRSA
|
||||
verification=this.verification
|
||||
hmac=this.hmac
|
||||
param=this.param
|
||||
key_version=this.key_version
|
||||
isModalActive=this.isModalActive
|
||||
ciphertext=this.ciphertext
|
||||
plaintext=this.plaintext
|
||||
context=this.context
|
||||
nonce=this.nonce
|
||||
input=this.input
|
||||
bits=this.bits
|
||||
algorithm=this.algorithm
|
||||
signature=this.signature
|
||||
signature_algorithm=this.signature_algorithm
|
||||
hash_algorithm=this.hash_algorithm
|
||||
prehashed=this.prehashed
|
||||
wrappedToken=this.wrappedToken
|
||||
exportKeyType=this.exportKeyType
|
||||
exportKeyVersion=this.exportKeyVersion
|
||||
encodedBase64=this.encodedBase64
|
||||
valid=this.valid
|
||||
doSubmit=(action "doSubmit")
|
||||
clearParams=(action "clearParams")
|
||||
}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
@@ -57,12 +57,6 @@
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<TransitKeyActions
|
||||
@selectedAction={{this.selectedAction}}
|
||||
@backend={{this.backend}}
|
||||
@key={{this.model}}
|
||||
@capabilities={{this.capabilities}}
|
||||
@onRefresh={{action "refresh"}}
|
||||
/>
|
||||
<TransitKeyActions @selectedAction={{this.selectedAction}} @key={{this.model}} />
|
||||
</div>
|
||||
</div>
|
||||
@@ -23,7 +23,7 @@ const SELECTORS = {
|
||||
form: (item) => `[data-test-transit-key="${item}"]`,
|
||||
versionRow: (version) => `[data-test-transit-version="${version}"]`,
|
||||
rotate: {
|
||||
trigger: '[data-test-confirm-action-trigger]',
|
||||
trigger: '[data-test-transit-key-rotate]',
|
||||
confirm: '[data-test-confirm-button]',
|
||||
},
|
||||
};
|
||||
@@ -344,6 +344,7 @@ module('Acceptance | transit (flaky)', function (hooks) {
|
||||
|
||||
await click(SELECTORS.versionsTab);
|
||||
assert.dom(SELECTORS.versionRow(1)).hasTextContaining('Version 1', `${name}: only one key version`);
|
||||
|
||||
await waitUntil(() => find(SELECTORS.rotate.trigger));
|
||||
await click(SELECTORS.rotate.trigger);
|
||||
await click(SELECTORS.rotate.confirm);
|
||||
|
||||
@@ -60,7 +60,7 @@ module('Integration | Component | transit key actions', function (hooks) {
|
||||
render(hbs`
|
||||
<TransitKeyActions />`);
|
||||
const err = await promise;
|
||||
assert.ok(err.message.includes('`key` is required for'), 'asserts without key');
|
||||
assert.ok(err.message.includes('@key is required for'), 'asserts without key');
|
||||
});
|
||||
|
||||
test('it renders', async function (assert) {
|
||||
@@ -102,19 +102,6 @@ module('Integration | Component | transit key actions', function (hooks) {
|
||||
.exists({ count: 1 }, 'renders signature_algorithm field on verify with rsa key');
|
||||
});
|
||||
|
||||
test('it renders: rotate', async function (assert) {
|
||||
this.set('key', { backend: 'transit', id: 'akey', supportedActions: ['rotate'] });
|
||||
await render(hbs`
|
||||
<TransitKeyActions @selectedAction="rotate" @key={{this.key}} />`);
|
||||
|
||||
assert.dom('*').hasText('', 'renders an empty div');
|
||||
|
||||
this.set('key.canRotate', true);
|
||||
assert
|
||||
.dom('button')
|
||||
.hasText('Rotate encryption key', 'renders confirm-button when key.canRotate is true');
|
||||
});
|
||||
|
||||
async function doEncrypt(assert, actions = [], keyattrs = {}) {
|
||||
const keyDefaults = { backend: 'transit', id: 'akey', supportedActions: ['encrypt'].concat(actions) };
|
||||
|
||||
@@ -312,7 +299,7 @@ module('Integration | Component | transit key actions', function (hooks) {
|
||||
validKeyVersions: [1],
|
||||
});
|
||||
await render(hbs`
|
||||
<TransitKeyActions @key={{this.key}} />`);
|
||||
<TransitKeyActions @key={{this.key}} @selectedAction="hmac" />`);
|
||||
await fillIn('#algorithm', 'sha2-384');
|
||||
await blur('#algorithm');
|
||||
await fillIn('[data-test-component="code-mirror-modifier"] textarea', 'plaintext');
|
||||
|
||||
Reference in New Issue
Block a user