mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-29 17:52:32 +00:00 
			
		
		
		
	UI: add pki cluster config parameters (#20724)
* add config directory, rename crl and urls models * fix imports * add cluster config fields to edit form * reorder url save * update tests * add to details page * add details test; * fix adapter name * fix cluster adapter test name * combine adapter tests * update imports * fix git diff * move crl and urls adapters to config folder * add config file * woops add config adapter * final renaming!! * fix imports after naming to base * add cluster to beforeModel hook * hide help text * maybe you should write tests that actually pass, claire * seriously claire its embarrassing
This commit is contained in:
		| @@ -3,16 +3,11 @@ | ||||
|  * SPDX-License-Identifier: MPL-2.0 | ||||
|  */ | ||||
| 
 | ||||
| import { encodePath } from 'vault/utils/path-encoding-helpers'; | ||||
| import ApplicationAdapter from '../application'; | ||||
| import ApplicationAdapter from '../../application'; | ||||
| 
 | ||||
| export default class PkiCrlAdapter extends ApplicationAdapter { | ||||
| export default class PkiConfigBaseAdapter extends ApplicationAdapter { | ||||
|   namespace = 'v1'; | ||||
| 
 | ||||
|   _url(backend) { | ||||
|     return `${this.buildURL()}/${encodePath(backend)}/config/crl`; | ||||
|   } | ||||
| 
 | ||||
|   findRecord(store, type, backend) { | ||||
|     return this.ajax(this._url(backend), 'GET').then((resp) => { | ||||
|       return resp.data; | ||||
							
								
								
									
										15
									
								
								ui/app/adapters/pki/config/cluster.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								ui/app/adapters/pki/config/cluster.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| /** | ||||
|  * Copyright (c) HashiCorp, Inc. | ||||
|  * SPDX-License-Identifier: MPL-2.0 | ||||
|  */ | ||||
|  | ||||
| import { encodePath } from 'vault/utils/path-encoding-helpers'; | ||||
| import PkiConfigBaseAdapter from './base'; | ||||
|  | ||||
| export default class PkiConfigClusterAdapter extends PkiConfigBaseAdapter { | ||||
|   namespace = 'v1'; | ||||
|  | ||||
|   _url(backend) { | ||||
|     return `${this.buildURL()}/${encodePath(backend)}/config/cluster`; | ||||
|   } | ||||
| } | ||||
							
								
								
									
										15
									
								
								ui/app/adapters/pki/config/crl.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								ui/app/adapters/pki/config/crl.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| /** | ||||
|  * Copyright (c) HashiCorp, Inc. | ||||
|  * SPDX-License-Identifier: MPL-2.0 | ||||
|  */ | ||||
|  | ||||
| import { encodePath } from 'vault/utils/path-encoding-helpers'; | ||||
| import PkiConfigBaseAdapter from './base'; | ||||
|  | ||||
| export default class PkiConfigCrlAdapter extends PkiConfigBaseAdapter { | ||||
|   namespace = 'v1'; | ||||
|  | ||||
|   _url(backend) { | ||||
|     return `${this.buildURL()}/${encodePath(backend)}/config/crl`; | ||||
|   } | ||||
| } | ||||
							
								
								
									
										15
									
								
								ui/app/adapters/pki/config/urls.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								ui/app/adapters/pki/config/urls.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| /** | ||||
|  * Copyright (c) HashiCorp, Inc. | ||||
|  * SPDX-License-Identifier: MPL-2.0 | ||||
|  */ | ||||
|  | ||||
| import { encodePath } from 'vault/utils/path-encoding-helpers'; | ||||
| import PkiConfigBaseAdapter from './base'; | ||||
|  | ||||
| export default class PkiConfigUrlsAdapter extends PkiConfigBaseAdapter { | ||||
|   namespace = 'v1'; | ||||
|  | ||||
|   _url(backend) { | ||||
|     return `${this.buildURL()}/${encodePath(backend)}/config/urls`; | ||||
|   } | ||||
| } | ||||
| @@ -1,24 +0,0 @@ | ||||
| /** | ||||
|  * Copyright (c) HashiCorp, Inc. | ||||
|  * SPDX-License-Identifier: MPL-2.0 | ||||
|  */ | ||||
|  | ||||
| import { encodePath } from 'vault/utils/path-encoding-helpers'; | ||||
| import ApplicationAdapter from '../application'; | ||||
|  | ||||
| export default class PkiUrlsAdapter extends ApplicationAdapter { | ||||
|   namespace = 'v1'; | ||||
|  | ||||
|   _url(backend) { | ||||
|     return `${this.buildURL()}/${encodePath(backend)}/config/urls`; | ||||
|   } | ||||
|  | ||||
|   updateRecord(store, type, snapshot) { | ||||
|     const data = snapshot.serialize(); | ||||
|     return this.ajax(this._url(snapshot.record.id), 'POST', { data }); | ||||
|   } | ||||
|  | ||||
|   urlForFindRecord(id) { | ||||
|     return this._url(id); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										40
									
								
								ui/app/models/pki/config/cluster.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								ui/app/models/pki/config/cluster.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| /** | ||||
|  * Copyright (c) HashiCorp, Inc. | ||||
|  * SPDX-License-Identifier: MPL-2.0 | ||||
|  */ | ||||
|  | ||||
| import Model, { attr } from '@ember-data/model'; | ||||
| import { withFormFields } from 'vault/decorators/model-form-fields'; | ||||
| import lazyCapabilities, { apiPath } from 'vault/macros/lazy-capabilities'; | ||||
|  | ||||
| @withFormFields() | ||||
| export default class PkiConfigClusterModel extends Model { | ||||
|   // This model uses the backend value as the model ID | ||||
|   get useOpenAPI() { | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   getHelpUrl(backendPath) { | ||||
|     return `/v1/${backendPath}/config/cluster?help=1`; | ||||
|   } | ||||
|  | ||||
|   @attr('string', { | ||||
|     label: "Mount's API path", | ||||
|     subText: | ||||
|       "Specifies the path to this performance replication cluster's API mount path, including any namespaces as path components. This address is used for the ACME directories, which must be served over a TLS-enabled listener.", | ||||
|   }) | ||||
|   path; | ||||
|   @attr('string', { | ||||
|     label: 'AIA path', | ||||
|     subText: | ||||
|       "Specifies the path to this performance replication cluster's AIA distribution point; may refer to an external, non-Vault responder.", | ||||
|   }) | ||||
|   aiaPath; | ||||
|  | ||||
|   // this is for pki-only cluster config, not the universal vault cluster | ||||
|   @lazyCapabilities(apiPath`${'id'}/config/cluster`, 'id') clusterPath; | ||||
|  | ||||
|   get canSet() { | ||||
|     return this.clusterPath.get('canCreate') !== false; | ||||
|   } | ||||
| } | ||||
| @@ -17,7 +17,7 @@ const formFieldGroups = [ | ||||
|   { 'Unified Revocation': ['crossClusterRevocation', 'unifiedCrl', 'unifiedCrlOnExistingPaths'] }, | ||||
| ]; | ||||
| @withFormFields(null, formFieldGroups) | ||||
| export default class PkiCrlModel extends Model { | ||||
| export default class PkiConfigCrlModel extends Model { | ||||
|   // This model uses the backend value as the model ID
 | ||||
| 
 | ||||
|   @attr('boolean') autoRebuild; | ||||
| @@ -8,7 +8,7 @@ import { withFormFields } from 'vault/decorators/model-form-fields'; | ||||
| import lazyCapabilities, { apiPath } from 'vault/macros/lazy-capabilities'; | ||||
| 
 | ||||
| @withFormFields() | ||||
| export default class PkiUrlsModel extends Model { | ||||
| export default class PkiConfigUrlsModel extends Model { | ||||
|   // This model uses the backend value as the model ID
 | ||||
|   get useOpenAPI() { | ||||
|     return true; | ||||
| @@ -23,8 +23,20 @@ | ||||
|     </ToolbarActions> | ||||
|   </Toolbar> | ||||
|  | ||||
|   {{#if (not (eq @cluster 403))}} | ||||
|     <h2 class="title is-4 has-bottom-margin-xs has-top-margin-xl has-border-bottom-light has-bottom-padding-s"> | ||||
|       Cluster Config | ||||
|     </h2> | ||||
|     {{#each @cluster.allFields as |attr|}} | ||||
|       <InfoTableRow | ||||
|         @label={{or attr.options.label (humanize (dasherize attr.name))}} | ||||
|         @value={{or (get @cluster attr.name) "None"}} | ||||
|       /> | ||||
|     {{/each}} | ||||
|   {{/if}} | ||||
|  | ||||
|   {{#if (not (eq @urls 403))}} | ||||
|     <h2 class="title is-4 has-bottom-margin-xs has-top-margin-m 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"> | ||||
|       Global URLs | ||||
|     </h2> | ||||
|     <InfoTableRow @label="Issuing certificates" @value={{or @urls.issuingCertificates "None"}} /> | ||||
|   | ||||
| @@ -14,7 +14,7 @@ import type Store from '@ember-data/store'; | ||||
| import type VersionService from 'vault/services/version'; | ||||
|  | ||||
| interface Args { | ||||
|   currentPath: string; | ||||
|   backend: string; | ||||
| } | ||||
|  | ||||
| export default class PkiConfigurationDetails extends Component<Args> { | ||||
| @@ -32,7 +32,7 @@ export default class PkiConfigurationDetails extends Component<Args> { | ||||
|   async deleteAllIssuers() { | ||||
|     try { | ||||
|       const issuerAdapter = this.store.adapterFor('pki/issuer'); | ||||
|       await issuerAdapter.deleteAllIssuers(this.args.currentPath); | ||||
|       await issuerAdapter.deleteAllIssuers(this.args.backend); | ||||
|       this.flashMessages.success('Successfully deleted all issuers and keys'); | ||||
|       this.showDeleteAllIssuers = false; | ||||
|       this.router.transitionTo('vault.cluster.secrets.backend.pki.configuration.index'); | ||||
|   | ||||
| @@ -3,6 +3,25 @@ | ||||
|     <AlertBanner @type="danger" @message={{this.errorBanner}} data-test-error-banner /> | ||||
|   {{/if}} | ||||
|   <form {{on "submit" (perform this.save)}}> | ||||
|     <fieldset class="is-shadowless is-marginless is-borderless is-fullwidth" data-test-cluster-config-edit-section> | ||||
|       <h2 class="title is-size-5 has-border-bottom-light page-header"> | ||||
|         Cluster Config | ||||
|       </h2> | ||||
|       {{#if @cluster.canSet}} | ||||
|         {{#each @cluster.allFields as |attr|}} | ||||
|           <FormField @attr={{attr}} @model={{@cluster}} @showHelpText={{false}} /> | ||||
|         {{/each}} | ||||
|       {{else}} | ||||
|         <EmptyState | ||||
|           class="is-box-shadowless" | ||||
|           @title="You do not have permission to set the cluster config" | ||||
|           @message="Ask your administrator if you think you should have access to:" | ||||
|         > | ||||
|           <code>POST /{{@backend}}/config/cluster</code> | ||||
|         </EmptyState> | ||||
|       {{/if}} | ||||
|     </fieldset> | ||||
|  | ||||
|     <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 | ||||
|   | ||||
| @@ -13,21 +13,21 @@ import errorMessage from 'vault/utils/error-message'; | ||||
| import type RouterService from '@ember/routing/router-service'; | ||||
| import type FlashMessageService from 'vault/services/flash-messages'; | ||||
| import type VersionService from 'vault/services/version'; | ||||
| import type PkiCrlModel from 'vault/models/pki/crl'; | ||||
| import type PkiUrlsModel from 'vault/models/pki/urls'; | ||||
| import type PkiConfigCrlModel from 'vault/models/pki/config/crl'; | ||||
| import type PkiConfigUrlsModel from 'vault/models/pki/config/urls'; | ||||
| import type { FormField, TtlEvent } from 'vault/app-types'; | ||||
|  | ||||
| interface Args { | ||||
|   crl: PkiCrlModel; | ||||
|   urls: PkiUrlsModel; | ||||
|   crl: PkiConfigCrlModel; | ||||
|   urls: PkiConfigUrlsModel; | ||||
| } | ||||
| interface PkiCrlTtls { | ||||
| interface PkiConfigCrlTtls { | ||||
|   autoRebuildGracePeriod: string; | ||||
|   expiry: string; | ||||
|   deltaRebuildInterval: string; | ||||
|   ocspExpiry: string; | ||||
| } | ||||
| interface PkiCrlBooleans { | ||||
| interface PkiConfigCrlBooleans { | ||||
|   autoRebuild: boolean; | ||||
|   enableDelta: boolean; | ||||
|   disable: boolean; | ||||
| @@ -69,10 +69,10 @@ export default class PkiConfigurationEditComponent extends Component<Args> { | ||||
|   handleTtl(attr: FormField, e: TtlEvent) { | ||||
|     const { enabled, goSafeTimeString } = e; | ||||
|     const ttlAttr = attr.name; | ||||
|     this.args.crl[ttlAttr as keyof PkiCrlTtls] = goSafeTimeString; | ||||
|     this.args.crl[ttlAttr as keyof PkiConfigCrlTtls] = 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 | ||||
|     this.args.crl[attr.options.mapToBoolean as keyof PkiConfigCrlBooleans] = attr.options.isOppositeValue | ||||
|       ? !enabled | ||||
|       : enabled; | ||||
|   } | ||||
|   | ||||
| @@ -11,7 +11,7 @@ import { tracked } from '@glimmer/tracking'; | ||||
| import { task } from 'ember-concurrency'; | ||||
| import errorMessage from 'vault/utils/error-message'; | ||||
| import type PkiActionModel from 'vault/models/pki/action'; | ||||
| import type PkiUrlsModel from 'vault/models/pki/urls'; | ||||
| import type PkiConfigUrlsModel from 'vault/models/pki/config/urls'; | ||||
| import type FlashMessageService from 'vault/services/flash-messages'; | ||||
| import type RouterService from '@ember/routing/router-service'; | ||||
| import type { ValidationMap } from 'vault/vault/app-types'; | ||||
| @@ -22,7 +22,7 @@ interface AdapterOptions { | ||||
| } | ||||
| interface Args { | ||||
|   model: PkiActionModel; | ||||
|   urls: PkiUrlsModel; | ||||
|   urls: PkiConfigUrlsModel; | ||||
|   onCancel: CallableFunction; | ||||
|   onComplete: CallableFunction; | ||||
|   onSave?: CallableFunction; | ||||
| @@ -107,8 +107,10 @@ export default class PkiGenerateRootComponent extends Component<Args> { | ||||
|     const continueSave = this.checkFormValidity(); | ||||
|     if (!continueSave) return; | ||||
|     try { | ||||
|       yield this.setUrls(); | ||||
|       yield this.args.model.save({ adapterOptions: this.args.adapterOptions }); | ||||
|       // root generation must occur first in case templates are used for URL fields | ||||
|       // this way an issuer_id exists for backend to interpolate into the template | ||||
|       yield this.setUrls(); | ||||
|       this.flashMessages.success('Successfully generated root.'); | ||||
|       if (this.args.onSave) { | ||||
|         this.args.onSave(); | ||||
|   | ||||
| @@ -18,7 +18,8 @@ export default class PkiRoute extends Route { | ||||
|     const mountPath = this.secretMountPath.currentPath; | ||||
|     return hash({ | ||||
|       role: this.pathHelp.getNewModel('pki/role', mountPath), | ||||
|       urls: this.pathHelp.getNewModel('pki/urls', mountPath), | ||||
|       urls: this.pathHelp.getNewModel('pki/config/urls', mountPath), | ||||
|       cluster: this.pathHelp.getNewModel('pki/config/cluster', mountPath), | ||||
|       key: this.pathHelp.getNewModel('pki/key', mountPath), | ||||
|       signCsr: this.pathHelp.getNewModel('pki/sign-intermediate', mountPath), | ||||
|       certGenerate: this.pathHelp.getNewModel('pki/certificate/generate', mountPath), | ||||
|   | ||||
| @@ -14,8 +14,9 @@ export default class PkiConfigurationRoute extends Route { | ||||
|     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), | ||||
|       cluster: this.store.findRecord('pki/config/cluster', engine.id).catch((e) => e.httpStatus), | ||||
|       urls: this.store.findRecord('pki/config/urls', engine.id).catch((e) => e.httpStatus), | ||||
|       crl: this.store.findRecord('pki/config/crl', engine.id).catch((e) => e.httpStatus), | ||||
|     }); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -12,9 +12,10 @@ export default class PkiConfigurationEditRoute extends Route { | ||||
|   @service secretMountPath; | ||||
|  | ||||
|   model() { | ||||
|     const { urls, crl, engine } = this.modelFor('configuration'); | ||||
|     const { cluster, urls, crl, engine } = this.modelFor('configuration'); | ||||
|     return { | ||||
|       engineId: engine.id, | ||||
|       cluster, | ||||
|       urls, | ||||
|       crl, | ||||
|     }; | ||||
|   | ||||
| @@ -20,10 +20,11 @@ export default class ConfigurationIndexRoute extends Route { | ||||
|   } | ||||
|  | ||||
|   model() { | ||||
|     const { urls, crl, engine } = this.modelFor('configuration'); | ||||
|     const { cluster, urls, crl, engine } = this.modelFor('configuration'); | ||||
|     return hash({ | ||||
|       hasConfig: this.shouldPromptConfig, | ||||
|       engine, | ||||
|       cluster, | ||||
|       urls, | ||||
|       crl, | ||||
|       mountConfig: this.fetchMountConfig(engine.id), | ||||
|   | ||||
| @@ -10,4 +10,9 @@ | ||||
|   </p.levelLeft> | ||||
| </PageHeader> | ||||
|  | ||||
| <Page::PkiConfigurationEdit @urls={{this.model.urls}} @crl={{this.model.crl}} @backend={{this.model.engineId}} /> | ||||
| <Page::PkiConfigurationEdit | ||||
|   @cluster={{this.model.cluster}} | ||||
|   @urls={{this.model.urls}} | ||||
|   @crl={{this.model.crl}} | ||||
|   @backend={{this.model.engineId}} | ||||
| /> | ||||
| @@ -10,10 +10,11 @@ | ||||
| /> | ||||
|  | ||||
| <Page::PkiConfigurationDetails | ||||
|   @cluster={{this.model.cluster}} | ||||
|   @urls={{this.model.urls}} | ||||
|   @crl={{this.model.crl}} | ||||
|   @mountConfig={{this.model.mountConfig}} | ||||
|   @currentPath={{this.model.engine.id}} | ||||
|   @backend={{this.model.engine.id}} | ||||
|   @canDeleteAllIssuers={{this.model.issuerModel.canDeleteAllIssuers}} | ||||
|   @hasConfig={{this.model.hasConfig}} | ||||
| /> | ||||
| @@ -45,7 +45,7 @@ module('Acceptance | pki engine route cleanup test', function (hooks) { | ||||
|       await visit(`/vault/secrets/${this.mountPath}/pki/overview`); | ||||
|       await click(SELECTORS.emptyStateLink); | ||||
|       configs = this.store.peekAll('pki/action'); | ||||
|       urls = this.store.peekRecord('pki/urls', this.mountPath); | ||||
|       urls = this.store.peekRecord('pki/config/urls', this.mountPath); | ||||
|       config = configs.objectAt(0); | ||||
|       assert.strictEqual(configs.length, 1, 'One config model present'); | ||||
|       assert.false(urls.hasDirtyAttributes, 'URLs is loaded from endpoint'); | ||||
| @@ -54,13 +54,13 @@ module('Acceptance | pki engine route cleanup test', function (hooks) { | ||||
|       // Cancel button rolls it back | ||||
|       await click(SELECTORS.configuration.cancelButton); | ||||
|       configs = this.store.peekAll('pki/action'); | ||||
|       urls = this.store.peekRecord('pki/urls', this.mountPath); | ||||
|       urls = this.store.peekRecord('pki/config/urls', this.mountPath); | ||||
|       assert.strictEqual(configs.length, 0, 'config model is rolled back on cancel'); | ||||
|       assert.strictEqual(urls.id, this.mountPath, 'Urls still exists on exit'); | ||||
|  | ||||
|       await click(SELECTORS.emptyStateLink); | ||||
|       configs = this.store.peekAll('pki/action'); | ||||
|       urls = this.store.peekRecord('pki/urls', this.mountPath); | ||||
|       urls = this.store.peekRecord('pki/config/urls', this.mountPath); | ||||
|       config = configs.objectAt(0); | ||||
|       assert.strictEqual(configs.length, 1, 'One config model present'); | ||||
|       assert.false(urls.hasDirtyAttributes, 'URLs is loaded from endpoint'); | ||||
| @@ -69,7 +69,7 @@ module('Acceptance | pki engine route cleanup test', function (hooks) { | ||||
|       // Exit page via link rolls it back | ||||
|       await click(SELECTORS.overviewBreadcrumb); | ||||
|       configs = this.store.peekAll('pki/action'); | ||||
|       urls = this.store.peekRecord('pki/urls', this.mountPath); | ||||
|       urls = this.store.peekRecord('pki/config/urls', this.mountPath); | ||||
|       assert.strictEqual(configs.length, 0, 'config model is rolled back on cancel'); | ||||
|       assert.strictEqual(urls.id, this.mountPath, 'Urls still exists on exit'); | ||||
|     }); | ||||
|   | ||||
| @@ -5,6 +5,8 @@ | ||||
|  | ||||
| export const SELECTORS = { | ||||
|   errorBanner: '[data-test-error-banner]', | ||||
|   configEditSection: '[data-test-cluster-config-edit-section]', | ||||
|   configInput: (attr) => `[data-test-input="${attr}"]`, | ||||
|   urlsEditSection: '[data-test-urls-edit-section]', | ||||
|   urlFieldInput: (attr) => `[data-test-input="${attr}"] textarea`, | ||||
|   urlFieldLabel: (attr) => `[data-test-input="${attr}"] label`, | ||||
|   | ||||
| @@ -24,8 +24,15 @@ module('Integration | Component | Page::PkiConfigurationDetails', function (hook | ||||
|     this.secretMountPath.currentPath = 'pki-test'; | ||||
|  | ||||
|     this.store = this.owner.lookup('service:store'); | ||||
|     this.urls = this.store.createRecord('pki/urls', { id: 'pki-test', issuingCertificates: 'example.com' }); | ||||
|     this.crl = this.store.createRecord('pki/crl', { | ||||
|     this.cluster = this.store.createRecord('pki/config/cluster', { | ||||
|       id: 'pki-test', | ||||
|       path: 'https://pr-a.vault.example.com/v1/ns1/pki-root', | ||||
|     }); | ||||
|     this.urls = this.store.createRecord('pki/config/urls', { | ||||
|       id: 'pki-test', | ||||
|       issuingCertificates: 'example.com', | ||||
|     }); | ||||
|     this.crl = this.store.createRecord('pki/config/crl', { | ||||
|       id: 'pki-test', | ||||
|       expiry: '20h', | ||||
|       disable: false, | ||||
| @@ -54,6 +61,17 @@ module('Integration | Component | Page::PkiConfigurationDetails', function (hook | ||||
|     }; | ||||
|   }); | ||||
|  | ||||
|   test('shows the correct information on cluster config', async function (assert) { | ||||
|     await render(hbs`<Page::PkiConfigurationDetails @cluster={{this.cluster}} @hasConfig={{true}} />,`, { | ||||
|       owner: this.engine, | ||||
|     }); | ||||
|  | ||||
|     assert | ||||
|       .dom(SELECTORS.rowValue("Mount's API path")) | ||||
|       .hasText('https://pr-a.vault.example.com/v1/ns1/pki-root', 'mount API path row renders'); | ||||
|     assert.dom(SELECTORS.rowValue('AIA path')).hasText('None', "renders 'None' when no data"); | ||||
|   }); | ||||
|  | ||||
|   test('shows the correct information on global urls section', async function (assert) { | ||||
|     await render( | ||||
|       hbs`<Page::PkiConfigurationDetails @urls={{this.urls}} @crl={{this.crl}} @mountConfig={{this.mountConfig}} @hasConfig={{true}} />,`, | ||||
|   | ||||
| @@ -26,8 +26,12 @@ module('Integration | Component | page/pki-configuration-edit', function (hooks) | ||||
|     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', | ||||
|     this.store.pushPayload('pki/config/cluster', { | ||||
|       modelName: 'pki/config/cluster', | ||||
|       id: this.backend, | ||||
|     }); | ||||
|     this.store.pushPayload('pki/config/crl', { | ||||
|       modelName: 'pki/config/crl', | ||||
|       id: this.backend, | ||||
|       auto_rebuild: false, | ||||
|       auto_rebuild_grace_period: '12h', | ||||
| @@ -38,19 +42,31 @@ module('Integration | Component | page/pki-configuration-edit', function (hooks) | ||||
|       ocsp_disable: false, | ||||
|       ocsp_expiry: '12h', | ||||
|     }); | ||||
|     this.store.pushPayload('pki/urls', { | ||||
|       modelName: 'pki/urls', | ||||
|     this.store.pushPayload('pki/config/urls', { | ||||
|       modelName: 'pki/config/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); | ||||
|     this.cluster = this.store.peekRecord('pki/config/cluster', this.backend); | ||||
|     this.crl = this.store.peekRecord('pki/config/crl', this.backend); | ||||
|     this.urls = this.store.peekRecord('pki/config/urls', this.backend); | ||||
|   }); | ||||
|  | ||||
|   test('it renders with config data and updates config', async function (assert) { | ||||
|     assert.expect(27); | ||||
|     assert.expect(28); | ||||
|     this.server.post(`/${this.backend}/config/cluster`, (schema, req) => { | ||||
|       assert.ok(true, 'request made to save cluster config'); | ||||
|       assert.propEqual( | ||||
|         JSON.parse(req.requestBody), | ||||
|         { | ||||
|           path: 'https://pr-a.vault.example.com/v1/ns1/pki-root', | ||||
|           aia_path: 'http://another-path.com', | ||||
|         }, | ||||
|         'it updates config model attributes' | ||||
|       ); | ||||
|     }); | ||||
|     this.server.post(`/${this.backend}/config/crl`, (schema, req) => { | ||||
|       assert.ok(true, 'request made to save crl config'); | ||||
|       assert.propEqual( | ||||
| @@ -83,6 +99,7 @@ module('Integration | Component | page/pki-configuration-edit', function (hooks) | ||||
|     await render( | ||||
|       hbs` | ||||
|       <Page::PkiConfigurationEdit | ||||
|         @cluster={{this.cluster}} | ||||
|         @urls={{this.urls}} | ||||
|         @crl={{this.crl}} | ||||
|         @backend={{this.backend}} | ||||
| @@ -91,6 +108,7 @@ module('Integration | Component | page/pki-configuration-edit', function (hooks) | ||||
|       this.context | ||||
|     ); | ||||
|  | ||||
|     assert.dom(SELECTORS.configEditSection).exists('renders config section'); | ||||
|     assert.dom(SELECTORS.urlsEditSection).exists('renders urls section'); | ||||
|     assert.dom(SELECTORS.crlEditSection).exists('renders crl section'); | ||||
|     assert.dom(SELECTORS.cancelButton).exists(); | ||||
| @@ -101,6 +119,8 @@ module('Integration | Component | page/pki-configuration-edit', function (hooks) | ||||
|     assert.dom(SELECTORS.urlFieldInput('crlDistributionPoints')).hasValue('some-crl-distribution.com'); | ||||
|     assert.dom(SELECTORS.urlFieldInput('ocspServers')).hasValue('ocsp-stuff.com'); | ||||
|  | ||||
|     await fillIn(SELECTORS.configInput('path'), 'https://pr-a.vault.example.com/v1/ns1/pki-root'); | ||||
|     await fillIn(SELECTORS.configInput('aiaPath'), 'http://another-path.com'); | ||||
|     await fillIn(SELECTORS.urlFieldInput('issuingCertificates'), 'update-hashicorp.com'); | ||||
|     await fillIn(SELECTORS.urlFieldInput('crlDistributionPoints'), 'test-crl.com'); | ||||
|     await fillIn(SELECTORS.urlFieldInput('ocspServers'), 'ocsp.com'); | ||||
|   | ||||
| @@ -25,7 +25,7 @@ module('Integration | Component | page/pki-configure-create', function (hooks) { | ||||
|       { label: 'configure' }, | ||||
|     ]; | ||||
|     this.config = this.store.createRecord('pki/action'); | ||||
|     this.urls = this.store.createRecord('pki/urls'); | ||||
|     this.urls = this.store.createRecord('pki/config/urls'); | ||||
|   }); | ||||
|  | ||||
|   test('it renders', async function (assert) { | ||||
|   | ||||
| @@ -23,7 +23,7 @@ module('Integration | Component | pki-generate-root', function (hooks) { | ||||
|     this.store = this.owner.lookup('service:store'); | ||||
|     this.secretMountPath = this.owner.lookup('service:secret-mount-path'); | ||||
|     this.secretMountPath.currentPath = 'pki-test'; | ||||
|     this.urls = this.store.createRecord('pki/urls', { id: 'pki-test' }); | ||||
|     this.urls = this.store.createRecord('pki/config/urls', { id: 'pki-test' }); | ||||
|     this.model = this.store.createRecord('pki/action'); | ||||
|     this.onSave = Sinon.spy(); | ||||
|     this.onCancel = Sinon.spy(); | ||||
|   | ||||
							
								
								
									
										68
									
								
								ui/tests/unit/adapters/pki/config-test.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								ui/tests/unit/adapters/pki/config-test.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | ||||
| /** | ||||
|  * 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/config', function (hooks) { | ||||
|   setupTest(hooks); | ||||
|   setupMirage(hooks); | ||||
|  | ||||
|   hooks.beforeEach(async function () { | ||||
|     this.store = this.owner.lookup('service:store'); | ||||
|     this.backend = 'pki-engine'; | ||||
|   }); | ||||
|  | ||||
|   const testHelper = (test) => { | ||||
|     test('it should make request to correct endpoint on update', async function (assert) { | ||||
|       assert.expect(1); | ||||
|  | ||||
|       this.server.post(`/${this.backend}/config/${this.endpoint}`, () => { | ||||
|         assert.ok(true, `request made to POST config/${this.endpoint} endpoint on update`); | ||||
|       }); | ||||
|  | ||||
|       this.store.pushPayload(`pki/config/${this.endpoint}`, { | ||||
|         modelName: `pki/config/${this.endpoint}`, | ||||
|         id: this.backend, | ||||
|       }); | ||||
|  | ||||
|       const model = this.store.peekRecord(`pki/config/${this.endpoint}`, 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/${this.endpoint}`, () => { | ||||
|         assert.ok(true, `request is made to GET /config/${this.endpoint} endpoint on find`); | ||||
|         return { data: { id: this.backend } }; | ||||
|       }); | ||||
|  | ||||
|       this.store.findRecord(`pki/config/${this.endpoint}`, this.backend); | ||||
|     }); | ||||
|   }; | ||||
|  | ||||
|   module('cluster', function (hooks) { | ||||
|     hooks.beforeEach(async function () { | ||||
|       this.endpoint = 'cluster'; | ||||
|     }); | ||||
|     testHelper(test); | ||||
|   }); | ||||
|  | ||||
|   module('urls', function (hooks) { | ||||
|     hooks.beforeEach(async function () { | ||||
|       this.endpoint = 'urls'; | ||||
|     }); | ||||
|     testHelper(test); | ||||
|   }); | ||||
|  | ||||
|   module('crl', function (hooks) { | ||||
|     hooks.beforeEach(async function () { | ||||
|       this.endpoint = 'crl'; | ||||
|     }); | ||||
|     testHelper(test); | ||||
|   }); | ||||
| }); | ||||
| @@ -1,45 +0,0 @@ | ||||
| /** | ||||
|  * 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); | ||||
|   }); | ||||
| }); | ||||
| @@ -1,45 +0,0 @@ | ||||
| /** | ||||
|  * 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/urls', 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/urls`, () => { | ||||
|       assert.ok(true, 'request made to correct endpoint on update'); | ||||
|     }); | ||||
|  | ||||
|     this.store.pushPayload('pki/urls', { | ||||
|       modelName: 'pki/urls', | ||||
|       id: this.backend, | ||||
|     }); | ||||
|  | ||||
|     const model = this.store.peekRecord('pki/urls', 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/urls`, () => { | ||||
|       assert.ok(true, 'request is made to correct endpoint on find'); | ||||
|       return { data: { id: this.backend } }; | ||||
|     }); | ||||
|  | ||||
|     this.store.findRecord('pki/urls', this.backend); | ||||
|   }); | ||||
| }); | ||||
| @@ -1,7 +1,7 @@ | ||||
| import Model from '@ember-data/model'; | ||||
| import { FormField } from 'vault/app-types'; | ||||
| 
 | ||||
| export default class PkiCrlModel extends Model { | ||||
| export default class PkiConfigCrlModel extends Model { | ||||
|   autoRebuild: boolean; | ||||
|   autoRebuildGracePeriod: string; | ||||
|   enableDelta: boolean; | ||||
| @@ -1,6 +1,6 @@ | ||||
| import Model from '@ember-data/model'; | ||||
| 
 | ||||
| export default class PkiUrlsModel extends Model { | ||||
| export default class PkiConfigUrlsModel extends Model { | ||||
|   get useOpenAPI(): boolean; | ||||
|   getHelpUrl(backendPath: string): string; | ||||
|   issuingCertificates: array; | ||||
		Reference in New Issue
	
	Block a user
	 claire bontempo
					claire bontempo