dashboard/models/secret.js

169 lines
4.1 KiB
JavaScript

import r from 'jsrsasign';
import { KUBERNETES } from '@/config/labels-annotations';
import { base64Decode } from '@/utils/crypto';
import { removeObjects } from '@/utils/array';
export const OPAQUE = 'Opaque';
export const SERVICE_ACCT = 'kubernetes.io/service-account-token';
export const DOCKER = 'kubernetes.io/dockercfg';
export const DOCKER_JSON = 'kubernetes.io/dockerconfigjson';
export const BASIC = 'kubernetes.io/basic-auth';
export const SSH = 'kubernetes.io/ssh-auth';
export const TLS = 'kubernetes.io/tls';
export const BOOTSTRAP = 'bootstrap.kubernetes.io/token';
export const ISTIO_TLS = 'istio.io/key-and-cert';
const DISPLAY_TYPES = {
[OPAQUE]: 'Opaque',
[SERVICE_ACCT]: 'Service Acct Token',
[DOCKER]: 'Registry',
[DOCKER_JSON]: 'Registry',
[BASIC]: 'Basic Auth',
[SSH]: 'SSH',
[TLS]: 'Certificate',
[BOOTSTRAP]: 'Bootstrap Token',
[ISTIO_TLS]: 'Certificate (Istio)',
};
export default {
canUpdate() {
return this.hasLink('update') && this.$rootGetters['type-map/isEditable'](this.type) && this.secretType !== SERVICE_ACCT;
},
keysDisplay() {
const keys = [
...Object.keys(this.data || []),
...Object.keys(this.binaryData || [])
];
if ( !keys.length ) {
return '(none)';
}
// if ( keys.length >= 4 ) {
// return `${keys[0]}, ${keys[1]}, ${keys[2]} and ${keys.length - 3} more`;
// }
return keys.join(', ');
},
// decode some secret data to show in list view
dataPreview() {
if (this._type === DOCKER_JSON) {
const encodedJSON = this.data['.dockerconfigjson'];
if (encodedJSON) {
const decodedJSON = base64Decode(encodedJSON);
try {
const auths = JSON.parse(decodedJSON).auths;
const out = [];
for (const domain in auths) {
out.push(domain);
}
return out.join(', ');
} catch (e) {
return decodedJSON;
}
}
} else if (this._type === TLS) {
return this.certInfo || this.keysDisplay;
} else {
return this.keysDisplay;
}
},
secretType() {
return this._type;
},
typeDisplay() {
const mapped = DISPLAY_TYPES[this._type];
if ( mapped ) {
return mapped;
}
return (this._type || '').replace(/^kubernetes.io\//, '');
},
tableTypeDisplay() {
if (this._type === SERVICE_ACCT) {
return { typeDisplay: this.typeDisplay, serviceAccountID: this.serviceAccountID };
} else {
return this.typeDisplay;
}
},
serviceAccountID() {
if (this.secretType === SERVICE_ACCT) {
const name = this.metadata.annotations[KUBERNETES.SERVICE_ACCOUNT_NAME];
const namespace = this.namespace;
let fqid = name;
if (namespace ) {
fqid = `${ namespace }/${ name }`;
}
return fqid;
}
return null;
},
// parse TLS certs and return issuer, notAfter, cn, sans
certInfo() {
const pem = base64Decode(this.data['tls.crt']);
let issuer, notAfter, cn, sans, x;
if (pem) {
try {
x = new r.X509();
x.readCertPEM(pem);
const issuerString = x.getIssuerString();
issuer = issuerString.slice(issuerString.indexOf('CN=') + 3);
notAfter = r.zulutodate(x.getNotAfter());
const cnString = x.getSubjectString();
cn = cnString.slice(cnString.indexOf('CN=') + 3);
} catch {
return null;
}
try {
sans = x.getExtSubjectAltName();
} catch (e) {
sans = [];
}
return {
issuer, notAfter, cn, sans
};
}
},
// use for + n more name display
unrepeatedSans() {
if (this._type === TLS ) {
const commonBases = this.certInfo.sans.filter(name => name.indexOf('*.') === 0 || name.indexOf('www.') === 0).map(name => name.substr(name.indexOf('.')));
const displaySans = removeObjects(this.certInfo.sans, commonBases);
return displaySans;
}
},
timeTilExpiration() {
if (this._type === TLS) {
const expiration = this.certInfo.notAfter;
const timeThen = expiration.valueOf();
const timeNow = Date.now();
return timeThen - timeNow;
}
},
};