Switch from node-forge to PKI.js (#13894)
* Switch parse-pki-cert from node-forge to PKI.js This replaces the implementation of parse-pki-cert to use PKI.js rather than node-forge for two reasons: - PKI.js uses Web Crypto rather than maintaining a built-in implementation of several algorithms. - node-forge presently lacks support for ECDSA and Ed25519 certificates. Related: #13680 Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com> * Add dependency on PKI.js $ yarn add -D asn1js pvutils pkijs Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com> * Remove dependency on node-forge $ yarn remove node-forge Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com> * Add changelog entry Signed-off-by: Alexander Scheel <alex.scheel@hashicorp.com>
This commit is contained in:
parent
2b3661b863
commit
dcdfaa8889
|
@ -0,0 +1,3 @@
|
|||
```release-note:improvement
|
||||
ui: Add support for ECDSA and Ed25519 certificate views
|
||||
```
|
|
@ -1,5 +1,7 @@
|
|||
import { helper } from '@ember/component/helper';
|
||||
import { pki } from 'node-forge';
|
||||
import * as asn1js from 'asn1js';
|
||||
import { fromBase64, stringToArrayBuffer } from 'pvutils';
|
||||
import { Certificate } from 'pkijs';
|
||||
|
||||
export function parsePkiCert([model]) {
|
||||
// model has to be the responseJSON from PKI serializer
|
||||
|
@ -7,18 +9,45 @@ export function parsePkiCert([model]) {
|
|||
return;
|
||||
}
|
||||
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);
|
||||
let cert_base64 = model.certificate.replace(/(-----(BEGIN|END) CERTIFICATE-----|\n)/g, '');
|
||||
let cert_der = fromBase64(cert_base64);
|
||||
let cert_asn1 = asn1js.fromBER(stringToArrayBuffer(cert_der));
|
||||
cert = new Certificate({ schema: cert_asn1.result });
|
||||
} catch (error) {
|
||||
console.log('Error parsing certificate:', error, model.certificate);
|
||||
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;
|
||||
|
||||
// We wish to get the CN element out of this certificate's subject. A
|
||||
// subject is a list of RDNs, where each RDN is a (type, value) tuple
|
||||
// and where a type is an OID. The OID for CN can be found here:
|
||||
//
|
||||
// http://oid-info.com/get/2.5.4.3
|
||||
// https://datatracker.ietf.org/doc/html/rfc5280#page-112
|
||||
//
|
||||
// Each value is then encoded as another ASN.1 object; in the case of a
|
||||
// CommonName field, this is usually a PrintableString, BMPString, or a
|
||||
// UTF8String. Regardless of encoding, it should be present in the
|
||||
// valueBlock's value field if it is renderable.
|
||||
const commonNameOID = '2.5.4.3';
|
||||
const commonNames = cert?.subject?.typesAndValues
|
||||
.filter((rdn) => rdn?.type === commonNameOID)
|
||||
.map((rdn) => rdn?.value?.valueBlock?.value);
|
||||
|
||||
// Theoretically, there might be multiple (or no) CommonNames -- but Vault
|
||||
// presently refuses to issue certificates without CommonNames in most
|
||||
// cases. For now, return the first CommonName we find. Alternatively, we
|
||||
// might update our callers to handle multiple, or join them using some
|
||||
// separator like ','.
|
||||
const commonName = commonNames ? (commonNames.length ? commonNames[0] : null) : null;
|
||||
|
||||
// Date instances are stored in the value field as the notAfter/notBefore
|
||||
// field themselves are Time values.
|
||||
const expiryDate = cert?.notAfter?.value;
|
||||
const issueDate = cert?.notBefore?.value;
|
||||
return {
|
||||
can_parse: true,
|
||||
common_name: commonName,
|
||||
|
|
|
@ -67,6 +67,7 @@
|
|||
"@icholy/duration": "^5.1.0",
|
||||
"@storybook/cli": "^6.3.10",
|
||||
"@storybook/ember-cli-storybook": "^0.4.0",
|
||||
"asn1js": "^2.2.0",
|
||||
"autosize": "^4.0.0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"babel-plugin-inline-json-import": "^0.3.2",
|
||||
|
@ -156,13 +157,14 @@
|
|||
"jsondiffpatch": "^0.4.1",
|
||||
"jsonlint": "^1.6.3",
|
||||
"loader.js": "^4.7.0",
|
||||
"node-forge": "^0.10.0",
|
||||
"node-sass": "^4.10.0",
|
||||
"normalize.css": "4.1.1",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"pkijs": "^2.2.2",
|
||||
"pretender": "^3.4.3",
|
||||
"prettier": "^2.2.1",
|
||||
"prettier-eslint-cli": "^5.0.0",
|
||||
"pvutils": "^1.0.17",
|
||||
"qunit": "^2.14.1",
|
||||
"qunit-dom": "^1.6.0",
|
||||
"route-recognizer": "^0.3.4",
|
||||
|
|
31
ui/yarn.lock
31
ui/yarn.lock
|
@ -5087,6 +5087,13 @@ asn1@~0.2.3:
|
|||
dependencies:
|
||||
safer-buffer "~2.1.0"
|
||||
|
||||
asn1js@^2.1.1, asn1js@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/asn1js/-/asn1js-2.2.0.tgz#d890fcdda86b8a005693df14a986bfb2c2069c57"
|
||||
integrity sha512-oagLNqpfNv7CvmyMoexMDNyVDSiq1rya0AEUgcLlNHdHgNl6U/hi8xY370n5y+ZIFEXOx0J4B1qF2NDjMRxklA==
|
||||
dependencies:
|
||||
pvutils latest
|
||||
|
||||
assert-never@^1.1.0, assert-never@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/assert-never/-/assert-never-1.2.1.tgz#11f0e363bf146205fb08193b5c7b90f4d1cf44fe"
|
||||
|
@ -7353,6 +7360,11 @@ bytes@3.1.0:
|
|||
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
|
||||
integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==
|
||||
|
||||
bytestreamjs@^1.0.29:
|
||||
version "1.0.29"
|
||||
resolved "https://registry.yarnpkg.com/bytestreamjs/-/bytestreamjs-1.0.29.tgz#691f8ee8e5a150c61b925993a3eec0911ed17f1d"
|
||||
integrity sha512-Mri3yqoo9YvdaSvD5OYl4Rdu9zCBJInW/Ez31sdlNY4ikMy//EvTTmidfLcs0e+NBvKVEpPzYvJAesjgMdjnZg==
|
||||
|
||||
cacache@^12.0.2:
|
||||
version "12.0.4"
|
||||
resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.4.tgz#668bcbd105aeb5f1d92fe25570ec9525c8faa40c"
|
||||
|
@ -16125,11 +16137,6 @@ node-fetch@^2.6.1:
|
|||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
|
||||
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
|
||||
|
||||
node-forge@^0.10.0:
|
||||
version "0.10.0"
|
||||
resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3"
|
||||
integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==
|
||||
|
||||
node-gyp@^3.8.0:
|
||||
version "3.8.0"
|
||||
resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.8.0.tgz#540304261c330e80d0d5edce253a68cb3964218c"
|
||||
|
@ -17142,6 +17149,15 @@ pkg-up@^2.0.0:
|
|||
dependencies:
|
||||
find-up "^2.1.0"
|
||||
|
||||
pkijs@^2.2.2:
|
||||
version "2.2.2"
|
||||
resolved "https://registry.yarnpkg.com/pkijs/-/pkijs-2.2.2.tgz#d0780379a2fb80c892c3ead4bcfb42675b67a982"
|
||||
integrity sha512-xRTEW9LgUeHBe5hRCC4EHvLbO6o3L/t8uEk8cTaSMVEjEcy2G5qJ/bY2ndvrGgZlKDThnTrM4Xlwu8Qpyr6mOg==
|
||||
dependencies:
|
||||
asn1js "^2.1.1"
|
||||
bytestreamjs "^1.0.29"
|
||||
pvutils "^1.0.17"
|
||||
|
||||
please-upgrade-node@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942"
|
||||
|
@ -17615,6 +17631,11 @@ puppeteer-core@^2.1.1:
|
|||
rimraf "^2.6.1"
|
||||
ws "^6.1.0"
|
||||
|
||||
pvutils@^1.0.17, pvutils@latest:
|
||||
version "1.0.17"
|
||||
resolved "https://registry.yarnpkg.com/pvutils/-/pvutils-1.0.17.tgz#ade3c74dfe7178944fe44806626bd2e249d996bf"
|
||||
integrity sha512-wLHYUQxWaXVQvKnwIDWFVKDJku9XDCvyhhxoq8dc5MFdIlRenyPI9eSfEtcvgHgD7FlvCyGAlWgOzRnZD99GZQ==
|
||||
|
||||
q@^1.1.2:
|
||||
version "1.5.1"
|
||||
resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7"
|
||||
|
|
Loading…
Reference in New Issue