mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-31 02:28:09 +00:00 
			
		
		
		
	UI/Hide empty masked PKI row values (#14400)
* fix empty masked inputs displaying * Revert "fix empty masked inputs displaying" This reverts commit 8b297df7cf971bce32d73c07fea2b1b8112c2f4b. * fix empty masked inputs displaying * fix info banner conditional * add test coverage * adds changelog * fixes tests * change other canParse conditional
This commit is contained in:
		
							
								
								
									
										3
									
								
								changelog/14400.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								changelog/14400.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | |||||||
|  | ```release-note:bug | ||||||
|  | ui: Fixes displaying empty masked values in PKI engine | ||||||
|  | ``` | ||||||
| @@ -8,7 +8,7 @@ | |||||||
|     {{/if}} |     {{/if}} | ||||||
|   </h2> |   </h2> | ||||||
|   {{#if (or this.model.certificate this.model.csr)}} |   {{#if (or this.model.certificate this.model.csr)}} | ||||||
|     {{#if (not (eq this.model.canParse true))}} |     {{#if (eq this.model.canParse false)}} | ||||||
|       <AlertBanner |       <AlertBanner | ||||||
|         @type="info" |         @type="info" | ||||||
|         @message="There was an error parsing the certificate's metadata. As a result, Vault cannot display the issue and expiration dates. This will not interfere with the certificate's functionality." |         @message="There was an error parsing the certificate's metadata. As a result, Vault cannot display the issue and expiration dates. This will not interfere with the certificate's functionality." | ||||||
| @@ -16,7 +16,7 @@ | |||||||
|       /> |       /> | ||||||
|     {{/if}} |     {{/if}} | ||||||
|     {{#each this.model.attrs as |attr|}} |     {{#each this.model.attrs as |attr|}} | ||||||
|       {{#if attr.options.masked}} |       {{#if (and attr.options.masked (get this.model attr.name))}} | ||||||
|         <InfoTableRow |         <InfoTableRow | ||||||
|           data-test-table-row |           data-test-table-row | ||||||
|           @label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}} |           @label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}} | ||||||
| @@ -108,7 +108,7 @@ | |||||||
|       data-test-warning |       data-test-warning | ||||||
|     /> |     /> | ||||||
|     {{#each this.model.attrs as |attr|}} |     {{#each this.model.attrs as |attr|}} | ||||||
|       {{#if attr.options.masked}} |       {{#if (and attr.options.masked (get this.model attr.name))}} | ||||||
|         <InfoTableRow |         <InfoTableRow | ||||||
|           data-test-table-row={{this.value}} |           data-test-table-row={{this.value}} | ||||||
|           @label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}} |           @label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}} | ||||||
|   | |||||||
| @@ -75,12 +75,6 @@ | |||||||
|             @label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}} |             @label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}} | ||||||
|             @value={{date-format (get this.model attr.name) "MMM dd, yyyy hh:mm:ss a" isFormatted=true}} |             @value={{date-format (get this.model attr.name) "MMM dd, yyyy hh:mm:ss a" isFormatted=true}} | ||||||
|           /> |           /> | ||||||
|         {{else if (and (get this.model attr.name) (eq attr.name "revocationTime"))}} |  | ||||||
|           <InfoTableRow |  | ||||||
|             data-test-table-row |  | ||||||
|             @label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}} |  | ||||||
|             @value={{date-format (get this.model attr.name) "MMM dd, yyyy hh:mm:ss a"}} |  | ||||||
|           /> |  | ||||||
|         {{else}} |         {{else}} | ||||||
|           <InfoTableRow |           <InfoTableRow | ||||||
|             @label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}} |             @label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}} | ||||||
|   | |||||||
| @@ -14,7 +14,7 @@ | |||||||
|     </h1> |     </h1> | ||||||
|   </p.levelLeft> |   </p.levelLeft> | ||||||
| </PageHeader> | </PageHeader> | ||||||
| {{#if (not (eq this.model.canParse true))}} | {{#if (eq this.model.canParse false)}} | ||||||
|   <AlertBanner |   <AlertBanner | ||||||
|     @type="info" |     @type="info" | ||||||
|     @message="There was an error parsing the certificate's metadata. As a result, Vault cannot display the common name or the issue and expiration dates. This will not interfere with the certificate's functionality." |     @message="There was an error parsing the certificate's metadata. As a result, Vault cannot display the common name or the issue and expiration dates. This will not interfere with the certificate's functionality." | ||||||
| @@ -31,7 +31,7 @@ | |||||||
|         @value={{stringify (get this.model attr.name)}} |         @value={{stringify (get this.model attr.name)}} | ||||||
|       /> |       /> | ||||||
|     {{else}} |     {{else}} | ||||||
|       {{#if attr.options.masked}} |       {{#if (and attr.options.masked (get this.model attr.name))}} | ||||||
|         <InfoTableRow |         <InfoTableRow | ||||||
|           data-test-table-row |           data-test-table-row | ||||||
|           @label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}} |           @label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}} | ||||||
| @@ -45,7 +45,7 @@ | |||||||
|           @label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}} |           @label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}} | ||||||
|           @value={{date-format (get this.model attr.name) "MMM dd, yyyy hh:mm:ss a" isFormatted=true}} |           @value={{date-format (get this.model attr.name) "MMM dd, yyyy hh:mm:ss a" isFormatted=true}} | ||||||
|         /> |         /> | ||||||
|       {{else if (and (get this.model attr.name) (eq attr.name "revocationTime"))}} |       {{else if (eq attr.name "revocationTime")}} | ||||||
|         <InfoTableRow |         <InfoTableRow | ||||||
|           data-test-table-row |           data-test-table-row | ||||||
|           @label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}} |           @label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}} | ||||||
|   | |||||||
| @@ -90,7 +90,9 @@ module('Acceptance | clients current', function (hooks) { | |||||||
|     // Filter by namespace |     // Filter by namespace | ||||||
|     await clickTrigger(); |     await clickTrigger(); | ||||||
|     await searchSelect.options.objectAt(0).click(); |     await searchSelect.options.objectAt(0).click(); | ||||||
|     await settled(); |     await waitUntil(() => { | ||||||
|  |       return find('[data-test-horizontal-bar-chart]'); | ||||||
|  |     }); | ||||||
|     assert.dom('[data-test-stat-text="total-clients"] .stat-value').hasText('15'); |     assert.dom('[data-test-stat-text="total-clients"] .stat-value').hasText('15'); | ||||||
|     assert.dom('[data-test-stat-text="entity-clients"] .stat-value').hasText('5'); |     assert.dom('[data-test-stat-text="entity-clients"] .stat-value').hasText('5'); | ||||||
|     assert.dom('[data-test-stat-text="non-entity-clients"] .stat-value').hasText('10'); |     assert.dom('[data-test-stat-text="non-entity-clients"] .stat-value').hasText('10'); | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| import { currentRouteName, settled, click } from '@ember/test-helpers'; | import { currentRouteName, settled } from '@ember/test-helpers'; | ||||||
| import { module, test } from 'qunit'; | import { module, test } from 'qunit'; | ||||||
| import { setupApplicationTest } from 'ember-qunit'; | import { setupApplicationTest } from 'ember-qunit'; | ||||||
| import editPage from 'vault/tests/pages/secrets/backend/pki/edit-role'; | import editPage from 'vault/tests/pages/secrets/backend/pki/edit-role'; | ||||||
| @@ -7,6 +7,7 @@ import generatePage from 'vault/tests/pages/secrets/backend/pki/generate-cert'; | |||||||
| import configPage from 'vault/tests/pages/settings/configure-secret-backends/pki/section-cert'; | import configPage from 'vault/tests/pages/settings/configure-secret-backends/pki/section-cert'; | ||||||
| import enablePage from 'vault/tests/pages/settings/mount-secret-backend'; | import enablePage from 'vault/tests/pages/settings/mount-secret-backend'; | ||||||
| import authPage from 'vault/tests/pages/auth'; | import authPage from 'vault/tests/pages/auth'; | ||||||
|  | import { SELECTORS } from 'vault/tests/helpers/pki'; | ||||||
|  |  | ||||||
| module('Acceptance | secrets/pki/list?tab=certs', function (hooks) { | module('Acceptance | secrets/pki/list?tab=certs', function (hooks) { | ||||||
|   setupApplicationTest(hooks); |   setupApplicationTest(hooks); | ||||||
| @@ -55,11 +56,15 @@ elRplAzrMF4= | |||||||
|     await settled(); |     await settled(); | ||||||
|     await generatePage.issueCert('foo'); |     await generatePage.issueCert('foo'); | ||||||
|     await settled(); |     await settled(); | ||||||
|     assert.dom('.masked-font').exists({ count: 3 }, 'renders 3 masked rows'); |     assert.dom(SELECTORS.certificate).exists('displays masked certificate'); | ||||||
|     let firstUnMaskButton = document.querySelectorAll('.masked-input-toggle')[0]; |     assert.dom(SELECTORS.commonName).exists('displays common name'); | ||||||
|     await click(firstUnMaskButton); |     assert.dom(SELECTORS.issueDate).exists('displays issue date'); | ||||||
|     assert.dom('.masked-value').hasTextContaining('-----BEGIN CERTIFICATE-----'); |     assert.dom(SELECTORS.expiryDate).exists('displays expiration date'); | ||||||
|     await settled(); |     assert.dom(SELECTORS.issuingCa).exists('displays masked issuing CA'); | ||||||
|  |     assert.dom(SELECTORS.privateKey).exists('displays masked private key'); | ||||||
|  |     assert.dom(SELECTORS.serialNumber).exists('displays serial number'); | ||||||
|  |     assert.dom(SELECTORS.caChain).doesNotExist('does not display empty masked CA chain'); | ||||||
|  |  | ||||||
|     await generatePage.back(); |     await generatePage.back(); | ||||||
|     await settled(); |     await settled(); | ||||||
|     assert.notOk(generatePage.commonNameValue, 'the form is cleared'); |     assert.notOk(generatePage.commonNameValue, 'the form is cleared'); | ||||||
| @@ -70,9 +75,10 @@ elRplAzrMF4= | |||||||
|     await settled(); |     await settled(); | ||||||
|     await generatePage.sign('common', CSR); |     await generatePage.sign('common', CSR); | ||||||
|     await settled(); |     await settled(); | ||||||
|     let firstUnMaskButton = document.querySelectorAll('.masked-input-toggle')[0]; |     assert.ok(SELECTORS.certificate, 'displays masked certificate'); | ||||||
|     await click(firstUnMaskButton); |     assert.ok(SELECTORS.commonName, 'displays common name'); | ||||||
|     assert.dom('.masked-value').hasTextContaining('-----BEGIN CERTIFICATE-----'); |     assert.ok(SELECTORS.issuingCa, 'displays masked issuing CA'); | ||||||
|  |     assert.ok(SELECTORS.serialNumber, 'displays serial number'); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   test('it views a cert', async function (assert) { |   test('it views a cert', async function (assert) { | ||||||
| @@ -82,12 +88,17 @@ elRplAzrMF4= | |||||||
|     await listPage.visitRoot({ backend: path, tab: 'certs' }); |     await listPage.visitRoot({ backend: path, tab: 'certs' }); | ||||||
|     await settled(); |     await settled(); | ||||||
|     assert.ok(listPage.secrets.length > 0, 'lists certs'); |     assert.ok(listPage.secrets.length > 0, 'lists certs'); | ||||||
|  |  | ||||||
|     await listPage.secrets.objectAt(0).click(); |     await listPage.secrets.objectAt(0).click(); | ||||||
|     await settled(); |     await settled(); | ||||||
|     assert.equal(currentRouteName(), 'vault.cluster.secrets.backend.show', 'navigates to the show page'); |     assert.equal(currentRouteName(), 'vault.cluster.secrets.backend.show', 'navigates to the show page'); | ||||||
|     let firstUnMaskButton = document.querySelectorAll('.masked-input-toggle')[0]; |     assert.dom(SELECTORS.certificate).exists('displays masked certificate'); | ||||||
|     await click(firstUnMaskButton); |     assert.dom(SELECTORS.commonName).exists('displays common name'); | ||||||
|     assert.dom('.masked-value').hasTextContaining('-----BEGIN CERTIFICATE-----'); |     assert.dom(SELECTORS.issueDate).exists('displays issue date'); | ||||||
|  |     assert.dom(SELECTORS.expiryDate).exists('displays expiration date'); | ||||||
|  |     assert.dom(SELECTORS.serialNumber).exists('displays serial number'); | ||||||
|  |     assert.dom(SELECTORS.revocationTime).doesNotExist('does not display revocation time of 0'); | ||||||
|  |     assert.dom(SELECTORS.issuingCa).doesNotExist('does not display empty issuing CA'); | ||||||
|  |     assert.dom(SELECTORS.caChain).doesNotExist('does not display empty CA chain'); | ||||||
|  |     assert.dom(SELECTORS.privateKey).doesNotExist('does not display empty private key'); | ||||||
|   }); |   }); | ||||||
| }); | }); | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ import { currentRouteName, settled, click } from '@ember/test-helpers'; | |||||||
| import { module, test } from 'qunit'; | import { module, test } from 'qunit'; | ||||||
| import { setupApplicationTest } from 'ember-qunit'; | import { setupApplicationTest } from 'ember-qunit'; | ||||||
| import page from 'vault/tests/pages/settings/configure-secret-backends/pki/section-cert'; | import page from 'vault/tests/pages/settings/configure-secret-backends/pki/section-cert'; | ||||||
|  | import { SELECTORS } from 'vault/tests/helpers/pki'; | ||||||
| import authPage from 'vault/tests/pages/auth'; | import authPage from 'vault/tests/pages/auth'; | ||||||
| import enablePage from 'vault/tests/pages/settings/mount-secret-backend'; | import enablePage from 'vault/tests/pages/settings/mount-secret-backend'; | ||||||
|  |  | ||||||
| @@ -77,13 +78,15 @@ BXUV2Uwtxf+QCphnlht9muX2fsLIzDJea0JipWj1uf2H8OZsjE8= | |||||||
|     await page.form.generateCA(); |     await page.form.generateCA(); | ||||||
|     await settled(); |     await settled(); | ||||||
|  |  | ||||||
|     assert.ok(page.form.commonNameIsPresent, 'the common name displays'); |     assert.dom(SELECTORS.certificate).exists('certificate is present and masked'); | ||||||
|     assert.ok(page.form.issueDateIsPresent, 'the issue date displays'); |     assert.dom(SELECTORS.commonName).exists('displays common name'); | ||||||
|     assert.ok(page.form.expiryDateIsPresent, 'the expiration date displays'); |     assert.dom(SELECTORS.issueDate).exists('displays issue date'); | ||||||
|     assert |     assert.dom(SELECTORS.expiryDate).exists('displays expiration date'); | ||||||
|       .dom('[data-test-value-div="Certificate"] [data-test-masked-input]') |     assert.dom(SELECTORS.issuingCa).exists('displays masked issuing CA'); | ||||||
|       .exists('certificate is present'); |     assert.dom(SELECTORS.serialNumber).exists('displays serial number'); | ||||||
|  |     assert.dom(SELECTORS.csr).doesNotExist('does not display empty CSR'); | ||||||
|  |     assert.dom(SELECTORS.caChain).doesNotExist('does not display empty CA chain'); | ||||||
|  |     assert.dom(SELECTORS.privateKey).doesNotExist('does not display empty private key'); | ||||||
|     await page.form.back(); |     await page.form.back(); | ||||||
|     await page.form.generateCA(); |     await page.form.generateCA(); | ||||||
|     await settled(); |     await settled(); | ||||||
| @@ -126,6 +129,8 @@ BXUV2Uwtxf+QCphnlht9muX2fsLIzDJea0JipWj1uf2H8OZsjE8= | |||||||
|     await settled(); |     await settled(); | ||||||
|     await page.form.csrField(csrVal).submit(); |     await page.form.csrField(csrVal).submit(); | ||||||
|     await settled(); |     await settled(); | ||||||
|  |     assert.dom(SELECTORS.caChain).doesNotExist('does not display empty CA chain'); | ||||||
|  |     assert.dom(SELECTORS.privateKey).doesNotExist('does not display empty private key'); | ||||||
|     await click('.masked-input-toggle'); |     await click('.masked-input-toggle'); | ||||||
|     intermediateCert = document.querySelector('[data-test-masked-input]').innerText; |     intermediateCert = document.querySelector('[data-test-masked-input]').innerText; | ||||||
|     await page.form.back(); |     await page.form.back(); | ||||||
|   | |||||||
							
								
								
									
										12
									
								
								ui/tests/helpers/pki.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								ui/tests/helpers/pki.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | export const SELECTORS = { | ||||||
|  |   caChain: '[data-test-value-div="CA chain"] [data-test-masked-input]', | ||||||
|  |   certificate: '[data-test-value-div="Certificate"] [data-test-masked-input]', | ||||||
|  |   commonName: '[data-test-row-value="Common name"]', | ||||||
|  |   csr: '[data-test-value-div="CSR"] [data-test-masked-input]', | ||||||
|  |   expiryDate: '[data-test-row-value="Expiration date"]', | ||||||
|  |   issueDate: '[data-test-row-value="Issue date"]', | ||||||
|  |   issuingCa: '[data-test-value-div="Issuing CA"] [data-test-masked-input]', | ||||||
|  |   privateKey: '[data-test-value-div="Private key"] [data-test-masked-input]', | ||||||
|  |   revocationTime: '[data-test-row-value="Revocation time"]', | ||||||
|  |   serialNumber: '[data-test-row-value="Serial number"]', | ||||||
|  | }; | ||||||
| @@ -27,15 +27,11 @@ export default { | |||||||
|   csr: text('[data-test-row-value="CSR"]', { normalize: false }), |   csr: text('[data-test-row-value="CSR"]', { normalize: false }), | ||||||
|   csrField: fillable('[data-test-input="csr"]'), |   csrField: fillable('[data-test-input="csr"]'), | ||||||
|   certificate: text('[data-test-row-value="Certificate"]', { normalize: false }), |   certificate: text('[data-test-row-value="Certificate"]', { normalize: false }), | ||||||
|   commonNameIsPresent: isPresent('[data-test-row-value="Common name"]'), |  | ||||||
|   uploadCert: clickable('[data-test-input="uploadPemBundle"]'), |   uploadCert: clickable('[data-test-input="uploadPemBundle"]'), | ||||||
|   enterCertAsText: clickable('[data-test-text-toggle]'), |   enterCertAsText: clickable('[data-test-text-toggle]'), | ||||||
|   pemBundle: fillable('[data-test-text-file-textarea]'), |   pemBundle: fillable('[data-test-text-file-textarea]'), | ||||||
|   commonName: fillable('[data-test-input="commonName"]'), |   commonName: fillable('[data-test-input="commonName"]'), | ||||||
|  |  | ||||||
|   issueDateIsPresent: text('[data-test-row-value="Issue date"]'), |  | ||||||
|   expiryDateIsPresent: text('[data-test-row-value="Expiration date"]'), |  | ||||||
|  |  | ||||||
|   async generateCA(commonName = 'PKI CA', type = 'root') { |   async generateCA(commonName = 'PKI CA', type = 'root') { | ||||||
|     if (type === 'intermediate') { |     if (type === 'intermediate') { | ||||||
|       return await this.replaceCA().commonName(commonName).caType('intermediate').submit(); |       return await this.replaceCA().commonName(commonName).caType('intermediate').submit(); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 claire bontempo
					claire bontempo