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/Fix node-forge EC error #13238

Merged
merged 12 commits into from
Nov 23, 2021
3 changes: 3 additions & 0 deletions changelog/13238.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:bug
ui: Fixes node-forge error when parsing EC (elliptical curve) certs
```
20 changes: 15 additions & 5 deletions ui/app/helpers/parse-pki-cert.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,24 @@ export function parsePkiCert([model]) {
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;
let cert;
// node-forge cannot parse EC (elliptical curve) certs
// set canParse to false if unable to convert a Forge cert from PEM
try {
cert = pki.certificateFromPem(model.certificate);
} catch (error) {
return {
can_parse: false,
};
}
const commonName = cert?.subject.getField('CN') ? cert.subject.getField('CN').value : null;
const expiryDate = cert?.validity.notAfter;
const issueDate = cert?.validity.notBefore;
return {
can_parse: true,
common_name: commonName,
issue_date: issueDate,
expiry_date: expiryDate,
issue_date: issueDate,
};
}

Expand Down
107 changes: 54 additions & 53 deletions ui/app/models/pki-ca-certificate.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ 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 [
Expand All @@ -28,25 +27,79 @@ export default Certificate.extend({
backend: attr('string', {
readOnly: true,
}),
canParse: attr('boolean'),
caType: attr('string', {
possibleValues: ['root', 'intermediate'],
defaultValue: 'root',
label: 'CA Type',
readOnly: true,
}),
commonName: attr('string'),
csr: attr('string', {
editType: 'textarea',
label: 'CSR',
masked: true,
}),
expiryDate: attr('string', {
label: 'Expiration date',
}),
issueDate: attr('string'),
keyBits: attr('number', {
defaultValue: 2048,
}),
keyType: attr('string', {
possibleValues: ['rsa', 'ec', 'ed25519'],
defaultValue: 'rsa',
}),
maxPathLength: attr('number', {
defaultValue: -1,
}),
organization: attr({
editType: 'stringArray',
}),
ou: attr({
label: 'OU (OrganizationalUnit)',
editType: 'stringArray',
}),
pemBundle: attr('string', {
label: 'PEM bundle',
editType: 'file',
}),
permittedDnsNames: attr('string', {
label: 'Permitted DNS domains',
}),
privateKeyFormat: attr('string', {
possibleValues: ['', 'der', 'pem', 'pkcs8'],
defaultValue: '',
}),
type: attr('string', {
possibleValues: ['internal', 'exported'],
defaultValue: 'internal',
}),
uploadPemBundle: attr('boolean', {
label: 'Upload PEM bundle',
readOnly: true,
}),

// address attrs
country: attr({
editType: 'stringArray',
}),
locality: attr({
editType: 'stringArray',
label: 'Locality/City',
}),
streetAddress: attr({
editType: 'stringArray',
}),
postalCode: attr({
editType: 'stringArray',
}),
province: attr({
editType: 'stringArray',
label: 'Province/State',
}),

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

return groups;
}),
type: attr('string', {
possibleValues: ['internal', 'exported'],
defaultValue: 'internal',
}),
ou: attr({
label: 'OU (OrganizationalUnit)',
editType: 'stringArray',
}),
organization: attr({
editType: 'stringArray',
}),
country: attr({
editType: 'stringArray',
}),
locality: attr({
editType: 'stringArray',
label: 'Locality/City',
}),
province: attr({
editType: 'stringArray',
label: 'Province/State',
}),
streetAddress: attr({
editType: 'stringArray',
}),
postalCode: attr({
editType: 'stringArray',
}),

keyType: attr('string', {
possibleValues: ['rsa', 'ec','ed25519'],
defaultValue: 'rsa',
}),
keyBits: attr('number', {
defaultValue: 2048,
}),
privateKeyFormat: attr('string', {
possibleValues: ['', 'der', 'pem', 'pkcs8'],
defaultValue: '',
}),
maxPathLength: attr('number', {
defaultValue: -1,
}),
permittedDnsNames: attr('string', {
label: 'Permitted DNS domains',
}),

csr: attr('string', {
editType: 'textarea',
label: 'CSR',
masked: true,
}),

deletePath: lazyCapabilities(apiPath`${'backend'}/root`, 'backend'),
canDeleteRoot: and('deletePath.canDelete', 'deletePath.canSudo'),
Expand Down
62 changes: 31 additions & 31 deletions ui/app/models/pki-certificate.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@ import fieldToAttrs, { expandAttributeMeta } from 'vault/utils/field-to-attrs';

export default Model.extend({
idPrefix: 'cert/',

backend: attr('string', {
readOnly: true,
}),
//the id prefixed with `cert/` so we can use it as the *secret param for the secret show route
idForNav: attr('string', {
readOnly: true,
Expand All @@ -29,55 +25,59 @@ export default Model.extend({
];
}),

commonName: attr('string'),
expiryDate: attr('string', {
label: 'Expiration date',
altNames: attr('string', {
label: 'DNS/Email Subject Alternative Names (SANs)',
}),
issueDate: attr('string'),
role: attr('object', {
backend: attr('string', {
readOnly: true,
}),
revocationTime: attr('number'),
altNames: attr('string', {
label: 'DNS/Email Subject Alternative Names (SANs)',
caChain: attr('string', {
label: 'CA chain',
masked: true,
}),
ipSans: attr('string', {
label: 'IP Subject Alternative Names (SANs)',
canParse: attr('boolean'),
certificate: attr('string', {
masked: true,
}),
otherSans: attr({
editType: 'stringArray',
label: 'Other SANs',
helpText:
'The format is the same as OpenSSL: <oid>;<type>:<value> where the only current valid type is UTF8',
commonName: attr('string'),
excludeCnFromSans: attr('boolean', {
label: 'Exclude Common Name from Subject Alternative Names (SANs)',
defaultValue: false,
}),
ttl: attr({
label: 'TTL',
editType: 'ttl',
expiryDate: attr('string', {
label: 'Expiration date',
}),
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,
ipSans: attr('string', {
label: 'IP Subject Alternative Names (SANs)',
}),
issueDate: attr('string'),
issuingCa: attr('string', {
label: 'Issuing CA',
masked: true,
}),
caChain: attr('string', {
label: 'CA chain',
masked: true,
otherSans: attr({
editType: 'stringArray',
label: 'Other SANs',
helpText:
'The format is the same as OpenSSL: <oid>;<type>:<value> where the only current valid type is UTF8',
}),
privateKey: attr('string', {
masked: true,
}),
privateKeyType: attr('string'),
revocationTime: attr('number'),
role: attr('object', {
readOnly: true,
}),
serialNumber: attr('string'),
ttl: attr({
label: 'TTL',
editType: 'ttl',
}),

fieldsToAttrs(fieldGroups) {
return fieldToAttrs(this, fieldGroups);
Expand Down
8 changes: 7 additions & 1 deletion ui/app/templates/components/pki-cert-show.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@
</h1>
</p.levelLeft>
</PageHeader>

{{#unless model.canParse}}
<AlertBanner
@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."
data-test-warning
/>
{{/unless}}
<div class="box is-fullwidth is-sideless is-paddingless is-marginless">
<MessageError @model={{model}} />
{{#each model.attrs as |attr|}}
Expand Down