initial upload
This commit is contained in:
parent
b2a512f7fe
commit
48ae5e89aa
30 changed files with 1293 additions and 0 deletions
58
functions/db.authorities.mjs
Normal file
58
functions/db.authorities.mjs
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
|
||||
import {
|
||||
JsonDB,
|
||||
Config
|
||||
} from 'node-json-db';
|
||||
|
||||
import {
|
||||
default as ValidateSchema
|
||||
} from 'validate'
|
||||
|
||||
import {
|
||||
randomBytes
|
||||
} from "crypto";
|
||||
|
||||
|
||||
var authorityDB = new JsonDB(new Config("datastore/database/authorityDB.json", true, true, '/'));
|
||||
|
||||
const authoritySchema = new ValidateSchema({
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
match: /^[a-zA-Z0-9\ \-\_]+$/,
|
||||
length: { min: 3, max: 32 },
|
||||
message: 'invalid name'
|
||||
}
|
||||
})
|
||||
|
||||
export async function saveAuthority(authorityID, authorityConfig) {
|
||||
let configErrorList = authoritySchema.validate(authorityConfig);
|
||||
|
||||
configErrorList = configErrorList.map((configError) => {
|
||||
return configError.message;
|
||||
})
|
||||
|
||||
if (configErrorList.length > 0) {
|
||||
return {
|
||||
status: "error",
|
||||
errors: configErrorList
|
||||
}
|
||||
}
|
||||
|
||||
await authorityDB.push(`/${authorityID}`, authorityConfig);
|
||||
|
||||
return {
|
||||
status: "ok"
|
||||
}
|
||||
}
|
||||
|
||||
export async function getAuthority(authorityID) {
|
||||
let AuthorityData = await authorityDB.getData(`/${authorityID}`);
|
||||
return AuthorityData;
|
||||
}
|
||||
|
||||
export async function deleteAuthority(authorityID) {
|
||||
await authorityDB.delete(`/${authorityID}`);
|
||||
}
|
||||
|
||||
saveAuthority(randomBytes(4).toString("hex"), {names: "{test}"})
|
||||
91
functions/db.certificates.mjs
Normal file
91
functions/db.certificates.mjs
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
|
||||
import {
|
||||
JsonDB,
|
||||
Config
|
||||
} from 'node-json-db';
|
||||
|
||||
import {
|
||||
default as ValidateSchema
|
||||
} from 'validate'
|
||||
|
||||
|
||||
var certificateDB = new JsonDB(new Config("datastore/database/certificates.json", true, true, '/'));
|
||||
|
||||
const certificateSchema = new ValidateSchema({
|
||||
displayName: {
|
||||
type: String,
|
||||
required: true,
|
||||
match: /^[a-zA-Z0-9\ \-\_\.]+$/,
|
||||
message: {
|
||||
type: '[displayName] must be a string.',
|
||||
required: '[displayName] is required.',
|
||||
match: '[displayName] is invalid.'
|
||||
}
|
||||
},
|
||||
certificateType: {
|
||||
type: String,
|
||||
required: true,
|
||||
enum: [
|
||||
'rootCA',
|
||||
'intermediateCA',
|
||||
'identity'
|
||||
],
|
||||
message: {
|
||||
type: '[certificateType] must be a string.',
|
||||
required: '[certificateType] is required.',
|
||||
enum: '[certificateType] must be one of [rootCA|intermediateCA|identity]'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export async function saveCertificate(sCertificateID, oCertificateData) {
|
||||
console.log("-----------------------------------------");
|
||||
let configErrorList = certificateSchema.validate(oCertificateData);
|
||||
|
||||
configErrorList = configErrorList.map((configError) => {
|
||||
return configError.message;
|
||||
})
|
||||
|
||||
console.log(configErrorList);
|
||||
|
||||
if (configErrorList.length > 0) {
|
||||
return {
|
||||
status: "error",
|
||||
errors: configErrorList
|
||||
}
|
||||
}
|
||||
|
||||
await certificateDB.push(`/${sCertificateID}`, oCertificateData);
|
||||
|
||||
console.log(oCertificateData);
|
||||
|
||||
setTimeout(() => {
|
||||
|
||||
}, 5000);
|
||||
|
||||
return {
|
||||
status: "ok"
|
||||
}
|
||||
}
|
||||
|
||||
export async function getCertificateByID(sCertificateID) {
|
||||
let oCertificateData = await certificateDB.getData(`/${sCertificateID}`);
|
||||
return oCertificateData;
|
||||
}
|
||||
|
||||
export async function getAllCertificates() {
|
||||
let aCertificateList = await certificateDB.getData(`/`);
|
||||
return aCertificateList;
|
||||
}
|
||||
|
||||
export async function getCertificatesOfType(sCertificateType) {
|
||||
let aCertificateList = await certificateDB.getData(`/`);
|
||||
aCertificateList = aCertificateList.filter((oCertificateData) => {
|
||||
return oCertificateData.certificateType == sCertificateType;
|
||||
})
|
||||
return aCertificateList;
|
||||
}
|
||||
|
||||
export async function deleteCertificate(sCertificateID) {
|
||||
await certificateDB.delete(`/${sCertificateID}`);
|
||||
}
|
||||
134
functions/db.users.mjs
Normal file
134
functions/db.users.mjs
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
|
||||
import {
|
||||
JsonDB,
|
||||
Config
|
||||
} from 'node-json-db';
|
||||
|
||||
import {
|
||||
default as ValidateSchema
|
||||
} from 'validate'
|
||||
|
||||
|
||||
var userDB = new JsonDB(new Config("datastore/database/userDB.json", true, true, '/'));
|
||||
|
||||
const userSchema = new ValidateSchema({
|
||||
username: {
|
||||
type: String,
|
||||
required: true,
|
||||
match: /^[a-zA-Z0-9\ \-\_]+$/,
|
||||
length: { min: 3, max: 32 },
|
||||
message: {
|
||||
type: '[username] must be of type String.',
|
||||
required: '[username] is required.',
|
||||
match: '[username] is invalid. Allowed characters: (a-z|A-Z|0-9| |-|_)',
|
||||
length: '[username] must consist of 3 to 32 characters.'
|
||||
}
|
||||
},
|
||||
firstName: {
|
||||
type: String,
|
||||
required: true,
|
||||
match: /^[a-zA-Z0-9\ \-\_]+$/,
|
||||
length: { min: 1, max: 32 },
|
||||
message: {
|
||||
type: '[firstName] must be of type String.',
|
||||
required: '[firstName] is required.',
|
||||
match: '[firstName] is invalid. Allowed characters: (a-z|A-Z|0-9| |-|_)',
|
||||
length: '[firstName] must consist of 1 to 32 characters.'
|
||||
}
|
||||
},
|
||||
lastName: {
|
||||
type: String,
|
||||
required: true,
|
||||
match: /^[a-zA-Z0-9\ \-\_]+$/,
|
||||
length: { min: 1, max: 32 },
|
||||
message: {
|
||||
type: '[lastName] must be of type String.',
|
||||
required: '[lastName] is required.',
|
||||
match: '[lastName] is invalid. Allowed characters: (a-z|A-Z|0-9| |-|_)',
|
||||
length: '[lastName] must consist of 1 to 32 characters.'
|
||||
}
|
||||
},
|
||||
emailAddress: {
|
||||
type: String,
|
||||
required: true,
|
||||
match: /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/,
|
||||
message: {
|
||||
type: '[emailAddress] must be of type String.',
|
||||
required: '[emailAddress] is required.',
|
||||
match: '[emailAddress] is invalid (e.g. admin@example.com).'
|
||||
}
|
||||
},
|
||||
enabled: {
|
||||
type: String,
|
||||
required: true,
|
||||
enum: [
|
||||
'true',
|
||||
'false'
|
||||
],
|
||||
message: {
|
||||
type: '[enabled] must be of type String.',
|
||||
required: '[enabled] is required.',
|
||||
enum: '[enabled] must be one of [true|false].'
|
||||
}
|
||||
},
|
||||
permissions: {
|
||||
type: Array,
|
||||
required: true,
|
||||
elements: [{
|
||||
type: String
|
||||
}],
|
||||
message: {
|
||||
type: '[permissions] must be of type Array.',
|
||||
required: '[permissions] is required.',
|
||||
elements: '[permissions] elements must be of type String.'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
export async function saveUser(sUserID, oUserData) {
|
||||
let dataErrorList = userSchema.validate(oUserData);
|
||||
|
||||
dataErrorList = dataErrorList.map((configError) => {
|
||||
return configError.message;
|
||||
})
|
||||
|
||||
if (dataErrorList.length > 0) {
|
||||
return {
|
||||
status: "error",
|
||||
errors: dataErrorList
|
||||
}
|
||||
}
|
||||
|
||||
await userDB.push(`/${sUserID}`, oUserData);
|
||||
|
||||
return {
|
||||
status: "ok"
|
||||
}
|
||||
}
|
||||
|
||||
export async function getUser(userID) {
|
||||
let requestData = await userDB.getData(`/${userID}`);
|
||||
return {
|
||||
username: requestData.username,
|
||||
firstName: requestData.firstName,
|
||||
lastName: requestData.lastName,
|
||||
emailAddress: requestData.emailAddress
|
||||
};
|
||||
}
|
||||
|
||||
export async function getAllUsers() {
|
||||
let userList = await userDB.getData(`/`);
|
||||
return userList.map((userData) => {
|
||||
return {
|
||||
username: userData.username,
|
||||
firstName: userData.firstName,
|
||||
lastName: userData.lastName,
|
||||
emailAddress: userData.emailAddress
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export async function deleteUser(userID) {
|
||||
await userDB.delete(`/${userID}`);
|
||||
}
|
||||
84
functions/pki.createCA.mjs
Normal file
84
functions/pki.createCA.mjs
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
|
||||
import {
|
||||
default as forge
|
||||
} from "node-forge";
|
||||
|
||||
import {
|
||||
writeFileSync,
|
||||
mkdirSync
|
||||
} from "fs";
|
||||
|
||||
import {
|
||||
randomBytes
|
||||
} from "crypto";
|
||||
|
||||
// Funktion zur Generierung und Speicherung eines Root-CA-Zertifikats
|
||||
export function generateRootCA(Params) {
|
||||
const uid = randomBytes(4).toString("hex");
|
||||
// Generiere ein neues Schlüsselpaar
|
||||
const keys = forge.pki.rsa.generateKeyPair(4096);
|
||||
|
||||
// Erstelle ein neues Zertifikat
|
||||
const cert = forge.pki.createCertificate();
|
||||
cert.publicKey = keys.publicKey;
|
||||
// cert.serialNumber = '01';
|
||||
cert.validity.notBefore = new Date();
|
||||
cert.validity.notAfter = new Date();
|
||||
cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 10);
|
||||
|
||||
const attrs = [{
|
||||
name: 'commonName',
|
||||
value: 'My Root CA'
|
||||
}, {
|
||||
name: 'countryName',
|
||||
value: 'US'
|
||||
}, {
|
||||
shortName: 'ST',
|
||||
value: 'California'
|
||||
}, {
|
||||
name: 'localityName',
|
||||
value: 'San Francisco'
|
||||
}, {
|
||||
name: 'organizationName',
|
||||
value: 'My Organization'
|
||||
}, {
|
||||
shortName: 'OU',
|
||||
value: 'My Organizational Unit'
|
||||
}];
|
||||
|
||||
cert.setSubject(attrs);
|
||||
cert.setIssuer(attrs);
|
||||
|
||||
// Erweiterungen hinzufügen
|
||||
cert.setExtensions([{
|
||||
name: 'basicConstraints',
|
||||
cA: true
|
||||
}, {
|
||||
name: 'keyUsage',
|
||||
keyCertSign: true,
|
||||
cRLSign: true
|
||||
}, {
|
||||
name: 'subjectKeyIdentifier'
|
||||
}]);
|
||||
|
||||
// Zertifikat mit dem privaten Schlüssel signieren
|
||||
cert.sign(keys.privateKey, forge.md.sha256.create());
|
||||
|
||||
// Zertifikat und Schlüssel als PEM kodieren
|
||||
const pemCert = forge.pki.certificateToPem(cert);
|
||||
const pemPrivateKey = forge.pki.privateKeyToPem(keys.privateKey);
|
||||
const pemPublicKey = forge.pki.publicKeyToPem(keys.publicKey);
|
||||
|
||||
// Erstelle das RootCA Verzeichnis
|
||||
mkdirSync(`datastore/certificates/${uid}`)
|
||||
|
||||
// Zertifikat und Schlüssel in Dateien speichern
|
||||
writeFileSync(`datastore/certificates/${uid}/rootCA.crt`, pemCert);
|
||||
writeFileSync(`datastore/certificates/${uid}/rootCA.key`, pemPrivateKey);
|
||||
writeFileSync(`datastore/certificates/${uid}/rootCA.pub`, pemPublicKey);
|
||||
|
||||
console.log('Root CA-Zertifikat und Schlüssel wurden generiert und gespeichert.');
|
||||
}
|
||||
|
||||
// Funktion aufrufen, um das Root-CA-Zertifikat zu generieren
|
||||
// generateRootCA();
|
||||
77
functions/pki.createCSR.mjs
Normal file
77
functions/pki.createCSR.mjs
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
|
||||
import {
|
||||
default as forge
|
||||
} from "node-forge";
|
||||
|
||||
import {
|
||||
writeFileSync,
|
||||
mkdirSync
|
||||
} from "fs";
|
||||
|
||||
import {
|
||||
randomBytes
|
||||
} from "crypto";
|
||||
|
||||
// Funktion zur Generierung und Speicherung eines Root-CA-Zertifikats
|
||||
export function generateRootCA(Params) {
|
||||
const uid = randomBytes(4).toString("hex");
|
||||
|
||||
// Generiere ein neues Schlüsselpaar
|
||||
const keys = forge.pki.rsa.generateKeyPair(4096);
|
||||
|
||||
// Erstelle einen neuen CSR
|
||||
const csr = forge.pki.createCertificationRequest();
|
||||
|
||||
// Setze den öffentlichen Schlüssel
|
||||
csr.publicKey = keys.publicKey;
|
||||
|
||||
// Setze die CSR Attribute
|
||||
csr.setSubject([{
|
||||
name: 'commonName',
|
||||
value: 'example.com'
|
||||
}, {
|
||||
name: 'countryName',
|
||||
value: 'US'
|
||||
}, {
|
||||
shortName: 'ST',
|
||||
value: 'California'
|
||||
}, {
|
||||
name: 'localityName',
|
||||
value: 'San Francisco'
|
||||
}, {
|
||||
name: 'organizationName',
|
||||
value: 'Example, Inc.'
|
||||
}, {
|
||||
shortName: 'OU',
|
||||
value: 'IT'
|
||||
}]);
|
||||
|
||||
// Signiere die CSR mit dem privaten Schlüssel
|
||||
csr.sign(keys.privateKey, forge.md.sha256.create());
|
||||
|
||||
// Überprüfe die CSR
|
||||
const verified = csr.verify();
|
||||
if (verified) {
|
||||
console.log('CSR verification successful');
|
||||
} else {
|
||||
console.error('CSR verification failed');
|
||||
return;
|
||||
}
|
||||
|
||||
// CSR und Schlüssel als PEM kodieren
|
||||
const pemCsr = forge.pki.certificationRequestToPem(csr);
|
||||
const pemPrivateKey = forge.pki.privateKeyToPem(keys.privateKey);
|
||||
|
||||
// Erstelle das RootCA Verzeichnis
|
||||
mkdirSync(`datastore/certificates/${uid}`)
|
||||
|
||||
// Zertifikat und Schlüssel in Dateien speichern
|
||||
writeFileSync(`datastore/certificates/${uid}/rootCA.crt`, pemCert);
|
||||
writeFileSync(`datastore/certificates/${uid}/rootCA.key`, pemPrivateKey);
|
||||
writeFileSync(`datastore/certificates/${uid}/rootCA.pub`, pemPublicKey);
|
||||
|
||||
console.log('Root CA-Zertifikat und Schlüssel wurden generiert und gespeichert.');
|
||||
}
|
||||
|
||||
// Funktion aufrufen, um das Root-CA-Zertifikat zu generieren
|
||||
// generateRootCA();
|
||||
298
functions/pki.createCert.mjs
Normal file
298
functions/pki.createCert.mjs
Normal file
|
|
@ -0,0 +1,298 @@
|
|||
|
||||
import {
|
||||
default as forge
|
||||
} from "node-forge";
|
||||
|
||||
import {
|
||||
loadCertificate,
|
||||
loadPrivateKey,
|
||||
saveCertificate,
|
||||
savePrivateKey
|
||||
} from "./pki.utils.mjs";
|
||||
|
||||
import {
|
||||
saveCertificate as saveCertificateToDatabase
|
||||
} from "./db.certificates.mjs";
|
||||
|
||||
import {
|
||||
default as ValidateSchema
|
||||
} from 'validate'
|
||||
|
||||
import {
|
||||
default as parseDuration
|
||||
} from "parse-duration";
|
||||
|
||||
import {
|
||||
randomBytes
|
||||
} from "crypto";
|
||||
import { error } from "console";
|
||||
|
||||
|
||||
const CertificateSchema = new ValidateSchema({
|
||||
certType: {
|
||||
type: String,
|
||||
required: true,
|
||||
enum: [
|
||||
'rootCA',
|
||||
'intermediateCA',
|
||||
'identity'
|
||||
],
|
||||
message: {
|
||||
type: '[certType] must be a string.',
|
||||
required: '[certType] is required.',
|
||||
enum: '[certType] must be one of [authority, identity]'
|
||||
}
|
||||
},
|
||||
parent: {
|
||||
type: String,
|
||||
required: false,
|
||||
message: {
|
||||
type: '[parent] must be a string.'
|
||||
}
|
||||
},
|
||||
duration: {
|
||||
type: String,
|
||||
required: true,
|
||||
message: {
|
||||
type: '[duration] must be a string.',
|
||||
required: '[duration] is required.'
|
||||
}
|
||||
},
|
||||
commonName: {
|
||||
type: String,
|
||||
required: true,
|
||||
match: /^[a-zA-Z0-9\ \-\_\.]+$/,
|
||||
length: { min: 3, max: 32 },
|
||||
message: {
|
||||
type: '[commonName] must be a string.',
|
||||
required: '[commonName] is required.',
|
||||
match: '[commonName] is invalid.',
|
||||
length: '[commonName] is invalid.'
|
||||
}
|
||||
},
|
||||
emailAddress: {
|
||||
type: String,
|
||||
required: true,
|
||||
match: /^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$/,
|
||||
message: {
|
||||
type: '[emailAddress] must be a string.',
|
||||
required: '[emailAddress] is required.',
|
||||
match: '[emailAddress] is invalid (e.g. admin@example.com).'
|
||||
}
|
||||
},
|
||||
countryName: {
|
||||
type: String,
|
||||
required: true,
|
||||
match: /^[A-Z]{2}$/,
|
||||
message: {
|
||||
type: '[countryName] must be a string.',
|
||||
required: '[countryName] is required.',
|
||||
match: '[countryName] needs to be 2 letter code (e.g. US).'
|
||||
}
|
||||
},
|
||||
stateOrProvinceName: {
|
||||
type: String,
|
||||
required: true,
|
||||
match: /^[A-Za-z ]{3,64}$/,
|
||||
message: {
|
||||
type: '[stateOrProvinceName] must be a string.',
|
||||
required: '[stateOrProvinceName] is required.',
|
||||
match: '[stateOrProvinceName] is invalid: (A-Z|a-z| ), 3-64 characters'
|
||||
}
|
||||
},
|
||||
localityName: {
|
||||
type: String,
|
||||
required: true,
|
||||
match: /^[A-Za-z ]{3,64}$/,
|
||||
message: {
|
||||
type: '[localityName] must be a string.',
|
||||
required: '[localityName] is required.',
|
||||
match: '[localityName] is invalid: (A-Z,a-z, ), 3-64 characters'
|
||||
}
|
||||
},
|
||||
organizationName: {
|
||||
type: String,
|
||||
required: true,
|
||||
match: /^[A-Za-z\ \-\_\.]{3,64}$/,
|
||||
message: {
|
||||
type: '[organizationName] must be a string.',
|
||||
required: '[organizationName] is required.',
|
||||
match: '[organizationName] is invalid: (A-Z,a-z, ), 3-64 characters'
|
||||
}
|
||||
},
|
||||
organizationalUnitName: {
|
||||
type: String,
|
||||
required: true,
|
||||
match: /^[A-Za-z\ \-\_\.]{3,64}$/,
|
||||
message: {
|
||||
type: '[organizationalUnitName] must be a string.',
|
||||
required: '[organizationalUnitName] is required.',
|
||||
match: '[organizationalUnitName] is invalid: (A-Z,a-z, ,.,-,_), 3-64 characters'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
function generateCertificate(Params) {
|
||||
let configErrorList = CertificateSchema.validate(Params);
|
||||
|
||||
configErrorList = configErrorList.map((configError) => {
|
||||
return configError.message;
|
||||
})
|
||||
|
||||
if (configErrorList.length > 0) {
|
||||
return {
|
||||
status: "error",
|
||||
errors: configErrorList
|
||||
}
|
||||
}
|
||||
|
||||
// generate certificate id
|
||||
const certificateId = randomBytes(4).toString("hex");
|
||||
|
||||
// generate new keypair
|
||||
const {
|
||||
privateKey,
|
||||
publicKey
|
||||
} = forge.pki.rsa.generateKeyPair(4096);
|
||||
|
||||
// initialize new certificate
|
||||
const certificate = forge.pki.createCertificate();
|
||||
certificate.publicKey = publicKey;
|
||||
// cert.serialNumber = '01';
|
||||
certificate.validity.notBefore = new Date(Date.now());
|
||||
certificate.validity.notAfter = new Date(Date.now() + parseDuration(Params.duration));
|
||||
|
||||
const attrs = [{
|
||||
name: 'commonName',
|
||||
value: Params.commonName
|
||||
}, {
|
||||
name: 'countryName',
|
||||
value: Params.countryName
|
||||
}, {
|
||||
name: 'stateOrProvinceName',
|
||||
value: Params.stateOrProvinceName
|
||||
}, {
|
||||
name: 'localityName',
|
||||
value: Params.localityName
|
||||
}, {
|
||||
name: 'organizationName',
|
||||
value: Params.organizationName
|
||||
}, {
|
||||
name: 'organizationalUnitName',
|
||||
value: Params.organizationalUnitName
|
||||
}];
|
||||
|
||||
certificate.setSubject(attrs);
|
||||
certificate.setIssuer(attrs);
|
||||
|
||||
// Erweiterungen hinzufügen
|
||||
certificate.setExtensions([{
|
||||
name: 'basicConstraints',
|
||||
cA: true
|
||||
}, {
|
||||
name: 'keyUsage',
|
||||
keyCertSign: true,
|
||||
cRLSign: true
|
||||
}, {
|
||||
name: 'subjectKeyIdentifier'
|
||||
}]);
|
||||
|
||||
console.log(`new certificate with uid ${certificateId} generated`);
|
||||
|
||||
return {
|
||||
status: "ok",
|
||||
certificateId,
|
||||
certificate,
|
||||
privateKey,
|
||||
publicKey
|
||||
}
|
||||
}
|
||||
|
||||
export async function createRootCertificate(certificateParameters) {
|
||||
let oGeneratedData = generateCertificate({
|
||||
certType: 'rootCA',
|
||||
parent: null,
|
||||
duration: certificateParameters.duration,
|
||||
emailAddress: certificateParameters.emailAddress,
|
||||
commonName: certificateParameters.commonName,
|
||||
countryName: certificateParameters.countryName,
|
||||
stateOrProvinceName: certificateParameters.stateOrProvinceName,
|
||||
localityName: certificateParameters.localityName,
|
||||
organizationName: certificateParameters.organizationName,
|
||||
organizationalUnitName: certificateParameters.organizationalUnitName
|
||||
});
|
||||
|
||||
if (oGeneratedData.status != "ok") {
|
||||
return {
|
||||
status: "error",
|
||||
errors: oGeneratedData.errors
|
||||
}
|
||||
}
|
||||
|
||||
// sign the new certificate
|
||||
oGeneratedData.certificate.sign(oGeneratedData.privateKey, forge.md.sha256.create());
|
||||
|
||||
// save certificate and keys
|
||||
saveCertificate(oGeneratedData.certificate, oGeneratedData.certificateId, 'rootCA');
|
||||
savePrivateKey(oGeneratedData.privateKey, oGeneratedData.certificateId, 'rootCA');
|
||||
saveCertificateToDatabase(oGeneratedData.certificateId, {
|
||||
displayName: certificateParameters.commonName,
|
||||
certificateType: 'rootCA'
|
||||
})
|
||||
|
||||
console.log(`new rootCA certificate with uid ${oGeneratedData.certificateId} saved`);
|
||||
|
||||
return {
|
||||
status: "ok",
|
||||
certificateId: oGeneratedData.certificateId
|
||||
}
|
||||
}
|
||||
|
||||
export async function createIntermediateCertificate(oCertificateParameters, sRootCertificateId) {
|
||||
let {
|
||||
certificateId: newCertificateId,
|
||||
certificate: newCertificate,
|
||||
privateKey: newPrivateKey
|
||||
} = generateCertificate(oCertificateParameters);
|
||||
|
||||
// load certificate authority certificate and privateKey
|
||||
const rootCACertificate = loadCertificate(sRootCertificateId);
|
||||
const rootCAPrivateKey = loadPrivateKey(sRootCertificateId);
|
||||
|
||||
// set rootCA as issuer
|
||||
newCertificate.setIssuer(rootCACertificate.subject.attributes);
|
||||
// sign certificate with root certificate
|
||||
newCertificate.sign(rootCAPrivateKey, forge.md.sha256.create());
|
||||
|
||||
// save certificate and keys
|
||||
saveCertificate(newCertificate, newCertificateId, 'intermediateCA');
|
||||
savePrivateKey(newPrivateKey, newCertificateId, 'intermediateCA');
|
||||
saveCertificateToDatabase(newCertificateId, {
|
||||
displayName: Params.commonName,
|
||||
certificateType: 'intermediateCA'
|
||||
})
|
||||
|
||||
console.log(`new intermediateCA certificate with uid ${newCertificateId} saved`);
|
||||
}
|
||||
|
||||
export async function createIdentityCertificate(Params) {
|
||||
let {
|
||||
certificateId,
|
||||
certificate,
|
||||
privateKey,
|
||||
publicKey
|
||||
} = generateCertificate(Params)
|
||||
}
|
||||
|
||||
// Funktion aufrufen, um das Root-CA-Zertifikat zu generieren
|
||||
console.log((await createRootCertificate({
|
||||
duration: '10y',
|
||||
emailAddress: 'kai@waggeling.net',
|
||||
commonName: 'waggeling.net rootCA',
|
||||
countryName: 'DE',
|
||||
stateOrProvinceName: 'Sachsen',
|
||||
localityName: 'Leipzig',
|
||||
organizationName: 'WCloud',
|
||||
organizationalUnitName: 'TEst'
|
||||
})));
|
||||
51
functions/pki.utils.mjs
Normal file
51
functions/pki.utils.mjs
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
|
||||
import {
|
||||
default as forge
|
||||
} from "node-forge";
|
||||
|
||||
import {
|
||||
readFileSync,
|
||||
writeFileSync,
|
||||
mkdirSync
|
||||
} from "fs";
|
||||
|
||||
|
||||
export function loadCertificate(sCertID) {
|
||||
return forge.pki.certificateFromPem(
|
||||
readFileSync(`datastore/certificates/${sCertID}/certificate.pem`, 'utf8')
|
||||
);
|
||||
}
|
||||
|
||||
export function loadPrivateKey(sCertID) {
|
||||
return forge.pki.privateKeyFromPem(
|
||||
readFileSync(`datastore/certificates/${sCertID}/privateKey.pem`, 'utf8')
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
export function saveCertificate(iCertificate, sCertID, sCertType) {
|
||||
// encode certificates as PEM
|
||||
const certificate = forge.pki.certificateToPem(iCertificate);
|
||||
|
||||
// create certificate directory
|
||||
mkdirSync(`datastore/certificates/`, { recursive: true });
|
||||
|
||||
// write certificate to file
|
||||
writeFileSync(`datastore/certificates/${sCertID}.crt`, certificate);
|
||||
}
|
||||
|
||||
export function savePrivateKey(iPrivateKey, sCertID) {
|
||||
// encode keys as PEM
|
||||
const privateKey = forge.pki.privateKeyToPem(iPrivateKey);
|
||||
|
||||
// create key directory
|
||||
mkdirSync(`datastore/keys/`, { recursive: true });
|
||||
|
||||
// write keys to file
|
||||
writeFileSync(`datastore/keys/${sCertID}.key`, privateKey);
|
||||
}
|
||||
|
||||
|
||||
export function generatePublicKeyFromPrivateKey(iPrivateKey) {
|
||||
return forge.pki.rsa.setPublicKey(iPrivateKey.n, iPrivateKey.e);
|
||||
}
|
||||
92
functions/structure.mjs
Normal file
92
functions/structure.mjs
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
|
||||
import {
|
||||
Op
|
||||
} from "sequelize";
|
||||
|
||||
import {
|
||||
ElementTable,
|
||||
AttributeTable
|
||||
} from "../database/models/structure.mjs";
|
||||
|
||||
|
||||
export async function CreateDirectory(parentId, name)
|
||||
{
|
||||
let ParentDirectory = await ElementTable.findByPk(parentId);
|
||||
|
||||
if (ParentDirectory == null) {
|
||||
var NewDirectory = await ElementTable.create({
|
||||
type: 'directory'
|
||||
});
|
||||
} else {
|
||||
var NewDirectory = await ParentDirectory.createChild({
|
||||
type: 'directory'
|
||||
});
|
||||
}
|
||||
|
||||
await NewDirectory.createAttribute({
|
||||
version: NewDirectory.latestVersion,
|
||||
contentType: 'name',
|
||||
contentValue: name
|
||||
})
|
||||
|
||||
return NewDirectory;
|
||||
}
|
||||
|
||||
export async function GetDirectory(directoryId, version = null)
|
||||
{
|
||||
let Directory = await ElementTable.findByPk(directoryId);
|
||||
|
||||
if (Directory == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (version == null) {
|
||||
version = Directory.latestVersion
|
||||
}
|
||||
|
||||
let Attributes = await Directory.getAttribute()
|
||||
|
||||
var Result = {
|
||||
id: Directory.id,
|
||||
version
|
||||
}
|
||||
|
||||
Attributes.forEach((Attribute) => {
|
||||
Result[Attribute.contentType] = Attribute.contentValue
|
||||
});
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
export async function GetDirectories(parentId = null)
|
||||
{
|
||||
let Directories = await ElementTable.findAll({
|
||||
where: {
|
||||
[Op.and]: {
|
||||
type: 'directory',
|
||||
parentId: parentId
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Directories = Directories.map(async (Directory) => {
|
||||
let Attributes = await Directory.getAttribute()
|
||||
|
||||
var Result = {
|
||||
id: Directory.id,
|
||||
version: Directory.latestVersion
|
||||
}
|
||||
|
||||
console.log(Attributes);
|
||||
|
||||
Attributes.forEach((Attribute) => {
|
||||
Result[Attribute.contentType] = Attribute.contentValue
|
||||
});
|
||||
|
||||
return Result;
|
||||
})
|
||||
|
||||
await Promise.all(Directories);
|
||||
|
||||
return Directories;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue