fix: encrypt decrypt

This commit is contained in:
Andras Bacsai
2023-07-25 10:48:31 +02:00
parent 4c51bffc7b
commit 338cbf62a1
3 changed files with 173 additions and 138 deletions

View File

@@ -105,12 +105,8 @@ async function reEncryptSecrets() {
if (version) { if (version) {
backupfile = `/app/db/prod.db_${version}_${date}`; backupfile = `/app/db/prod.db_${version}_${date}`;
} }
console.log(`Backup database to ${backupfile}.`);
await execaCommand(`cp /app/db/prod.db ${backupfile}`, { shell: true });
await execaCommand('env | grep COOLIFY > .env', { shell: true });
const secretOld = process.env['COOLIFY_SECRET_KEY']; const secretOld = process.env['COOLIFY_SECRET_KEY'];
let secretNew = process.env['COOLIFY_SECRET_KEY_BETTER']; let secretNew = process.env['COOLIFY_SECRET_KEY_BETTER'];
if (!secretNew) { if (!secretNew) {
console.log('No COOLIFY_SECRET_KEY_BETTER found... Generating new one...'); console.log('No COOLIFY_SECRET_KEY_BETTER found... Generating new one...');
const { stdout: newKey } = await execaCommand( const { stdout: newKey } = await execaCommand(
@@ -120,6 +116,8 @@ async function reEncryptSecrets() {
secretNew = newKey; secretNew = newKey;
} }
if (secretOld !== secretNew) { if (secretOld !== secretNew) {
console.log(`Backup database to ${backupfile}.`);
await execaCommand(`cp /app/db/prod.db ${backupfile}`, { shell: true });
console.log( console.log(
'Secrets (COOLIFY_SECRET_KEY & COOLIFY_SECRET_KEY_BETTER) are different, so re-encrypting everything...' 'Secrets (COOLIFY_SECRET_KEY & COOLIFY_SECRET_KEY_BETTER) are different, so re-encrypting everything...'
); );
@@ -132,170 +130,209 @@ async function reEncryptSecrets() {
await execaCommand(`echo "COOLIFY_SECRET_KEY_OLD_${date}=${secretOld}" >> .env`, { await execaCommand(`echo "COOLIFY_SECRET_KEY_OLD_${date}=${secretOld}" >> .env`, {
shell: true shell: true
}); });
const transactions = []; const transactions = [];
const secrets = await prisma.secret.findMany(); const secrets = await prisma.secret.findMany();
if (secrets.length > 0) { if (secrets.length > 0) {
for (const secret of secrets) { for (const secret of secrets) {
const value = decrypt(secret.value, secretOld); try {
const newValue = encrypt(value, secretNew); const value = decrypt(secret.value, secretOld);
transactions.push( const newValue = encrypt(value, secretNew);
prisma.secret.update({ transactions.push(
where: { id: secret.id }, prisma.secret.update({
data: { value: newValue } where: { id: secret.id },
}) data: { value: newValue }
); })
);
} catch (e) {
console.log(e);
}
} }
} }
const serviceSecrets = await prisma.serviceSecret.findMany(); const serviceSecrets = await prisma.serviceSecret.findMany();
if (serviceSecrets.length > 0) { if (serviceSecrets.length > 0) {
for (const secret of serviceSecrets) { for (const secret of serviceSecrets) {
const value = decrypt(secret.value, secretOld); try {
const newValue = encrypt(value, secretNew); const value = decrypt(secret.value, secretOld);
transactions.push( const newValue = encrypt(value, secretNew);
prisma.serviceSecret.update({ transactions.push(
where: { id: secret.id }, prisma.serviceSecret.update({
data: { value: newValue } where: { id: secret.id },
}) data: { value: newValue }
); })
);
} catch (e) {
console.log(e);
}
} }
} }
const gitlabApps = await prisma.gitlabApp.findMany(); const gitlabApps = await prisma.gitlabApp.findMany();
if (gitlabApps.length > 0) { if (gitlabApps.length > 0) {
for (const gitlabApp of gitlabApps) { for (const gitlabApp of gitlabApps) {
const value = decrypt(gitlabApp.privateSshKey, secretOld); try {
const newValue = encrypt(value, secretNew); const value = decrypt(gitlabApp.privateSshKey, secretOld);
const appSecret = decrypt(gitlabApp.appSecret, secretOld); const newValue = encrypt(value, secretNew);
const newAppSecret = encrypt(appSecret, secretNew); const appSecret = decrypt(gitlabApp.appSecret, secretOld);
transactions.push( const newAppSecret = encrypt(appSecret, secretNew);
prisma.gitlabApp.update({ transactions.push(
where: { id: gitlabApp.id }, prisma.gitlabApp.update({
data: { privateSshKey: newValue, appSecret: newAppSecret } where: { id: gitlabApp.id },
}) data: { privateSshKey: newValue, appSecret: newAppSecret }
); })
);
} catch (e) {
console.log(e);
}
} }
} }
const githubApps = await prisma.githubApp.findMany(); const githubApps = await prisma.githubApp.findMany();
if (githubApps.length > 0) { if (githubApps.length > 0) {
for (const githubApp of githubApps) { for (const githubApp of githubApps) {
const clientSecret = decrypt(githubApp.clientSecret, secretOld); try {
const newClientSecret = encrypt(clientSecret, secretNew); const clientSecret = decrypt(githubApp.clientSecret, secretOld);
const webhookSecret = decrypt(githubApp.webhookSecret, secretOld); const newClientSecret = encrypt(clientSecret, secretNew);
const newWebhookSecret = encrypt(webhookSecret, secretNew); const webhookSecret = decrypt(githubApp.webhookSecret, secretOld);
const privateKey = decrypt(githubApp.privateKey, secretOld); const newWebhookSecret = encrypt(webhookSecret, secretNew);
const newPrivateKey = encrypt(privateKey, secretNew); const privateKey = decrypt(githubApp.privateKey, secretOld);
const newPrivateKey = encrypt(privateKey, secretNew);
transactions.push( transactions.push(
prisma.githubApp.update({ prisma.githubApp.update({
where: { id: githubApp.id }, where: { id: githubApp.id },
data: { data: {
clientSecret: newClientSecret, clientSecret: newClientSecret,
webhookSecret: newWebhookSecret, webhookSecret: newWebhookSecret,
privateKey: newPrivateKey privateKey: newPrivateKey
} }
}) })
); );
} catch (e) {
console.log(e);
}
} }
} }
const databases = await prisma.database.findMany(); const databases = await prisma.database.findMany();
if (databases.length > 0) { if (databases.length > 0) {
for (const database of databases) { for (const database of databases) {
const dbUserPassword = decrypt(database.dbUserPassword, secretOld); try {
const newDbUserPassword = encrypt(dbUserPassword, secretNew); const dbUserPassword = decrypt(database.dbUserPassword, secretOld);
const rootUserPassword = decrypt(database.rootUserPassword, secretOld); const newDbUserPassword = encrypt(dbUserPassword, secretNew);
const newRootUserPassword = encrypt(rootUserPassword, secretNew); const rootUserPassword = decrypt(database.rootUserPassword, secretOld);
transactions.push( const newRootUserPassword = encrypt(rootUserPassword, secretNew);
prisma.database.update({ transactions.push(
where: { id: database.id }, prisma.database.update({
data: { where: { id: database.id },
dbUserPassword: newDbUserPassword, data: {
rootUserPassword: newRootUserPassword dbUserPassword: newDbUserPassword,
} rootUserPassword: newRootUserPassword
}) }
); })
);
} catch (e) {
console.log(e);
}
} }
} }
const databaseSecrets = await prisma.databaseSecret.findMany(); const databaseSecrets = await prisma.databaseSecret.findMany();
if (databaseSecrets.length > 0) { if (databaseSecrets.length > 0) {
for (const databaseSecret of databaseSecrets) { for (const databaseSecret of databaseSecrets) {
const value = decrypt(databaseSecret.value, secretOld); try {
const newValue = encrypt(value, secretNew); const value = decrypt(databaseSecret.value, secretOld);
transactions.push( const newValue = encrypt(value, secretNew);
prisma.databaseSecret.update({ transactions.push(
where: { id: databaseSecret.id }, prisma.databaseSecret.update({
data: { value: newValue } where: { id: databaseSecret.id },
}) data: { value: newValue }
); })
);
} catch (e) {
console.log(e);
}
} }
} }
const wordpresses = await prisma.wordpress.findMany(); const wordpresses = await prisma.wordpress.findMany();
if (wordpresses.length > 0) { if (wordpresses.length > 0) {
for (const wordpress of wordpresses) { for (const wordpress of wordpresses) {
const value = decrypt(wordpress.ftpHostKey, secretOld); try {
const newValue = encrypt(value, secretNew); const value = decrypt(wordpress.ftpHostKey, secretOld);
const ftpHostKeyPrivate = decrypt(wordpress.ftpHostKeyPrivate, secretOld); const newValue = encrypt(value, secretNew);
const newFtpHostKeyPrivate = encrypt(ftpHostKeyPrivate, secretNew); const ftpHostKeyPrivate = decrypt(wordpress.ftpHostKeyPrivate, secretOld);
let newFtpPassword = undefined; const newFtpHostKeyPrivate = encrypt(ftpHostKeyPrivate, secretNew);
if (wordpress.ftpPassword != null) { let newFtpPassword = undefined;
const ftpPassword = decrypt(wordpress.ftpPassword, secretOld); if (wordpress.ftpPassword != null) {
newFtpPassword = encrypt(ftpPassword, secretNew); const ftpPassword = decrypt(wordpress.ftpPassword, secretOld);
} newFtpPassword = encrypt(ftpPassword, secretNew);
}
transactions.push( transactions.push(
prisma.wordpress.update({ prisma.wordpress.update({
where: { id: wordpress.id }, where: { id: wordpress.id },
data: { data: {
ftpHostKey: newValue, ftpHostKey: newValue,
ftpHostKeyPrivate: newFtpHostKeyPrivate, ftpHostKeyPrivate: newFtpHostKeyPrivate,
ftpPassword: newFtpPassword ftpPassword: newFtpPassword
} }
}) })
); );
} catch (e) {
console.log(e);
}
} }
} }
const sshKeys = await prisma.sshKey.findMany(); const sshKeys = await prisma.sshKey.findMany();
if (sshKeys.length > 0) { if (sshKeys.length > 0) {
for (const key of sshKeys) { for (const key of sshKeys) {
const value = decrypt(key.privateKey, secretOld); try {
const newValue = encrypt(value, secretNew); const value = decrypt(key.privateKey, secretOld);
transactions.push( const newValue = encrypt(value, secretNew);
prisma.sshKey.update({ transactions.push(
where: { id: key.id }, prisma.sshKey.update({
data: { where: { id: key.id },
privateKey: newValue data: {
} privateKey: newValue
}) }
); })
);
} catch (e) {
console.log(e);
}
} }
} }
const dockerRegistries = await prisma.dockerRegistry.findMany(); const dockerRegistries = await prisma.dockerRegistry.findMany();
if (dockerRegistries.length > 0) { if (dockerRegistries.length > 0) {
for (const registry of dockerRegistries) { for (const registry of dockerRegistries) {
const value = decrypt(registry.password, secretOld); try {
const newValue = encrypt(value, secretNew); const value = decrypt(registry.password, secretOld);
transactions.push( const newValue = encrypt(value, secretNew);
prisma.dockerRegistry.update({ transactions.push(
where: { id: registry.id }, prisma.dockerRegistry.update({
data: { where: { id: registry.id },
password: newValue data: {
} password: newValue
}) }
); })
);
} catch (e) {
console.log(e);
}
} }
} }
const certificates = await prisma.certificate.findMany(); const certificates = await prisma.certificate.findMany();
if (certificates.length > 0) { if (certificates.length > 0) {
for (const certificate of certificates) { for (const certificate of certificates) {
const value = decrypt(certificate.key, secretOld); try {
const newValue = encrypt(value, secretNew); const value = decrypt(certificate.key, secretOld);
transactions.push( const newValue = encrypt(value, secretNew);
prisma.certificate.update({ transactions.push(
where: { id: certificate.id }, prisma.certificate.update({
data: { where: { id: certificate.id },
key: newValue data: {
} key: newValue
}) }
); })
);
} catch (e) {
console.log(e);
}
} }
} }
await prisma.$transaction(transactions); await prisma.$transaction(transactions);
@@ -317,29 +354,27 @@ const encrypt = (text, secret) => {
}; };
const decrypt = (hashString, secret) => { const decrypt = (hashString, secret) => {
if (hashString && secret) { if (hashString && secret) {
try { const hash = JSON.parse(hashString);
const hash = JSON.parse(hashString); const decipher = crypto.createDecipheriv(algorithm, secret, Buffer.from(hash.iv, 'hex'));
const decipher = crypto.createDecipheriv(algorithm, secret, Buffer.from(hash.iv, 'hex')); const decrpyted = Buffer.concat([
const decrpyted = Buffer.concat([ decipher.update(Buffer.from(hash.content, 'hex')),
decipher.update(Buffer.from(hash.content, 'hex')), decipher.final()
decipher.final() ]);
]); if (/<2F>/.test(decrpyted.toString())) {
return decrpyted.toString(); throw new Error('Invalid secret. Skipping...');
} catch (error) {
console.log({ decryptionError: error.message });
return hashString;
} }
return decrpyted.toString();
} }
}; };
// main() main()
// .catch((e) => { .catch((e) => {
// console.error(e); console.error(e);
// process.exit(1); process.exit(1);
// }) })
// .finally(async () => { .finally(async () => {
// await prisma.$disconnect(); await prisma.$disconnect();
// }); });
reEncryptSecrets() reEncryptSecrets()
.catch((e) => { .catch((e) => {
console.error(e); console.error(e);

View File

@@ -412,7 +412,7 @@ async function autoUpdater() {
await executeCommand({ command: `docker pull ${image}` }); await executeCommand({ command: `docker pull ${image}` });
} }
await executeCommand({ shell: true, command: `ls .env || env | grep COOLIFY > .env` }); await executeCommand({ shell: true, command: `ls .env || env | grep "^COOLIFY" | sort > .env` });
await executeCommand({ await executeCommand({
command: `sed -i '/COOLIFY_AUTO_UPDATE=/cCOOLIFY_AUTO_UPDATE=${isAutoUpdateEnabled}' .env` command: `sed -i '/COOLIFY_AUTO_UPDATE=/cCOOLIFY_AUTO_UPDATE=${isAutoUpdateEnabled}' .env`
}); });

View File

@@ -162,7 +162,7 @@ export async function update(request: FastifyRequest<Update>) {
await executeCommand({ command: `docker pull ${image}` }); await executeCommand({ command: `docker pull ${image}` });
} }
await executeCommand({ shell: true, command: `ls .env || env | grep COOLIFY > .env` }); await executeCommand({ shell: true, command: `ls .env || env | grep "^COOLIFY" | sort > .env` });
await executeCommand({ await executeCommand({
command: `sed -i '/COOLIFY_AUTO_UPDATE=/cCOOLIFY_AUTO_UPDATE=${isAutoUpdateEnabled}' .env` command: `sed -i '/COOLIFY_AUTO_UPDATE=/cCOOLIFY_AUTO_UPDATE=${isAutoUpdateEnabled}' .env`
}); });