Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UI/ PKI UI Redesign #12541

Merged
merged 41 commits into from Oct 4, 2021
Merged
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
f9b5e69
adds padding
hellobontempo Aug 2, 2021
692a2e1
Merge branch 'main' into ui/info-table-row-component
hellobontempo Sep 8, 2021
7167835
WIP// add attributes
hellobontempo Sep 13, 2021
25f5d86
Merge branch 'main' into ui/pki-cert-parse
hellobontempo Sep 13, 2021
308857a
Merge branch 'ui/info-table-row-component' into ui/pki-cert-parse
hellobontempo Sep 13, 2021
2e3506d
installs node-forge
hellobontempo Sep 13, 2021
870609b
correctly displays and formats cert metadata
hellobontempo Sep 13, 2021
64aa1cc
removes labels
hellobontempo Sep 14, 2021
5e63907
adds comment
hellobontempo Sep 14, 2021
bfdedb5
updates comment:
hellobontempo Sep 14, 2021
4c607bf
uses helper in hbs file
hellobontempo Sep 14, 2021
cf30e61
removes date-fns from serializer, reorders attrs
hellobontempo Sep 15, 2021
698387e
adds named arg to helper
hellobontempo Sep 15, 2021
af10d26
adds helper and implements try/catch so template won't error
hellobontempo Sep 15, 2021
f18486d
fixes helper
hellobontempo Sep 15, 2021
2ee0978
removes method from pki serializer
hellobontempo Sep 15, 2021
8e9f906
creates pki-ca serializer
hellobontempo Sep 15, 2021
fff701f
:
hellobontempo Sep 15, 2021
4dd59e2
adds attrs to pki-ca
hellobontempo Sep 16, 2021
3f0799a
removes changes from pki-ca
hellobontempo Sep 16, 2021
1890a46
adds todos
hellobontempo Sep 16, 2021
39fb068
fixes catch and helper erroring
hellobontempo Sep 17, 2021
3246355
removes try
hellobontempo Sep 17, 2021
7a9918f
pki-ca-cert displays common name, issue & expiry date
hellobontempo Sep 17, 2021
6776902
adds comment
hellobontempo Sep 17, 2021
d236f43
removes pki-ca serializer, tests still broken
hellobontempo Sep 17, 2021
96102c4
clean up
hellobontempo Sep 20, 2021
48d29ca
removes comments
hellobontempo Sep 20, 2021
d61da35
WIP// edits tests, need to fix parsing if setSignedIntermediate
hellobontempo Sep 20, 2021
12ceb9b
adds changelog
hellobontempo Sep 21, 2021
fdd48c6
updates hbs
hellobontempo Sep 21, 2021
370ab1e
fixes tests
hellobontempo Sep 21, 2021
89908ba
adds settled()
hellobontempo Sep 21, 2021
a9b73d8
change error to return
hellobontempo Sep 27, 2021
b0396f3
alphabetizes some attrs
hellobontempo Sep 27, 2021
6cf6704
alphabetizes some attrs
hellobontempo Sep 27, 2021
075e979
cleanup, remove comments, etc
hellobontempo Sep 27, 2021
dfc351d
adds test for date helper
hellobontempo Sep 27, 2021
98a6e96
Merge branch 'main' into ui/pki-cert-parse
hellobontempo Sep 27, 2021
6077f21
removes log
hellobontempo Sep 28, 2021
79dc35e
test
hellobontempo Sep 28, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions changelog/12541.txt
@@ -0,0 +1,3 @@
```release-note:improvement
ui: parse and display pki cert metadata
```
10 changes: 9 additions & 1 deletion ui/app/adapters/pki-ca-certificate.js
@@ -1,3 +1,4 @@
import { parsePkiCert } from '../helpers/parse-pki-cert';
import ApplicationAdapter from './application';

