mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-11-03 20:17:59 +00:00
UI: pki configuration edit form (#20245)
* setup routing, move queries in ConfigurationIndex to parent resource route * finish building out form, add model attrs build ttls * add types * update model attribute values, fix default ttl states * remove defaults and use openApi, group with booleans * add model to application route" * add save functionality * add error banner * add transition after save * use defaults from open api * fix empty state language * pass engine data * change model attrs to ttl objects * update types * add invalid form alert to error block * move data manipulation to serialize * fix serializer, add comments * add test for serializer * edit configuration details view * update details test * change to updateRecord so POST request is made * config/urls use POST instead of PUT * add edit tests, update details * add model hooks back to routes * rearrange to remove dif * remove createRecord for urls * update comment * wip sample ttl transform * Revert "wip sample ttl transform" This reverts commit 59fc179b5cd2994c4258e553e56667e29b3d6b72. * revert changes, move model updates back to component * simplify model fetches * address comments; * update pki/urls test * update adapter test
This commit is contained in:
@@ -18,4 +18,9 @@ export default class PkiCrlAdapter extends ApplicationAdapter {
|
|||||||
return resp.data;
|
return resp.data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateRecord(store, type, snapshot) {
|
||||||
|
const data = snapshot.serialize();
|
||||||
|
return this.ajax(this._url(snapshot.record.id), 'POST', { data });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,13 +13,12 @@ export default class PkiUrlsAdapter extends ApplicationAdapter {
|
|||||||
return `${this.buildURL()}/${encodePath(backend)}/config/urls`;
|
return `${this.buildURL()}/${encodePath(backend)}/config/urls`;
|
||||||
}
|
}
|
||||||
|
|
||||||
urlForCreateRecord(modelName, snapshot) {
|
updateRecord(store, type, snapshot) {
|
||||||
return this._url(snapshot.record.id);
|
const data = snapshot.serialize();
|
||||||
|
return this.ajax(this._url(snapshot.record.id), 'POST', { data });
|
||||||
}
|
}
|
||||||
|
|
||||||
urlForFindRecord(id) {
|
urlForFindRecord(id) {
|
||||||
return this._url(id);
|
return this._url(id);
|
||||||
}
|
}
|
||||||
urlForUpdateRecord(store, type, snapshot) {
|
|
||||||
return this._url(snapshot.record.id);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,15 +4,67 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import Model, { attr } from '@ember-data/model';
|
import Model, { attr } from '@ember-data/model';
|
||||||
|
import { withFormFields } from 'vault/decorators/model-form-fields';
|
||||||
|
import lazyCapabilities, { apiPath } from 'vault/macros/lazy-capabilities';
|
||||||
|
|
||||||
|
@withFormFields(['expiry', 'autoRebuildGracePeriod', 'deltaRebuildInterval', 'ocspExpiry'])
|
||||||
export default class PkiCrlModel extends Model {
|
export default class PkiCrlModel extends Model {
|
||||||
// This model uses the backend value as the model ID
|
// This model uses the backend value as the model ID
|
||||||
get useOpenAPI() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@attr('string') expiry;
|
|
||||||
@attr('boolean') autoRebuild;
|
@attr('boolean') autoRebuild;
|
||||||
@attr('string') ocspExpiry;
|
@attr('string', {
|
||||||
|
label: 'Auto-rebuild on',
|
||||||
|
labelDisabled: 'Auto-rebuild off',
|
||||||
|
mapToBoolean: 'autoRebuild',
|
||||||
|
isOppositeValue: false,
|
||||||
|
helperTextEnabled: 'Vault will rebuild the CRL in the below grace period before expiration',
|
||||||
|
helperTextDisabled: 'Vault will not automatically rebuild the CRL',
|
||||||
|
})
|
||||||
|
autoRebuildGracePeriod;
|
||||||
|
|
||||||
|
@attr('boolean') enableDelta;
|
||||||
|
@attr('string', {
|
||||||
|
label: 'Delta CRL building on',
|
||||||
|
labelDisabled: 'Delta CRL building off',
|
||||||
|
mapToBoolean: 'enableDelta',
|
||||||
|
isOppositeValue: false,
|
||||||
|
helperTextEnabled: 'Vault will rebuild the delta CRL at the interval below:',
|
||||||
|
helperTextDisabled: 'Vault will not rebuild the delta CRL at an interval',
|
||||||
|
})
|
||||||
|
deltaRebuildInterval;
|
||||||
|
|
||||||
|
@attr('boolean') disable;
|
||||||
|
@attr('string', {
|
||||||
|
label: 'Expiry',
|
||||||
|
labelDisabled: 'No expiry',
|
||||||
|
mapToBoolean: 'disable',
|
||||||
|
isOppositeValue: true,
|
||||||
|
helperTextDisabled: 'The CRL will not be built.',
|
||||||
|
helperTextEnabled: 'The CRL will expire after:',
|
||||||
|
})
|
||||||
|
expiry;
|
||||||
|
|
||||||
@attr('boolean') ocspDisable;
|
@attr('boolean') ocspDisable;
|
||||||
|
@attr('string', {
|
||||||
|
label: 'OCSP responder APIs enabled',
|
||||||
|
labelDisabled: 'OCSP responder APIs disabled',
|
||||||
|
mapToBoolean: 'ocspDisable',
|
||||||
|
isOppositeValue: true,
|
||||||
|
helperTextEnabled: "Requests about a certificate's status will be valid for:",
|
||||||
|
helperTextDisabled: 'Requests cannot be made to check if an individual certificate is valid.',
|
||||||
|
})
|
||||||
|
ocspExpiry;
|
||||||
|
|
||||||
|
// TODO follow-on ticket to add enterprise only attributes:
|
||||||
|
/*
|
||||||
|
@attr('boolean') crossClusterRevocation;
|
||||||
|
@attr('boolean') unifiedCrl;
|
||||||
|
@attr('boolean') unifiedCrlOnExistingPaths;
|
||||||
|
*/
|
||||||
|
|
||||||
|
@lazyCapabilities(apiPath`${'id'}/config/crl`, 'id') crlPath;
|
||||||
|
|
||||||
|
get canSet() {
|
||||||
|
return this.crlPath.get('canCreate') !== false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
* @param onChange {Function} - This function will be passed a TTL object, which includes enabled{bool}, seconds{number}, timeString{string}, goSafeTimeString{string}.
|
* @param onChange {Function} - This function will be passed a TTL object, which includes enabled{bool}, seconds{number}, timeString{string}, goSafeTimeString{string}.
|
||||||
* @param initialEnabled=false {Boolean} - Set this value if you want the toggle on when component is mounted
|
* @param initialEnabled=false {Boolean} - Set this value if you want the toggle on when component is mounted
|
||||||
* @param label="Time to live (TTL)" {String} - Label is the main label that lives next to the toggle. Yielded values will replace the label
|
* @param label="Time to live (TTL)" {String} - Label is the main label that lives next to the toggle. Yielded values will replace the label
|
||||||
|
* @param labelDisabled=Label to display when TTL is toggled off
|
||||||
* @param helperTextEnabled="" {String} - This helper text is shown under the label when the toggle is switched on
|
* @param helperTextEnabled="" {String} - This helper text is shown under the label when the toggle is switched on
|
||||||
* @param helperTextDisabled="" {String} - This helper text is shown under the label when the toggle is switched off
|
* @param helperTextDisabled="" {String} - This helper text is shown under the label when the toggle is switched off
|
||||||
* @param initialValue=null {string} - InitialValue is the duration value which will be shown when the component is loaded. If it can't be parsed, will default to 0.
|
* @param initialValue=null {string} - InitialValue is the duration value which will be shown when the component is loaded. If it can't be parsed, will default to 0.
|
||||||
@@ -52,6 +53,9 @@ export default class TtlPickerComponent extends Component {
|
|||||||
elementId = 'ttl-' + guidFor(this);
|
elementId = 'ttl-' + guidFor(this);
|
||||||
|
|
||||||
get label() {
|
get label() {
|
||||||
|
if (this.args.label && this.args.labelDisabled) {
|
||||||
|
return this.enableTTL ? this.args.label : this.args.labelDisabled;
|
||||||
|
}
|
||||||
return this.args.label || 'Time to live (TTL)';
|
return this.args.label || 'Time to live (TTL)';
|
||||||
}
|
}
|
||||||
get helperText() {
|
get helperText() {
|
||||||
|
|||||||
@@ -38,14 +38,37 @@
|
|||||||
<h2 class="title is-4 has-bottom-margin-xs has-top-margin-xl has-border-bottom-light has-bottom-padding-s">
|
<h2 class="title is-4 has-bottom-margin-xs has-top-margin-xl has-border-bottom-light has-bottom-padding-s">
|
||||||
Certificate Revocation List (CRL)
|
Certificate Revocation List (CRL)
|
||||||
</h2>
|
</h2>
|
||||||
<InfoTableRow @label="Expiry" @value={{@crl.expiry}} />
|
<InfoTableRow @label="CRL building" @value={{if @crl.disable "Disabled" "Enabled"}} />
|
||||||
<InfoTableRow @label="Auto-rebuild" @value={{if @crl.autoRebuild "On" "Off"}} />
|
{{#unless @crl.disable}}
|
||||||
|
<InfoTableRow @label="Expiry" @value={{@crl.expiry}} />
|
||||||
|
<InfoTableRow @label="Auto-rebuild">
|
||||||
|
<Icon
|
||||||
|
class={{if @crl.autoRebuild "icon-true" "icon-false"}}
|
||||||
|
@name={{if @crl.autoRebuild "check-circle" "x-square"}}
|
||||||
|
/>
|
||||||
|
{{if @crl.autoRebuild "On" "Off"}}
|
||||||
|
</InfoTableRow>
|
||||||
|
{{#if @crl.autoRebuild}}
|
||||||
|
<InfoTableRow @label="Auto-rebuild grace period" @value={{@crl.autoRebuildGracePeriod}} />
|
||||||
|
{{/if}}
|
||||||
|
<InfoTableRow @label="Delta CRL building">
|
||||||
|
<Icon
|
||||||
|
class={{if @crl.enableDelta "icon-true" "icon-false"}}
|
||||||
|
@name={{if @crl.enableDelta "check-circle" "x-square"}}
|
||||||
|
/>
|
||||||
|
{{if @crl.enableDelta "On" "Off"}}
|
||||||
|
</InfoTableRow>
|
||||||
|
{{#if @crl.enableDelta}}
|
||||||
|
<InfoTableRow @label="Delta rebuild interval" @value={{@crl.deltaRebuildInterval}} />
|
||||||
|
{{/if}}
|
||||||
|
{{/unless}}
|
||||||
<h2 class="title is-4 has-bottom-margin-xs has-top-margin-xl has-border-bottom-light has-bottom-padding-s">
|
<h2 class="title is-4 has-bottom-margin-xs has-top-margin-xl has-border-bottom-light has-bottom-padding-s">
|
||||||
Online Certificate Status Protocol (OCSP)
|
Online Certificate Status Protocol (OCSP)
|
||||||
</h2>
|
</h2>
|
||||||
<InfoTableRow @label="Responder APIs" @value={{if @crl.ocspDisable "Disabled" "Enabled"}} />
|
<InfoTableRow @label="Responder APIs" @value={{if @crl.ocspDisable "Disabled" "Enabled"}} />
|
||||||
<InfoTableRow @label="Interval" @value={{@crl.ocspExpiry}} />
|
{{#unless @crl.ocspDisable}}
|
||||||
|
<InfoTableRow @label="Interval" @value={{@crl.ocspExpiry}} />
|
||||||
|
{{/unless}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{else}}
|
{{else}}
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
|
|||||||
99
ui/lib/pki/addon/components/page/pki-configuration-edit.hbs
Normal file
99
ui/lib/pki/addon/components/page/pki-configuration-edit.hbs
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
<div class="box is-sideless is-fullwidth is-marginless">
|
||||||
|
{{#if this.errorBanner}}
|
||||||
|
<AlertBanner @type="danger" @message={{this.errorBanner}} data-test-error-banner />
|
||||||
|
{{/if}}
|
||||||
|
<form {{on "submit" (perform this.save)}}>
|
||||||
|
<fieldset class="box is-shadowless is-marginless is-borderless is-fullwidth" data-test-urls-edit-section>
|
||||||
|
<h2 class="title is-size-5 has-border-bottom-light page-header">
|
||||||
|
Global URLs
|
||||||
|
</h2>
|
||||||
|
{{#if @urls.canSet}}
|
||||||
|
{{#each @urls.allFields as |attr|}}
|
||||||
|
<FormField @attr={{attr}} @model={{@urls}} @showHelpText={{false}} />
|
||||||
|
{{/each}}
|
||||||
|
{{else}}
|
||||||
|
<EmptyState
|
||||||
|
class="is-box-shadowless"
|
||||||
|
@title="You do not have permission to set URLs"
|
||||||
|
@message="Ask your administrator if you think you should have access to:"
|
||||||
|
>
|
||||||
|
<code>POST /{{@backend}}/config/urls</code>
|
||||||
|
</EmptyState>
|
||||||
|
{{/if}}
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset class="box is-shadowless is-marginless is-borderless is-fullwidth" data-test-crl-edit-section>
|
||||||
|
<h2 class="title is-size-5 has-border-bottom-light page-header">
|
||||||
|
Certificate Revocation List (CRL)
|
||||||
|
</h2>
|
||||||
|
{{#if @crl.canSet}}
|
||||||
|
{{#each @crl.formFields as |attr|}}
|
||||||
|
{{#if (eq attr.name "ocspExpiry")}}
|
||||||
|
<h2 class="title is-size-5 has-border-bottom-light page-header">
|
||||||
|
Online Certificate Status Protocol (OCSP)
|
||||||
|
</h2>
|
||||||
|
{{/if}}
|
||||||
|
{{#if (or (includes attr.name this.alwaysRender) (not @crl.disable))}}
|
||||||
|
{{#let (get @crl attr.options.mapToBoolean) as |booleanValue|}}
|
||||||
|
<div class="field">
|
||||||
|
<TtlPicker
|
||||||
|
data-test-input={{attr.name}}
|
||||||
|
@onChange={{fn this.handleTtl attr}}
|
||||||
|
@label={{attr.options.label}}
|
||||||
|
@labelDisabled={{attr.options.labelDisabled}}
|
||||||
|
@helperTextDisabled={{attr.options.helperTextDisabled}}
|
||||||
|
@helperTextEnabled={{attr.options.helperTextEnabled}}
|
||||||
|
@initialEnabled={{if attr.options.isOppositeValue (not booleanValue) booleanValue}}
|
||||||
|
@initialValue={{get @crl attr.name}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{{/let}}
|
||||||
|
{{/if}}
|
||||||
|
{{/each}}
|
||||||
|
{{else}}
|
||||||
|
<EmptyState
|
||||||
|
class="is-box-shadowless"
|
||||||
|
@title="You do not have permission to set revocation configuration"
|
||||||
|
@message="Ask your administrator if you think you should have access to:"
|
||||||
|
>
|
||||||
|
<code>POST /{{@backend}}/config/crl</code>
|
||||||
|
</EmptyState>
|
||||||
|
{{/if}}
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<div class="field is-grouped box is-fullwidth is-bottomless">
|
||||||
|
<div class="control">
|
||||||
|
{{#if (or @urls.canSet @crl.canSet)}}
|
||||||
|
<button
|
||||||
|
type="submit"
|
||||||
|
class="button is-primary {{if this.save.isRunning 'is-loading'}}"
|
||||||
|
disabled={{this.save.isRunning}}
|
||||||
|
data-test-configuration-edit-save
|
||||||
|
>
|
||||||
|
Save
|
||||||
|
</button>
|
||||||
|
{{/if}}
|
||||||
|
<button
|
||||||
|
{{on "click" this.cancel}}
|
||||||
|
type="button"
|
||||||
|
class="button has-left-margin-s"
|
||||||
|
disabled={{this.save.isRunning}}
|
||||||
|
data-test-configuration-edit-cancel
|
||||||
|
>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{{#if this.invalidFormAlert}}
|
||||||
|
<div class="control">
|
||||||
|
<AlertInline
|
||||||
|
@type="danger"
|
||||||
|
@paddingTop={{true}}
|
||||||
|
@message={{this.invalidFormAlert}}
|
||||||
|
@mimicRefresh={{true}}
|
||||||
|
data-test-configuration-edit-validation-alert
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
77
ui/lib/pki/addon/components/page/pki-configuration-edit.ts
Normal file
77
ui/lib/pki/addon/components/page/pki-configuration-edit.ts
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) HashiCorp, Inc.
|
||||||
|
* SPDX-License-Identifier: MPL-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Component from '@glimmer/component';
|
||||||
|
import { tracked } from '@glimmer/tracking';
|
||||||
|
import { inject as service } from '@ember/service';
|
||||||
|
import { action } from '@ember/object';
|
||||||
|
import { task } from 'ember-concurrency';
|
||||||
|
import { waitFor } from '@ember/test-waiters';
|
||||||
|
import RouterService from '@ember/routing/router-service';
|
||||||
|
import FlashMessageService from 'vault/services/flash-messages';
|
||||||
|
import { FormField, TtlEvent } from 'vault/app-types';
|
||||||
|
import PkiCrlModel from 'vault/models/pki/crl';
|
||||||
|
import PkiUrlsModel from 'vault/models/pki/urls';
|
||||||
|
import errorMessage from 'vault/utils/error-message';
|
||||||
|
|
||||||
|
interface Args {
|
||||||
|
crl: PkiCrlModel;
|
||||||
|
urls: PkiUrlsModel;
|
||||||
|
}
|
||||||
|
interface PkiCrlTtls {
|
||||||
|
autoRebuildGracePeriod: string;
|
||||||
|
expiry: string;
|
||||||
|
deltaRebuildInterval: string;
|
||||||
|
ocspExpiry: string;
|
||||||
|
}
|
||||||
|
interface PkiCrlBooleans {
|
||||||
|
autoRebuild: boolean;
|
||||||
|
enableDelta: boolean;
|
||||||
|
disable: boolean;
|
||||||
|
ocspDisable: boolean;
|
||||||
|
}
|
||||||
|
export default class PkiConfigurationEditComponent extends Component<Args> {
|
||||||
|
@service declare readonly router: RouterService;
|
||||||
|
@service declare readonly flashMessages: FlashMessageService;
|
||||||
|
|
||||||
|
@tracked invalidFormAlert = '';
|
||||||
|
@tracked errorBanner = '';
|
||||||
|
|
||||||
|
get alwaysRender() {
|
||||||
|
return ['expiry', 'ocspExpiry'];
|
||||||
|
}
|
||||||
|
|
||||||
|
@task
|
||||||
|
@waitFor
|
||||||
|
*save(event: Event) {
|
||||||
|
event.preventDefault();
|
||||||
|
try {
|
||||||
|
yield this.args.urls.save();
|
||||||
|
yield this.args.crl.save();
|
||||||
|
this.flashMessages.success('Successfully updated configuration');
|
||||||
|
this.router.transitionTo('vault.cluster.secrets.backend.pki.configuration.index');
|
||||||
|
} catch (error) {
|
||||||
|
this.invalidFormAlert = 'There was an error submitting this form.';
|
||||||
|
this.errorBanner = errorMessage(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
cancel() {
|
||||||
|
this.router.transitionTo('vault.cluster.secrets.backend.pki.configuration.index');
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
handleTtl(attr: FormField, e: TtlEvent) {
|
||||||
|
const { enabled, goSafeTimeString } = e;
|
||||||
|
const ttlAttr = attr.name;
|
||||||
|
this.args.crl[ttlAttr as keyof PkiCrlTtls] = goSafeTimeString;
|
||||||
|
// expiry and ocspExpiry both correspond to 'disable' booleans
|
||||||
|
// so when ttl is enabled, the booleans are set to false
|
||||||
|
this.args.crl[attr.options.mapToBoolean as keyof PkiCrlBooleans] = attr.options.isOppositeValue
|
||||||
|
? !enabled
|
||||||
|
: enabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import Route from '@ember/routing/route';
|
import Route from '@ember/routing/route';
|
||||||
|
import { inject as service } from '@ember/service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the overview, roles, issuers, certificates, and key routes all need to be aware of the whether there is a config for the engine
|
* the overview, roles, issuers, certificates, and key routes all need to be aware of the whether there is a config for the engine
|
||||||
@@ -21,6 +22,7 @@ export function withConfig() {
|
|||||||
return SuperClass;
|
return SuperClass;
|
||||||
}
|
}
|
||||||
return class CheckConfig extends SuperClass {
|
return class CheckConfig extends SuperClass {
|
||||||
|
@service secretMountPath;
|
||||||
shouldPromptConfig = false;
|
shouldPromptConfig = false;
|
||||||
|
|
||||||
async beforeModel() {
|
async beforeModel() {
|
||||||
|
|||||||
@@ -4,5 +4,18 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import Route from '@ember/routing/route';
|
import Route from '@ember/routing/route';
|
||||||
|
import { inject as service } from '@ember/service';
|
||||||
|
import { hash } from 'rsvp';
|
||||||
|
|
||||||
export default class PkiConfigurationRoute extends Route {}
|
export default class PkiConfigurationRoute extends Route {
|
||||||
|
@service store;
|
||||||
|
|
||||||
|
model() {
|
||||||
|
const engine = this.modelFor('application');
|
||||||
|
return hash({
|
||||||
|
engine,
|
||||||
|
urls: this.store.findRecord('pki/urls', engine.id).catch((e) => e.httpStatus),
|
||||||
|
crl: this.store.findRecord('pki/crl', engine.id).catch((e) => e.httpStatus),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export default class PkiConfigurationCreateRoute extends Route {
|
|||||||
model() {
|
model() {
|
||||||
return hash({
|
return hash({
|
||||||
config: this.store.createRecord('pki/action'),
|
config: this.store.createRecord('pki/action'),
|
||||||
urls: this.getOrCreateUrls(this.secretMountPath.currentPath),
|
urls: this.modelFor('configuration').urls,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,12 +28,4 @@ export default class PkiConfigurationCreateRoute extends Route {
|
|||||||
{ label: 'configure' },
|
{ label: 'configure' },
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
async getOrCreateUrls(backend) {
|
|
||||||
try {
|
|
||||||
return this.store.findRecord('pki/urls', backend);
|
|
||||||
} catch (e) {
|
|
||||||
return this.store.createRecord('pki/urls', { id: backend });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,5 +4,29 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import Route from '@ember/routing/route';
|
import Route from '@ember/routing/route';
|
||||||
|
import { inject as service } from '@ember/service';
|
||||||
|
import { withConfirmLeave } from 'core/decorators/confirm-leave';
|
||||||
|
|
||||||
export default class PkiConfigurationEditRoute extends Route {}
|
@withConfirmLeave('model.config', ['model.urls', 'model.crl'])
|
||||||
|
export default class PkiConfigurationEditRoute extends Route {
|
||||||
|
@service secretMountPath;
|
||||||
|
|
||||||
|
model() {
|
||||||
|
const { urls, crl, engine } = this.modelFor('configuration');
|
||||||
|
return {
|
||||||
|
engineId: engine.id,
|
||||||
|
urls,
|
||||||
|
crl,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
setupController(controller, resolvedModel) {
|
||||||
|
super.setupController(controller, resolvedModel);
|
||||||
|
controller.breadcrumbs = [
|
||||||
|
{ label: 'secrets', route: 'secrets', linkExternal: true },
|
||||||
|
{ label: this.secretMountPath.currentPath, route: 'overview' },
|
||||||
|
{ label: 'configuration', route: 'configuration.index' },
|
||||||
|
{ label: 'edit' },
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,46 +11,23 @@ import { hash } from 'rsvp';
|
|||||||
@withConfig()
|
@withConfig()
|
||||||
export default class ConfigurationIndexRoute extends Route {
|
export default class ConfigurationIndexRoute extends Route {
|
||||||
@service store;
|
@service store;
|
||||||
@service secretMountPath;
|
|
||||||
|
|
||||||
async fetchUrls(backend) {
|
|
||||||
try {
|
|
||||||
return await this.store.findRecord('pki/urls', backend);
|
|
||||||
} catch (e) {
|
|
||||||
return e.httpStatus;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fetchCrl(backend) {
|
|
||||||
try {
|
|
||||||
return await this.store.findRecord('pki/crl', backend);
|
|
||||||
} catch (e) {
|
|
||||||
return e.httpStatus;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fetchMountConfig(path) {
|
|
||||||
const mountConfig = await this.store.query('secret-engine', { path });
|
|
||||||
|
|
||||||
|
async fetchMountConfig(backend) {
|
||||||
|
const mountConfig = await this.store.query('secret-engine', { path: backend });
|
||||||
if (mountConfig) {
|
if (mountConfig) {
|
||||||
return mountConfig.get('firstObject');
|
return mountConfig.get('firstObject');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async model() {
|
model() {
|
||||||
const backend = this.secretMountPath.currentPath;
|
const { urls, crl, engine } = this.modelFor('configuration');
|
||||||
|
|
||||||
return hash({
|
return hash({
|
||||||
hasConfig: this.shouldPromptConfig,
|
hasConfig: this.shouldPromptConfig,
|
||||||
engine: this.modelFor('application'),
|
engine,
|
||||||
urls: this.fetchUrls(backend),
|
urls,
|
||||||
crl: this.fetchCrl(backend),
|
crl,
|
||||||
mountConfig: this.fetchMountConfig(backend),
|
mountConfig: this.fetchMountConfig(engine.id),
|
||||||
issuerModel: this.store.createRecord('pki/issuer'),
|
issuerModel: this.store.createRecord('pki/issuer'),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
setupController(controller, resolvedModel) {
|
|
||||||
super.setupController(controller, resolvedModel);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1,13 @@
|
|||||||
configuration.edit
|
<PageHeader as |p|>
|
||||||
|
<p.top>
|
||||||
|
<Page::Breadcrumbs @breadcrumbs={{this.breadcrumbs}} />
|
||||||
|
</p.top>
|
||||||
|
<p.levelLeft>
|
||||||
|
<h1 class="title is-3">
|
||||||
|
<Icon @name="file-text" @size="24" class="has-text-grey-light" />
|
||||||
|
Edit PKI configuration
|
||||||
|
</h1>
|
||||||
|
</p.levelLeft>
|
||||||
|
</PageHeader>
|
||||||
|
|
||||||
|
<Page::PkiConfigurationEdit @urls={{this.model.urls}} @crl={{this.model.crl}} @backend={{this.model.engineId}} />
|
||||||
@@ -299,9 +299,10 @@ module('Acceptance | pki engine route cleanup test', function (hooks) {
|
|||||||
await click(SELECTORS.configuration.generateRootSave);
|
await click(SELECTORS.configuration.generateRootSave);
|
||||||
// Go to list view so we fetch all the issuers
|
// Go to list view so we fetch all the issuers
|
||||||
await visit(`/vault/secrets/${this.mountPath}/pki/issuers`);
|
await visit(`/vault/secrets/${this.mountPath}/pki/issuers`);
|
||||||
|
|
||||||
issuers = this.store.peekAll('pki/issuer');
|
issuers = this.store.peekAll('pki/issuer');
|
||||||
const issuerId = issuers.objectAt(0).id;
|
const issuerId = issuers.objectAt(0).id;
|
||||||
assert.strictEqual(issuers.length, 1, 'Issuer exists on model');
|
assert.strictEqual(issuers.length, 1, 'Issuer exists on model in list');
|
||||||
await visit(`/vault/secrets/${this.mountPath}/pki/issuers/${issuerId}/details`);
|
await visit(`/vault/secrets/${this.mountPath}/pki/issuers/${issuerId}/details`);
|
||||||
await click(SELECTORS.issuerDetails.configure);
|
await click(SELECTORS.issuerDetails.configure);
|
||||||
issuer = this.store.peekRecord('pki/issuer', issuerId);
|
issuer = this.store.peekRecord('pki/issuer', issuerId);
|
||||||
@@ -310,7 +311,7 @@ module('Acceptance | pki engine route cleanup test', function (hooks) {
|
|||||||
assert.true(issuer.hasDirtyAttributes, 'Model is dirty');
|
assert.true(issuer.hasDirtyAttributes, 'Model is dirty');
|
||||||
await click(SELECTORS.overviewBreadcrumb);
|
await click(SELECTORS.overviewBreadcrumb);
|
||||||
issuers = this.store.peekAll('pki/issuer');
|
issuers = this.store.peekAll('pki/issuer');
|
||||||
assert.strictEqual(issuers.length, 1, 'Issuer exists on model');
|
assert.strictEqual(issuers.length, 1, 'Issuer exists on model in overview');
|
||||||
issuer = this.store.peekRecord('pki/issuer', issuerId);
|
issuer = this.store.peekRecord('pki/issuer', issuerId);
|
||||||
assert.false(issuer.hasDirtyAttributes, 'Dirty attrs were rolled back');
|
assert.false(issuer.hasDirtyAttributes, 'Dirty attrs were rolled back');
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
/**
|
|
||||||
* Copyright (c) HashiCorp, Inc.
|
|
||||||
* SPDX-License-Identifier: MPL-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
export const SELECTORS = {
|
|
||||||
// global urls
|
|
||||||
issuingCertificatesLabel: '[data-test-row-label="Issuing certificates"]',
|
|
||||||
issuingCertificatesRowVal: '[data-test-row-value="Issuing certificates"]',
|
|
||||||
crlDistributionPointsLabel: '[data-test-row-label="CRL distribution points"]',
|
|
||||||
crlDistributionPointsRowVal: '[data-test-row-value="CRL distribution points"]',
|
|
||||||
// crl
|
|
||||||
expiryLabel: '[data-test-row-label="Expiry"]',
|
|
||||||
expiryRowVal: '[data-test-row-value="Expiry"]',
|
|
||||||
rebuildLabel: '[data-test-row-label="Auto-rebuild"]',
|
|
||||||
rebuildRowVal: '[data-test-row-value="Auto-rebuild"]',
|
|
||||||
responderApiLabel: '[data-test-row-label="Responder APIs"]',
|
|
||||||
responderApiRowVal: '[data-test-row-value="Responder APIs"]',
|
|
||||||
intervalLabel: '[data-test-row-label="Interval"]',
|
|
||||||
intervalRowVal: '[data-test-row-value="Interval"]',
|
|
||||||
// mount configuration
|
|
||||||
engineTypeLabel: '[data-test-row-label="Secret engine type"]',
|
|
||||||
engineTypeRowVal: '[data-test-row-value="Secret engine type"]',
|
|
||||||
pathLabel: '[data-test-row-label="Path"]',
|
|
||||||
pathRowVal: '[data-test-row-value="Path"]',
|
|
||||||
accessorLabel: '[data-test-row-label="Accessor"]',
|
|
||||||
accessorRowVal: '[data-test-row-value="Accessor"]',
|
|
||||||
localLabel: '[data-test-row-label="Local"]',
|
|
||||||
localRowVal: '[data-test-value-div="Local"]',
|
|
||||||
sealWrapLabel: '[data-test-row-label="Seal wrap"]',
|
|
||||||
sealWrapRowVal: '[data-test-value-div="Seal wrap"]',
|
|
||||||
maxLeaseTtlLabel: '[data-test-row-label="Max lease TTL"]',
|
|
||||||
maxLeaseTtlRowVal: '[data-test-row-value="Max lease TTL"]',
|
|
||||||
allowedManagedKeysLabel: '[data-test-row-label="Allowed managed keys"]',
|
|
||||||
allowedManagedKeysRowVal: '[data-test-value-div="Allowed managed keys"]',
|
|
||||||
};
|
|
||||||
19
ui/tests/helpers/pki/page/pki-configuration-edit.js
Normal file
19
ui/tests/helpers/pki/page/pki-configuration-edit.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) HashiCorp, Inc.
|
||||||
|
* SPDX-License-Identifier: MPL-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const SELECTORS = {
|
||||||
|
errorBanner: '[data-test-error-banner]',
|
||||||
|
urlsEditSection: '[data-test-urls-edit-section]',
|
||||||
|
urlFieldInput: (attr) => `[data-test-input="${attr}"] textarea`,
|
||||||
|
urlFieldLabel: (attr) => `[data-test-input="${attr}"] label`,
|
||||||
|
crlEditSection: '[data-test-crl-edit-section]',
|
||||||
|
crlToggleInput: (attr) => `[data-test-input="${attr}"] input`,
|
||||||
|
crlTtlInput: (attr) => `[data-test-ttl-value="${attr}"]`,
|
||||||
|
crlFieldLabel: (attr) => `[data-test-input="${attr}"] label`,
|
||||||
|
saveButton: '[data-test-configuration-edit-save]',
|
||||||
|
cancelButton: '[data-test-configuration-edit-cancel]',
|
||||||
|
validationAlert: '[data-test-configuration-edit-validation-alert]',
|
||||||
|
deleteButton: (attr) => `[data-test-input="${attr}"] [data-test-string-list-button="delete"]`,
|
||||||
|
};
|
||||||
@@ -8,7 +8,12 @@ import { setupRenderingTest } from 'ember-qunit';
|
|||||||
import { render } from '@ember/test-helpers';
|
import { render } from '@ember/test-helpers';
|
||||||
import { hbs } from 'ember-cli-htmlbars';
|
import { hbs } from 'ember-cli-htmlbars';
|
||||||
import { setupEngine } from 'ember-engines/test-support';
|
import { setupEngine } from 'ember-engines/test-support';
|
||||||
import { SELECTORS } from 'vault/tests/helpers/pki/page/pki-configuration-details';
|
|
||||||
|
const SELECTORS = {
|
||||||
|
rowLabel: (attr) => `[data-test-row-label="${attr}"]`,
|
||||||
|
rowValue: (attr) => `[data-test-value-div="${attr}"]`,
|
||||||
|
rowIcon: (attr, icon) => `[data-test-row-value="${attr}"] [data-test-icon="${icon}"]`,
|
||||||
|
};
|
||||||
|
|
||||||
module('Integration | Component | Page::PkiConfigurationDetails', function (hooks) {
|
module('Integration | Component | Page::PkiConfigurationDetails', function (hooks) {
|
||||||
setupRenderingTest(hooks);
|
setupRenderingTest(hooks);
|
||||||
@@ -23,9 +28,13 @@ module('Integration | Component | Page::PkiConfigurationDetails', function (hook
|
|||||||
this.crl = this.store.createRecord('pki/crl', {
|
this.crl = this.store.createRecord('pki/crl', {
|
||||||
id: 'pki-test',
|
id: 'pki-test',
|
||||||
expiry: '20h',
|
expiry: '20h',
|
||||||
autoRebuild: false,
|
disable: false,
|
||||||
|
autoRebuild: true,
|
||||||
|
autoRebuildGracePeriod: '13h',
|
||||||
|
enableDelta: true,
|
||||||
|
deltaRebuildInterval: '15m',
|
||||||
ocspExpiry: '77h',
|
ocspExpiry: '77h',
|
||||||
oscpDisable: true,
|
ocspDisable: false,
|
||||||
});
|
});
|
||||||
this.mountConfig = {
|
this.mountConfig = {
|
||||||
id: 'pki-test',
|
id: 'pki-test',
|
||||||
@@ -49,10 +58,10 @@ module('Integration | Component | Page::PkiConfigurationDetails', function (hook
|
|||||||
);
|
);
|
||||||
|
|
||||||
assert
|
assert
|
||||||
.dom(SELECTORS.issuingCertificatesLabel)
|
.dom(SELECTORS.rowLabel('Issuing certificates'))
|
||||||
.hasText('Issuing certificates', 'issuing certificate row label renders');
|
.hasText('Issuing certificates', 'issuing certificate row label renders');
|
||||||
assert
|
assert
|
||||||
.dom(SELECTORS.issuingCertificatesRowVal)
|
.dom(SELECTORS.rowValue('Issuing certificates'))
|
||||||
.hasText('example.com', 'issuing certificate value renders');
|
.hasText('example.com', 'issuing certificate value renders');
|
||||||
this.urls.issuingCertificates = null;
|
this.urls.issuingCertificates = null;
|
||||||
await render(
|
await render(
|
||||||
@@ -60,13 +69,13 @@ module('Integration | Component | Page::PkiConfigurationDetails', function (hook
|
|||||||
{ owner: this.engine }
|
{ owner: this.engine }
|
||||||
);
|
);
|
||||||
assert
|
assert
|
||||||
.dom(SELECTORS.issuingCertificatesRowVal)
|
.dom(SELECTORS.rowValue('Issuing certificates'))
|
||||||
.hasText('None', 'issuing certificate value renders None if none is configured');
|
.hasText('None', 'issuing certificate value renders None if none is configured');
|
||||||
assert
|
assert
|
||||||
.dom(SELECTORS.crlDistributionPointsLabel)
|
.dom(SELECTORS.rowLabel('CRL distribution points'))
|
||||||
.hasText('CRL distribution points', 'crl distribution points row label renders');
|
.hasText('CRL distribution points', 'crl distribution points row label renders');
|
||||||
assert
|
assert
|
||||||
.dom(SELECTORS.crlDistributionPointsRowVal)
|
.dom(SELECTORS.rowValue('CRL distribution points'))
|
||||||
.hasText('None', 'crl distribution points value renders None if none is configured');
|
.hasText('None', 'crl distribution points value renders None if none is configured');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -76,26 +85,61 @@ module('Integration | Component | Page::PkiConfigurationDetails', function (hook
|
|||||||
{ owner: this.engine }
|
{ owner: this.engine }
|
||||||
);
|
);
|
||||||
|
|
||||||
assert.dom(SELECTORS.expiryLabel).hasText('Expiry', 'crl expiry row label renders');
|
assert.dom(SELECTORS.rowLabel('CRL building')).hasText('CRL building', 'crl expiry row label renders');
|
||||||
assert.dom(SELECTORS.expiryRowVal).hasText('20h', 'expiry value renders');
|
assert.dom(SELECTORS.rowValue('CRL building')).hasText('Enabled', 'enabled renders');
|
||||||
assert.dom(SELECTORS.rebuildLabel).hasText('Auto-rebuild', 'auto rebuild label renders');
|
assert.dom(SELECTORS.rowValue('Expiry')).hasText('20h', 'expiry value renders');
|
||||||
|
assert.dom(SELECTORS.rowLabel('Auto-rebuild')).hasText('Auto-rebuild', 'auto rebuild label renders');
|
||||||
|
assert.dom(SELECTORS.rowValue('Auto-rebuild')).hasText('On', 'it renders truthy auto build');
|
||||||
|
assert.dom(SELECTORS.rowIcon('Auto-rebuild', 'check-circle'));
|
||||||
assert
|
assert
|
||||||
.dom(SELECTORS.rebuildRowVal)
|
.dom(SELECTORS.rowValue('Auto-rebuild grace period'))
|
||||||
.hasText('Off', 'auto-rebuild value renders off if auto rebuild is false');
|
.hasText('13h', 'it renders auto build grace period');
|
||||||
this.crl.autoRebuild = true;
|
assert.dom(SELECTORS.rowValue('Delta CRL building')).hasText('On', 'it renders truthy delta crl build');
|
||||||
|
assert.dom(SELECTORS.rowIcon('Delta CRL building', 'check-circle'));
|
||||||
|
assert
|
||||||
|
.dom(SELECTORS.rowValue('Delta rebuild interval'))
|
||||||
|
.hasText('15m', 'it renders delta build duration');
|
||||||
|
assert
|
||||||
|
.dom(SELECTORS.rowValue('Responder APIs'))
|
||||||
|
.hasText('Enabled', 'responder apis value renders Enabled if oscp_disable=false');
|
||||||
|
assert.dom(SELECTORS.rowValue('Interval')).hasText('77h', 'interval value renders');
|
||||||
|
// check falsy aut_rebuild and _enable_delta hides duration values
|
||||||
|
this.crl.autoRebuild = false;
|
||||||
|
this.crl.enableDelta = false;
|
||||||
await render(
|
await render(
|
||||||
hbs`<Page::PkiConfigurationDetails @urls={{this.urls}} @crl={{this.crl}} @mountConfig={{this.mountConfig}} @hasConfig={{true}} />,`,
|
hbs`<Page::PkiConfigurationDetails @urls={{this.urls}} @crl={{this.crl}} @mountConfig={{this.mountConfig}} @hasConfig={{true}} />,`,
|
||||||
{ owner: this.engine }
|
{ owner: this.engine }
|
||||||
);
|
);
|
||||||
|
assert.dom(SELECTORS.rowValue('Auto-rebuild')).hasText('Off', 'it renders falsy auto build');
|
||||||
|
assert.dom(SELECTORS.rowIcon('Auto-rebuild', 'x-square'));
|
||||||
assert
|
assert
|
||||||
.dom(SELECTORS.rebuildRowVal)
|
.dom(SELECTORS.rowValue('Auto-rebuild grace period'))
|
||||||
.hasText('On', 'auto-rebuild value renders on if auto rebuild is true');
|
.doesNotExist('does not render auto-rebuild grace period');
|
||||||
assert.dom(SELECTORS.responderApiLabel).hasText('Responder APIs', 'responder apis row label renders');
|
assert.dom(SELECTORS.rowValue('Delta CRL building')).hasText('Off', 'it renders falsy delta cr build');
|
||||||
|
assert.dom(SELECTORS.rowIcon('Delta CRL building', 'x-square'));
|
||||||
assert
|
assert
|
||||||
.dom(SELECTORS.responderApiRowVal)
|
.dom(SELECTORS.rowValue('Delta rebuild interval'))
|
||||||
.hasText('Enabled', 'responder apis value renders Enabled if oscpDisable is true');
|
.doesNotExist('does not render delta rebuild duration');
|
||||||
assert.dom(SELECTORS.intervalLabel).hasText('Interval', 'interval row label renders');
|
|
||||||
assert.dom(SELECTORS.intervalRowVal).hasText('77h', 'interval value renders');
|
// check falsy disable and ocsp_disable hides duration values and other params
|
||||||
|
this.crl.autoRebuild = true;
|
||||||
|
this.crl.enableDelta = true;
|
||||||
|
this.crl.disable = true;
|
||||||
|
this.crl.ocspDisable = true;
|
||||||
|
await render(
|
||||||
|
hbs`<Page::PkiConfigurationDetails @urls={{this.urls}} @crl={{this.crl}} @mountConfig={{this.mountConfig}} @hasConfig={{true}} />,`,
|
||||||
|
{ owner: this.engine }
|
||||||
|
);
|
||||||
|
assert.dom(SELECTORS.rowValue('CRL building')).hasText('Disabled', 'disabled renders');
|
||||||
|
assert.dom(SELECTORS.rowValue('Expiry')).doesNotExist();
|
||||||
|
assert
|
||||||
|
.dom(SELECTORS.rowValue('Responder APIs'))
|
||||||
|
.hasText('Disabled', 'responder apis value renders Disabled');
|
||||||
|
assert.dom(SELECTORS.rowValue('Interval')).doesNotExist();
|
||||||
|
assert.dom(SELECTORS.rowValue('Auto-rebuild')).doesNotExist();
|
||||||
|
assert.dom(SELECTORS.rowValue('Auto-rebuild grace period')).doesNotExist();
|
||||||
|
assert.dom(SELECTORS.rowValue('Delta CRL building')).doesNotExist();
|
||||||
|
assert.dom(SELECTORS.rowValue('Delta rebuild interval')).doesNotExist();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('shows the correct information on mount configuration section', async function (assert) {
|
test('shows the correct information on mount configuration section', async function (assert) {
|
||||||
@@ -104,24 +148,28 @@ module('Integration | Component | Page::PkiConfigurationDetails', function (hook
|
|||||||
{ owner: this.engine }
|
{ owner: this.engine }
|
||||||
);
|
);
|
||||||
|
|
||||||
assert.dom(SELECTORS.engineTypeLabel).hasText('Secret engine type', 'engine type row label renders');
|
|
||||||
assert.dom(SELECTORS.engineTypeRowVal).hasText('pki', 'engine type row value renders');
|
|
||||||
assert.dom(SELECTORS.pathLabel).hasText('Path', 'path row label renders');
|
|
||||||
assert.dom(SELECTORS.pathRowVal).hasText('/pki-test', 'path row value renders');
|
|
||||||
assert.dom(SELECTORS.accessorLabel).hasText('Accessor', 'accessor row label renders');
|
|
||||||
assert.dom(SELECTORS.accessorRowVal).hasText('pki_33345b0d', 'accessor row value renders');
|
|
||||||
assert.dom(SELECTORS.localLabel).hasText('Local', 'local row label renders');
|
|
||||||
assert.dom(SELECTORS.localRowVal).hasText('No', 'local row value renders');
|
|
||||||
assert.dom(SELECTORS.sealWrapLabel).hasText('Seal wrap', 'seal wrap row label renders');
|
|
||||||
assert
|
assert
|
||||||
.dom(SELECTORS.sealWrapRowVal)
|
.dom(SELECTORS.rowLabel('Secret engine type'))
|
||||||
|
.hasText('Secret engine type', 'engine type row label renders');
|
||||||
|
assert.dom(SELECTORS.rowValue('Secret engine type')).hasText('pki', 'engine type row value renders');
|
||||||
|
assert.dom(SELECTORS.rowLabel('Path')).hasText('Path', 'path row label renders');
|
||||||
|
assert.dom(SELECTORS.rowValue('Path')).hasText('/pki-test', 'path row value renders');
|
||||||
|
assert.dom(SELECTORS.rowLabel('Accessor')).hasText('Accessor', 'accessor row label renders');
|
||||||
|
assert.dom(SELECTORS.rowValue('Accessor')).hasText('pki_33345b0d', 'accessor row value renders');
|
||||||
|
assert.dom(SELECTORS.rowLabel('Local')).hasText('Local', 'local row label renders');
|
||||||
|
assert.dom(SELECTORS.rowValue('Local')).hasText('No', 'local row value renders');
|
||||||
|
assert.dom(SELECTORS.rowLabel('Seal wrap')).hasText('Seal wrap', 'seal wrap row label renders');
|
||||||
|
assert
|
||||||
|
.dom(SELECTORS.rowValue('Seal wrap'))
|
||||||
.hasText('Yes', 'seal wrap row value renders Yes if sealWrap is true');
|
.hasText('Yes', 'seal wrap row value renders Yes if sealWrap is true');
|
||||||
assert.dom(SELECTORS.maxLeaseTtlLabel).hasText('Max lease TTL', 'max lease label renders');
|
assert.dom(SELECTORS.rowLabel('Max lease TTL')).hasText('Max lease TTL', 'max lease label renders');
|
||||||
assert.dom(SELECTORS.maxLeaseTtlRowVal).hasText('400h', 'max lease value renders');
|
assert.dom(SELECTORS.rowValue('Max lease TTL')).hasText('400h', 'max lease value renders');
|
||||||
assert
|
assert
|
||||||
.dom(SELECTORS.allowedManagedKeysLabel)
|
.dom(SELECTORS.rowLabel('Allowed managed keys'))
|
||||||
.hasText('Allowed managed keys', 'allowed managed keys label renders');
|
.hasText('Allowed managed keys', 'allowed managed keys label renders');
|
||||||
assert.dom(SELECTORS.allowedManagedKeysRowVal).hasText('Yes', 'allowed managed keys value renders');
|
assert
|
||||||
|
.dom(SELECTORS.rowValue('Allowed managed keys'))
|
||||||
|
.hasText('Yes', 'allowed managed keys value renders');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('shows mount configuration when hasConfig is false', async function (assert) {
|
test('shows mount configuration when hasConfig is false', async function (assert) {
|
||||||
@@ -133,23 +181,27 @@ module('Integration | Component | Page::PkiConfigurationDetails', function (hook
|
|||||||
{ owner: this.engine }
|
{ owner: this.engine }
|
||||||
);
|
);
|
||||||
|
|
||||||
assert.dom(SELECTORS.engineTypeLabel).hasText('Secret engine type', 'engine type row label renders');
|
|
||||||
assert.dom(SELECTORS.engineTypeRowVal).hasText('pki', 'engine type row value renders');
|
|
||||||
assert.dom(SELECTORS.pathLabel).hasText('Path', 'path row label renders');
|
|
||||||
assert.dom(SELECTORS.pathRowVal).hasText('/pki-test', 'path row value renders');
|
|
||||||
assert.dom(SELECTORS.accessorLabel).hasText('Accessor', 'accessor row label renders');
|
|
||||||
assert.dom(SELECTORS.accessorRowVal).hasText('pki_33345b0d', 'accessor row value renders');
|
|
||||||
assert.dom(SELECTORS.localLabel).hasText('Local', 'local row label renders');
|
|
||||||
assert.dom(SELECTORS.localRowVal).hasText('No', 'local row value renders');
|
|
||||||
assert.dom(SELECTORS.sealWrapLabel).hasText('Seal wrap', 'seal wrap row label renders');
|
|
||||||
assert
|
assert
|
||||||
.dom(SELECTORS.sealWrapRowVal)
|
.dom(SELECTORS.rowLabel('Secret engine type'))
|
||||||
|
.hasText('Secret engine type', 'engine type row label renders');
|
||||||
|
assert.dom(SELECTORS.rowValue('Secret engine type')).hasText('pki', 'engine type row value renders');
|
||||||
|
assert.dom(SELECTORS.rowLabel('Path')).hasText('Path', 'path row label renders');
|
||||||
|
assert.dom(SELECTORS.rowValue('Path')).hasText('/pki-test', 'path row value renders');
|
||||||
|
assert.dom(SELECTORS.rowLabel('Accessor')).hasText('Accessor', 'accessor row label renders');
|
||||||
|
assert.dom(SELECTORS.rowValue('Accessor')).hasText('pki_33345b0d', 'accessor row value renders');
|
||||||
|
assert.dom(SELECTORS.rowLabel('Local')).hasText('Local', 'local row label renders');
|
||||||
|
assert.dom(SELECTORS.rowValue('Local')).hasText('No', 'local row value renders');
|
||||||
|
assert.dom(SELECTORS.rowLabel('Seal wrap')).hasText('Seal wrap', 'seal wrap row label renders');
|
||||||
|
assert
|
||||||
|
.dom(SELECTORS.rowValue('Seal wrap'))
|
||||||
.hasText('Yes', 'seal wrap row value renders Yes if sealWrap is true');
|
.hasText('Yes', 'seal wrap row value renders Yes if sealWrap is true');
|
||||||
assert.dom(SELECTORS.maxLeaseTtlLabel).hasText('Max lease TTL', 'max lease label renders');
|
assert.dom(SELECTORS.rowLabel('Max lease TTL')).hasText('Max lease TTL', 'max lease label renders');
|
||||||
assert.dom(SELECTORS.maxLeaseTtlRowVal).hasText('400h', 'max lease value renders');
|
assert.dom(SELECTORS.rowValue('Max lease TTL')).hasText('400h', 'max lease value renders');
|
||||||
assert
|
assert
|
||||||
.dom(SELECTORS.allowedManagedKeysLabel)
|
.dom(SELECTORS.rowLabel('Allowed managed keys'))
|
||||||
.hasText('Allowed managed keys', 'allowed managed keys label renders');
|
.hasText('Allowed managed keys', 'allowed managed keys label renders');
|
||||||
assert.dom(SELECTORS.allowedManagedKeysRowVal).hasText('Yes', 'allowed managed keys value renders');
|
assert
|
||||||
|
.dom(SELECTORS.rowValue('Allowed managed keys'))
|
||||||
|
.hasText('Yes', 'allowed managed keys value renders');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -0,0 +1,211 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) HashiCorp, Inc.
|
||||||
|
* SPDX-License-Identifier: MPL-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { module, test } from 'qunit';
|
||||||
|
import { setupRenderingTest } from 'vault/tests/helpers';
|
||||||
|
import { click, fillIn, render } from '@ember/test-helpers';
|
||||||
|
import { setupEngine } from 'ember-engines/test-support';
|
||||||
|
import { hbs } from 'ember-cli-htmlbars';
|
||||||
|
import { setupMirage } from 'ember-cli-mirage/test-support';
|
||||||
|
import { SELECTORS } from 'vault/tests/helpers/pki/page/pki-configuration-edit';
|
||||||
|
import sinon from 'sinon';
|
||||||
|
import { allowAllCapabilitiesStub } from 'vault/tests/helpers/stubs';
|
||||||
|
|
||||||
|
module('Integration | Component | page/pki-configuration-edit', function (hooks) {
|
||||||
|
setupRenderingTest(hooks);
|
||||||
|
setupEngine(hooks, 'pki');
|
||||||
|
setupMirage(hooks);
|
||||||
|
|
||||||
|
hooks.beforeEach(async function () {
|
||||||
|
this.server.post('/sys/capabilities-self', allowAllCapabilitiesStub());
|
||||||
|
this.context = { owner: this.engine }; // this.engine set by setupEngine
|
||||||
|
this.store = this.owner.lookup('service:store');
|
||||||
|
this.cancelSpy = sinon.spy();
|
||||||
|
this.backend = 'pki-engine';
|
||||||
|
// both models only use findRecord. API parameters for pki/crl
|
||||||
|
// are set by default backend values when the engine is mounted
|
||||||
|
this.store.pushPayload('pki/crl', {
|
||||||
|
modelName: 'pki/crl',
|
||||||
|
id: this.backend,
|
||||||
|
auto_rebuild: false,
|
||||||
|
auto_rebuild_grace_period: '12h',
|
||||||
|
delta_rebuild_interval: '15m',
|
||||||
|
disable: false,
|
||||||
|
enable_delta: false,
|
||||||
|
expiry: '72h',
|
||||||
|
ocsp_disable: false,
|
||||||
|
ocsp_expiry: '12h',
|
||||||
|
});
|
||||||
|
this.store.pushPayload('pki/urls', {
|
||||||
|
modelName: 'pki/urls',
|
||||||
|
id: this.backend,
|
||||||
|
issuing_certificates: ['hashicorp.com'],
|
||||||
|
crl_distribution_points: ['some-crl-distribution.com'],
|
||||||
|
ocsp_servers: ['ocsp-stuff.com'],
|
||||||
|
});
|
||||||
|
this.urls = this.store.peekRecord('pki/urls', this.backend);
|
||||||
|
this.crl = this.store.peekRecord('pki/crl', this.backend);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('it renders with config data and updates config', async function (assert) {
|
||||||
|
assert.expect(27);
|
||||||
|
this.server.post(`/${this.backend}/config/crl`, (schema, req) => {
|
||||||
|
assert.ok(true, 'request made to save crl config');
|
||||||
|
assert.propEqual(
|
||||||
|
JSON.parse(req.requestBody),
|
||||||
|
{
|
||||||
|
auto_rebuild: true,
|
||||||
|
auto_rebuild_grace_period: '24h',
|
||||||
|
delta_rebuild_interval: '45m',
|
||||||
|
disable: false,
|
||||||
|
enable_delta: true,
|
||||||
|
expiry: '1152h',
|
||||||
|
ocsp_disable: false,
|
||||||
|
ocsp_expiry: '24h',
|
||||||
|
},
|
||||||
|
'it updates crl model attributes'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
this.server.post(`/${this.backend}/config/urls`, (schema, req) => {
|
||||||
|
assert.ok(true, 'request made to save urls config');
|
||||||
|
assert.propEqual(
|
||||||
|
JSON.parse(req.requestBody),
|
||||||
|
{
|
||||||
|
crl_distribution_points: ['test-crl.com'],
|
||||||
|
issuing_certificates: ['update-hashicorp.com'],
|
||||||
|
ocsp_servers: ['ocsp.com'],
|
||||||
|
},
|
||||||
|
'it updates url model attributes'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
await render(
|
||||||
|
hbs`
|
||||||
|
<Page::PkiConfigurationEdit
|
||||||
|
@urls={{this.urls}}
|
||||||
|
@crl={{this.crl}}
|
||||||
|
@backend={{this.backend}}
|
||||||
|
/>
|
||||||
|
`,
|
||||||
|
this.context
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.dom(SELECTORS.urlsEditSection).exists('renders urls section');
|
||||||
|
assert.dom(SELECTORS.crlEditSection).exists('renders crl section');
|
||||||
|
assert.dom(SELECTORS.cancelButton).exists();
|
||||||
|
this.urls.eachAttribute((name) => {
|
||||||
|
assert.dom(SELECTORS.urlFieldInput(name)).exists(`renders ${name} input`);
|
||||||
|
});
|
||||||
|
assert.dom(SELECTORS.urlFieldInput('issuingCertificates')).hasValue('hashicorp.com');
|
||||||
|
assert.dom(SELECTORS.urlFieldInput('crlDistributionPoints')).hasValue('some-crl-distribution.com');
|
||||||
|
assert.dom(SELECTORS.urlFieldInput('ocspServers')).hasValue('ocsp-stuff.com');
|
||||||
|
|
||||||
|
await fillIn(SELECTORS.urlFieldInput('issuingCertificates'), 'update-hashicorp.com');
|
||||||
|
await fillIn(SELECTORS.urlFieldInput('crlDistributionPoints'), 'test-crl.com');
|
||||||
|
await fillIn(SELECTORS.urlFieldInput('ocspServers'), 'ocsp.com');
|
||||||
|
|
||||||
|
// confirm default toggle state and text
|
||||||
|
this.crl.eachAttribute((name, { options }) => {
|
||||||
|
if (['expiry', 'ocspExpiry'].includes(name)) {
|
||||||
|
assert.dom(SELECTORS.crlToggleInput(name)).isChecked(`${name} defaults to toggled on`);
|
||||||
|
assert.dom(SELECTORS.crlFieldLabel(name)).hasTextContaining(options.label);
|
||||||
|
assert.dom(SELECTORS.crlFieldLabel(name)).hasTextContaining(options.helperTextEnabled);
|
||||||
|
}
|
||||||
|
if (['autoRebuildGracePeriod', 'deltaRebuildInterval'].includes(name)) {
|
||||||
|
assert.dom(SELECTORS.crlToggleInput(name)).isNotChecked(`${name} defaults off`);
|
||||||
|
assert.dom(SELECTORS.crlFieldLabel(name)).hasTextContaining(options.labelDisabled);
|
||||||
|
assert.dom(SELECTORS.crlFieldLabel(name)).hasTextContaining(options.helperTextDisabled);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// toggle everything on
|
||||||
|
await click(SELECTORS.crlToggleInput('autoRebuildGracePeriod'));
|
||||||
|
assert
|
||||||
|
.dom(SELECTORS.crlFieldLabel('autoRebuildGracePeriod'))
|
||||||
|
.hasTextContaining(
|
||||||
|
'Auto-rebuild on Vault will rebuild the CRL in the below grace period before expiration',
|
||||||
|
'it renders auto rebuild toggled on text'
|
||||||
|
);
|
||||||
|
await click(SELECTORS.crlToggleInput('deltaRebuildInterval'));
|
||||||
|
assert
|
||||||
|
.dom(SELECTORS.crlFieldLabel('deltaRebuildInterval'))
|
||||||
|
.hasTextContaining(
|
||||||
|
'Delta CRL building on Vault will rebuild the delta CRL at the interval below:',
|
||||||
|
'it renders delta crl build toggled on text'
|
||||||
|
);
|
||||||
|
|
||||||
|
// assert ttl values update model attributes
|
||||||
|
await fillIn(SELECTORS.crlTtlInput('Expiry'), '48');
|
||||||
|
await fillIn(SELECTORS.crlTtlInput('Auto-rebuild on'), '24');
|
||||||
|
await fillIn(SELECTORS.crlTtlInput('Delta CRL building on'), '45');
|
||||||
|
await fillIn(SELECTORS.crlTtlInput('OCSP responder APIs enabled'), '24');
|
||||||
|
await click(SELECTORS.saveButton);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('it removes urls and sends false crl values', async function (assert) {
|
||||||
|
assert.expect(8);
|
||||||
|
this.server.post(`/${this.backend}/config/crl`, (schema, req) => {
|
||||||
|
assert.ok(true, 'request made to save crl config');
|
||||||
|
assert.propEqual(
|
||||||
|
JSON.parse(req.requestBody),
|
||||||
|
{
|
||||||
|
auto_rebuild: false,
|
||||||
|
auto_rebuild_grace_period: '12h',
|
||||||
|
delta_rebuild_interval: '15m',
|
||||||
|
disable: true,
|
||||||
|
enable_delta: false,
|
||||||
|
expiry: '72h',
|
||||||
|
ocsp_disable: true,
|
||||||
|
ocsp_expiry: '12h',
|
||||||
|
},
|
||||||
|
'crl payload has correct data'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
this.server.post(`/${this.backend}/config/urls`, (schema, req) => {
|
||||||
|
assert.ok(true, 'request made to save urls config');
|
||||||
|
assert.propEqual(
|
||||||
|
JSON.parse(req.requestBody),
|
||||||
|
{
|
||||||
|
crl_distribution_points: [],
|
||||||
|
issuing_certificates: [],
|
||||||
|
ocsp_servers: [],
|
||||||
|
},
|
||||||
|
'url payload has empty arrays'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
await render(
|
||||||
|
hbs`
|
||||||
|
<Page::PkiConfigurationEdit
|
||||||
|
@urls={{this.urls}}
|
||||||
|
@crl={{this.crl}}
|
||||||
|
@backend={{this.backend}}
|
||||||
|
/>
|
||||||
|
`,
|
||||||
|
this.context
|
||||||
|
);
|
||||||
|
|
||||||
|
await click(SELECTORS.deleteButton('issuingCertificates'));
|
||||||
|
await click(SELECTORS.deleteButton('crlDistributionPoints'));
|
||||||
|
await click(SELECTORS.deleteButton('ocspServers'));
|
||||||
|
|
||||||
|
// toggle everything off
|
||||||
|
await click(SELECTORS.crlToggleInput('expiry'));
|
||||||
|
assert.dom(SELECTORS.crlFieldLabel('expiry')).hasText('No expiry The CRL will not be built.');
|
||||||
|
assert
|
||||||
|
.dom(SELECTORS.crlToggleInput('autoRebuildGracePeriod'))
|
||||||
|
.doesNotExist('expiry off hides the auto rebuild toggle');
|
||||||
|
assert
|
||||||
|
.dom(SELECTORS.crlToggleInput('deltaRebuildInterval'))
|
||||||
|
.doesNotExist('expiry off hides delta crl toggle');
|
||||||
|
await click(SELECTORS.crlToggleInput('ocspExpiry'));
|
||||||
|
assert
|
||||||
|
.dom(SELECTORS.crlFieldLabel('ocspExpiry'))
|
||||||
|
.hasTextContaining(
|
||||||
|
'OCSP responder APIs disabled Requests cannot be made to check if an individual certificate is valid.',
|
||||||
|
'it renders correct toggled off text'
|
||||||
|
);
|
||||||
|
|
||||||
|
await click(SELECTORS.saveButton);
|
||||||
|
});
|
||||||
|
});
|
||||||
45
ui/tests/unit/adapters/pki/crl-test.js
Normal file
45
ui/tests/unit/adapters/pki/crl-test.js
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) HashiCorp, Inc.
|
||||||
|
* SPDX-License-Identifier: MPL-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { module, test } from 'qunit';
|
||||||
|
import { setupTest } from 'vault/tests/helpers';
|
||||||
|
import { setupMirage } from 'ember-cli-mirage/test-support';
|
||||||
|
|
||||||
|
module('Unit | Adapter | pki/crl', function (hooks) {
|
||||||
|
setupTest(hooks);
|
||||||
|
setupMirage(hooks);
|
||||||
|
|
||||||
|
hooks.beforeEach(function () {
|
||||||
|
this.store = this.owner.lookup('service:store');
|
||||||
|
this.backend = 'pki-engine';
|
||||||
|
});
|
||||||
|
|
||||||
|
test('it should make request to correct endpoint on update', async function (assert) {
|
||||||
|
assert.expect(1);
|
||||||
|
|
||||||
|
this.server.post(`/${this.backend}/config/crl`, () => {
|
||||||
|
assert.ok(true, 'request made to correct endpoint on update');
|
||||||
|
});
|
||||||
|
|
||||||
|
this.store.pushPayload('pki/crl', {
|
||||||
|
modelName: 'pki/crl',
|
||||||
|
id: this.backend,
|
||||||
|
});
|
||||||
|
|
||||||
|
const model = this.store.peekRecord('pki/crl', this.backend);
|
||||||
|
await model.save();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('it should make request to correct endpoint on find', async function (assert) {
|
||||||
|
assert.expect(1);
|
||||||
|
|
||||||
|
this.server.get(`/${this.backend}/config/crl`, () => {
|
||||||
|
assert.ok(true, 'request is made to correct endpoint on find');
|
||||||
|
return { data: { id: this.backend } };
|
||||||
|
});
|
||||||
|
|
||||||
|
this.store.findRecord('pki/crl', this.backend);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -4,50 +4,42 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { module, test } from 'qunit';
|
import { module, test } from 'qunit';
|
||||||
import { resolve } from 'rsvp';
|
|
||||||
import { setupTest } from 'vault/tests/helpers';
|
import { setupTest } from 'vault/tests/helpers';
|
||||||
|
import { setupMirage } from 'ember-cli-mirage/test-support';
|
||||||
const storeStub = {
|
|
||||||
pushPayload() {},
|
|
||||||
serializerFor() {
|
|
||||||
return {
|
|
||||||
serializeIntoHash() {},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const makeSnapshot = (obj) => {
|
|
||||||
const snapshot = {
|
|
||||||
id: obj.id,
|
|
||||||
record: {
|
|
||||||
...obj,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
snapshot.attr = (attr) => snapshot[attr];
|
|
||||||
return snapshot;
|
|
||||||
};
|
|
||||||
|
|
||||||
module('Unit | Adapter | pki/urls', function (hooks) {
|
module('Unit | Adapter | pki/urls', function (hooks) {
|
||||||
setupTest(hooks);
|
setupTest(hooks);
|
||||||
|
setupMirage(hooks);
|
||||||
|
|
||||||
test('pki url endpoints', function (assert) {
|
hooks.beforeEach(function () {
|
||||||
let url, method;
|
this.store = this.owner.lookup('service:store');
|
||||||
const adapter = this.owner.factoryFor('adapter:pki/urls').create({
|
this.backend = 'pki-engine';
|
||||||
ajax: (...args) => {
|
});
|
||||||
[url, method] = args;
|
|
||||||
return resolve({});
|
test('it should make request to correct endpoint on update', async function (assert) {
|
||||||
},
|
assert.expect(1);
|
||||||
|
|
||||||
|
this.server.post(`/${this.backend}/config/urls`, () => {
|
||||||
|
assert.ok(true, 'request made to correct endpoint on update');
|
||||||
});
|
});
|
||||||
|
|
||||||
adapter.createRecord(storeStub, 'pki/urls', makeSnapshot({ id: 'pki-create' }));
|
this.store.pushPayload('pki/urls', {
|
||||||
assert.strictEqual(url, '/v1/pki-create/config/urls', 'create url OK');
|
modelName: 'pki/urls',
|
||||||
assert.strictEqual(method, 'POST', 'create method OK');
|
id: this.backend,
|
||||||
|
});
|
||||||
|
|
||||||
adapter.updateRecord(storeStub, 'pki/urls', makeSnapshot({ id: 'pki-update' }));
|
const model = this.store.peekRecord('pki/urls', this.backend);
|
||||||
assert.strictEqual(url, '/v1/pki-update/config/urls', 'update url OK');
|
await model.save();
|
||||||
assert.strictEqual(method, 'PUT', 'update method OK');
|
});
|
||||||
|
|
||||||
adapter.findRecord(null, 'capabilities', 'pki-find');
|
test('it should make request to correct endpoint on find', async function (assert) {
|
||||||
assert.strictEqual(url, '/v1/pki-find/config/urls', 'find url OK');
|
assert.expect(1);
|
||||||
assert.strictEqual(method, 'GET', 'find method OK');
|
|
||||||
|
this.server.get(`/${this.backend}/config/urls`, () => {
|
||||||
|
assert.ok(true, 'request is made to correct endpoint on find');
|
||||||
|
return { data: { id: this.backend } };
|
||||||
|
});
|
||||||
|
|
||||||
|
this.store.findRecord('pki/urls', this.backend);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -7,7 +7,13 @@
|
|||||||
export interface FormField {
|
export interface FormField {
|
||||||
name: string;
|
name: string;
|
||||||
type: string;
|
type: string;
|
||||||
options: unknown;
|
options: AttributeOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AttributeOptions {
|
||||||
|
label: string;
|
||||||
|
mapToBoolean: string;
|
||||||
|
isOppositeValue: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FormFieldGroups {
|
export interface FormFieldGroups {
|
||||||
@@ -40,3 +46,10 @@ export interface Breadcrumb {
|
|||||||
route?: string;
|
route?: string;
|
||||||
linkExternal?: boolean;
|
linkExternal?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface TtlEvent {
|
||||||
|
enabled: boolean;
|
||||||
|
seconds: number;
|
||||||
|
timeString: string;
|
||||||
|
goSafeTimeString: string;
|
||||||
|
}
|
||||||
|
|||||||
16
ui/types/vault/models/pki/crl.d.ts
vendored
Normal file
16
ui/types/vault/models/pki/crl.d.ts
vendored
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import Model from '@ember-data/model';
|
||||||
|
import { FormField } from 'vault/app-types';
|
||||||
|
|
||||||
|
export default class PkiCrlModel extends Model {
|
||||||
|
autoRebuild: boolean;
|
||||||
|
autoRebuildGracePeriod: string;
|
||||||
|
enableDelta: boolean;
|
||||||
|
expiry: string;
|
||||||
|
deltaRebuildInterval: string;
|
||||||
|
disable: boolean;
|
||||||
|
ocspExpiry: string;
|
||||||
|
ocspDisable: boolean;
|
||||||
|
crlPath: string;
|
||||||
|
formFields: FormField[];
|
||||||
|
get canSet(): boolean;
|
||||||
|
}
|
||||||
11
ui/types/vault/models/pki/urls.d.ts
vendored
Normal file
11
ui/types/vault/models/pki/urls.d.ts
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import Model from '@ember-data/model';
|
||||||
|
|
||||||
|
export default class PkiUrlsModel extends Model {
|
||||||
|
get useOpenAPI(): boolean;
|
||||||
|
getHelpUrl(backendPath: string): string;
|
||||||
|
issuingCertificates: array;
|
||||||
|
crlDistributionPoints: array;
|
||||||
|
ocspServers: array;
|
||||||
|
urlsPath: string;
|
||||||
|
get canSet(): boolean;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user