2021-10-04 21:31:36 +00:00
|
|
|
import { helper } from '@ember/component/helper';
|
2022-02-04 17:52:28 +00:00
|
|
|
import * as asn1js from 'asn1js';
|
|
|
|
import { fromBase64, stringToArrayBuffer } from 'pvutils';
|
|
|
|
import { Certificate } from 'pkijs';
|
2021-10-04 21:31:36 +00:00
|
|
|
|
|
|
|
export function parsePkiCert([model]) {
|
|
|
|
// model has to be the responseJSON from PKI serializer
|
2022-02-05 02:26:29 +00:00
|
|
|
// return if no certificate or if the "certificate" is actually a CRL
|
|
|
|
if (!model.certificate || model.certificate.includes('BEGIN X509 CRL')) {
|
2021-10-04 21:31:36 +00:00
|
|
|
return;
|
|
|
|
}
|
2021-11-23 18:51:02 +00:00
|
|
|
let cert;
|
|
|
|
try {
|
2022-02-04 17:52:28 +00:00
|
|
|
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 });
|
2021-11-23 18:51:02 +00:00
|
|
|
} catch (error) {
|
2022-10-18 15:46:02 +00:00
|
|
|
console.debug('DEBUG: Parsing Certificate', error); // eslint-disable-line
|
2021-11-23 18:51:02 +00:00
|
|
|
return {
|
|
|
|
can_parse: false,
|
|
|
|
};
|
|
|
|
}
|
2022-02-04 17:52:28 +00:00
|
|
|
|
|
|
|
// 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;
|
2021-10-04 21:31:36 +00:00
|
|
|
return {
|
2021-11-23 18:51:02 +00:00
|
|
|
can_parse: true,
|
2021-10-04 21:31:36 +00:00
|
|
|
common_name: commonName,
|
|
|
|
expiry_date: expiryDate,
|
2021-11-23 18:51:02 +00:00
|
|
|
issue_date: issueDate,
|
2021-10-04 21:31:36 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
export default helper(parsePkiCert);
|