export default ApplicationAdapter.extend({
Expand Down Expand Up @@ -41,7 +42,14 @@ export default ApplicationAdapter.extend({
}
response.id = snapshot.id;
response.modelName = type.modelName;
store.pushPayload(type.modelName, response);
// only parse if certificate is attached to response
if (response.data && response.data.certificate) {
const caCertMetadata = parsePkiCert([response.data]);
const transformedResponse = { ...response, ...caCertMetadata };
store.pushPayload(type.modelName, transformedResponse);
} else {
store.pushPayload(type.modelName, response);
}
});
},

Expand Down
20 changes: 20 additions & 0 deletions ui/app/helpers/parse-pki-cert.js
@@ -0,0 +1,20 @@
import { helper } from '@ember/component/helper';
import { pki } from 'node-forge';

export function parsePkiCert([model]) {
// model has to be the responseJSON from PKI serializer
if (!model.certificate) {
return;
}
const cert = pki.certificateFromPem(model.certificate);
const commonName = cert.subject.getField('CN') ? cert.subject.getField('CN').value : null;
const issueDate = cert.validity.notBefore;
const expiryDate = cert.validity.notAfter;
return {
common_name: commonName,
issue_date: issueDate,
expiry_date: expiryDate,
};
}

export default helper(parsePkiCert);
28 changes: 16 additions & 12 deletions ui/app/models/pki-ca-certificate.js
Expand Up @@ -4,43 +4,49 @@ import { computed } from '@ember/object';
import Certificate from './pki-certificate';
import lazyCapabilities, { apiPath } from 'vault/macros/lazy-capabilities';

// TODO: alphabetize attrs
export default Certificate.extend({
DISPLAY_FIELDS: computed(function() {
return [
'csr',
'certificate',
'expiration',
'commonName',
'issueDate',
'expiryDate',
'issuingCa',
'caChain',
'privateKey',
'privateKeyType',
'serialNumber',
];
}),
addBasicConstraints: attr('boolean', {
label: 'Add a Basic Constraints extension with CA: true',
helpText:
'Only needed as a workaround in some compatibility scenarios with Active Directory Certificate Services',
}),
backend: attr('string', {
readOnly: true,
}),

caType: attr('string', {
possibleValues: ['root', 'intermediate'],
defaultValue: 'root',
label: 'CA Type',
readOnly: true,
}),
uploadPemBundle: attr('boolean', {
label: 'Upload PEM bundle',
readOnly: true,
commonName: attr('string'),
expiryDate: attr('string', {
hellobontempo marked this conversation as resolved.
Show resolved Hide resolved
label: 'Expiration date',
}),
issueDate: attr('string'),
pemBundle: attr('string', {
label: 'PEM bundle',
editType: 'file',
}),
addBasicConstraints: attr('boolean', {
label: 'Add a Basic Constraints extension with CA: true',
helpText:
'Only needed as a workaround in some compatibility scenarios with Active Directory Certificate Services',
uploadPemBundle: attr('boolean', {
label: 'Upload PEM bundle',
readOnly: true,
}),

fieldDefinition: computed('caType', 'uploadPemBundle', function() {
const type = this.caType;
const isUpload = this.uploadPemBundle;
Expand Down Expand Up @@ -92,7 +98,6 @@ export default Certificate.extend({

return groups;
}),

type: attr('string', {
possibleValues: ['internal', 'exported'],
defaultValue: 'internal',
Expand Down Expand Up @@ -145,7 +150,6 @@ export default Certificate.extend({
label: 'CSR',
masked: true,
}),
expiration: attr(),

deletePath: lazyCapabilities(apiPath`${'backend'}/root`, 'backend'),
canDeleteRoot: and('deletePath.canDelete', 'deletePath.canSudo'),
Expand Down
21 changes: 10 additions & 11 deletions ui/app/models/pki-certificate.js
Expand Up @@ -17,27 +17,30 @@ export default Model.extend({
DISPLAY_FIELDS: computed(function() {
return [
'certificate',
'commonName',
'issuingCa',
'caChain',
'privateKey',
'privateKeyType',
'serialNumber',
'revocationTime',
'issueDate',
'expiryDate',
'serialNumber',
];
}),

commonName: attr('string'),
expiryDate: attr('string', {
label: 'Expiration date',
}),
issueDate: attr('string'),
role: attr('object', {
readOnly: true,
}),

revocationTime: attr('number'),
commonName: attr('string', {
label: 'Common Name',
}),

altNames: attr('string', {
label: 'DNS/Email Subject Alternative Names (SANs)',
}),

ipSans: attr('string', {
label: 'IP Subject Alternative Names (SANs)',
}),
Expand All @@ -47,22 +50,18 @@ export default Model.extend({
helpText:
'The format is the same as OpenSSL: <oid>;<type>:<value> where the only current valid type is UTF8',
}),

ttl: attr({
label: 'TTL',
editType: 'ttl',
}),

format: attr('string', {
defaultValue: 'pem',
possibleValues: ['pem', 'der', 'pem_bundle'],
}),

excludeCnFromSans: attr('boolean', {
label: 'Exclude Common Name from Subject Alternative Names (SANs)',
defaultValue: false,
}),

certificate: attr('string', {
masked: true,
}),
Expand Down
10 changes: 9 additions & 1 deletion ui/app/serializers/pki-certificate.js
Expand Up @@ -2,6 +2,7 @@ import RESTSerializer from '@ember-data/serializer/rest';
import { isNone, isBlank } from '@ember/utils';
import { assign } from '@ember/polyfills';
import { decamelize } from '@ember/string';
import { parsePkiCert } from '../helpers/parse-pki-cert';

export default RESTSerializer.extend({
keyForAttribute: function(attr) {
Expand Down Expand Up @@ -41,7 +42,14 @@ export default RESTSerializer.extend({
normalizeResponse(store, primaryModelClass, payload, id, requestType) {
const responseJSON = this.normalizeItems(payload);
const { modelName } = primaryModelClass;
let transformedPayload = { [modelName]: responseJSON };
let transformedPayload, certMetadata;
// hits cert/list endpoint first which returns an array, only want to parse if response is not an array
if (!Array.isArray(responseJSON)) {
certMetadata = parsePkiCert([responseJSON]);
transformedPayload = { [modelName]: { ...certMetadata, ...responseJSON } };
} else {
transformedPayload = { [modelName]: responseJSON };
}
return this._super(store, primaryModelClass, transformedPayload, id, requestType);
},

Expand Down
2 changes: 2 additions & 0 deletions ui/app/styles/components/info-table-row.scss
Expand Up @@ -23,6 +23,8 @@
.column {
align-self: center;
padding-left: 0px;
padding: $spacing-m;

&.info-table-row-edit {
padding-bottom: 0.3rem;
padding-top: 0.3rem;
Expand Down
35 changes: 21 additions & 14 deletions ui/app/templates/components/config-pki-ca.hbs
Expand Up @@ -10,25 +10,23 @@
{{#if (or model.certificate model.csr)}}
{{#each model.attrs as |attr|}}
{{#if attr.options.masked}}
<InfoTableRow @label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}} @value={{get model attr.name}}>
<InfoTableRow data-test-table-row
@label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}}
@value={{get model attr.name}}>
<MaskedInput
@value={{get model attr.name}}
@displayOnly={{true}}
@allowCopy={{true}}
/>
</InfoTableRow>
{{else if (eq attr.name "expiration")}}
{{info-table-row
data-test-table-row
label=(capitalize (or attr.options.label (humanize (dasherize attr.name))))
value=(date-format (get model attr.name) 'MMM dd, yyyy hh:mm:ss a')
}}
{{else if (and (get model attr.name) (or (eq attr.name "issueDate") (eq attr.name "expiryDate")))}}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only pass to date-format helper if get model attr.name returns a value AND attr.name equals issueDate or expiryDate

<InfoTableRow data-test-table-row={{value}}
@label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}}
@value={{date-format (get model attr.name) 'MMM dd, yyyy hh:mm:ss a' isFormatted=true}}/>
{{else}}
{{info-table-row
data-test-table-row
label=(capitalize (or attr.options.label (humanize (dasherize attr.name))))
value=(get model attr.name)
}}
<InfoTableRow data-test-table-row={{value}}
hellobontempo marked this conversation as resolved.
Show resolved Hide resolved
@label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}}
@value={{get model attr.name}}/>
{{/if}}
{{/each}}
<div class="field is-grouped box is-fullwidth is-bottomless">
Expand Down Expand Up @@ -94,15 +92,24 @@
/>
{{#each model.attrs as |attr|}}
{{#if attr.options.masked}}
<InfoTableRow @label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}} @value={{get model attr.name}}>
<InfoTableRow
data-test-table-row={{value}}
@label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}}
@value={{get model attr.name}}>
<MaskedInput
@value={{get model attr.name}}
@displayOnly={{true}}
@allowCopy={{true}}
/>
</InfoTableRow>
{{else if (and (get model attr.name) (or (eq attr.name "issueDate") (eq attr.name "expiryDate")))}}
<InfoTableRow data-test-table-row={{value}}
@label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}}
@value={{date-format (get model attr.name) 'MMM dd, yyyy hh:mm:ss a' isFormatted=true}}/>
{{else}}
{{info-table-row data-test-table-row label=(capitalize (or attr.options.label (humanize (dasherize attr.name)))) value=(get model attr.name)}}
<InfoTableRow data-test-table-row={{value}}
@label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}}
@value={{get model attr.name}}/>
{{/if}}
{{/each}}
<div class="field is-grouped box is-fullwidth is-bottomless">
Expand Down
16 changes: 13 additions & 3 deletions ui/app/templates/components/pki-cert-show.hbs
Expand Up @@ -13,18 +13,28 @@
<MessageError @model={{model}} />
{{#each model.attrs as |attr|}}
{{#if (eq attr.type "object")}}
<InfoTableRow @label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}} @value={{stringify (get model attr.name)}} />
<InfoTableRow data-test-table-row
@label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}}
@value={{stringify (get model attr.name)}} />
{{else}}
{{#if attr.options.masked}}
<InfoTableRow @label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}} @value={{get model attr.name}}>
<InfoTableRow data-test-table-row
@label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}}
@value={{get model attr.name}}>
<MaskedInput
@value={{get model attr.name}}
@displayOnly={{true}}
@allowCopy={{true}}
/>
</InfoTableRow>
{{else if (and (get model attr.name) (or (eq attr.name "issueDate") (eq attr.name "expiryDate")))}}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only pass to date-format helper if get model attr.name returns a value AND attr.name equals issueDate or expiryDate

<InfoTableRow data-test-table-row
@label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}}
@value={{date-format (get model attr.name) 'MMM dd, yyyy hh:mm:ss a' isFormatted=true}} />
{{else}}
<InfoTableRow @label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}} @value={{get model attr.name}} />
<InfoTableRow data-test-table-row
@label={{capitalize (or attr.options.label (humanize (dasherize attr.name)))}}
@value={{get model attr.name}} />
{{/if}}
{{/if}}
{{/each}}
Expand Down
5 changes: 4 additions & 1 deletion ui/lib/core/addon/helpers/date-format.js
@@ -1,8 +1,11 @@
import { helper } from '@ember/component/helper';
import { format, parseISO } from 'date-fns';

export function dateFormat([date, style]) {
export function dateFormat([date, style], { isFormatted = false }) {
// see format breaking in upgrade to date-fns 2.x https://github.com/date-fns/date-fns/blob/master/CHANGELOG.md#changed-5
if (isFormatted) {
hellobontempo marked this conversation as resolved.
Show resolved Hide resolved
return format(new Date(date), style);
}
let number = typeof date === 'string' ? parseISO(date) : date;
if (!number) {
return;
Expand Down