Introduced Secrets Manager

This commit is contained in:
2025-09-28 17:43:21 +02:00
parent 4d9b1f1dff
commit 83fc24be0c
13 changed files with 79 additions and 32 deletions

1
package-lock.json generated
View File

@@ -16,6 +16,7 @@
"@fastify/multipart": "^9.0.3",
"@fastify/swagger": "^9.5.1",
"@fastify/swagger-ui": "^5.2.3",
"@infisical/sdk": "^4.0.6",
"@prisma/client": "^6.15.0",
"@supabase/supabase-js": "^2.56.1",
"@zip.js/zip.js": "^2.7.73",

View File

@@ -23,6 +23,7 @@
"@fastify/multipart": "^9.0.3",
"@fastify/swagger": "^9.5.1",
"@fastify/swagger-ui": "^5.2.3",
"@infisical/sdk": "^4.0.6",
"@prisma/client": "^6.15.0",
"@supabase/supabase-js": "^2.56.1",
"@zip.js/zip.js": "^2.7.73",

View File

@@ -22,9 +22,11 @@ import exportRoutes from "./routes/exports"
import emailAsUserRoutes from "./routes/emailAsUser";
import {sendMail} from "./utils/mailer";
import {loadSecrets, secrets} from "./utils/secrets";
async function main() {
const app = Fastify({ logger: true });
await loadSecrets();
/*app.addHook("onRequest", (req, reply, done) => {
console.log("Incoming:", req.method, req.url, "Headers:", req.headers)
@@ -37,7 +39,7 @@ async function main() {
await app.register(supabasePlugin);
await app.register(tenantPlugin);
app.register(fastifyCookie, {
secret: process.env.COOKIE_SECRET || "supersecret", // optional, für signierte Cookies
secret: secrets.COOKIE_SECRET,
})
// Öffentliche Routes
await app.register(authRoutes);
@@ -68,8 +70,8 @@ async function main() {
// Start
try {
await app.listen({ port: 3100, host: "0.0.0.0" });
console.log("🚀 Server läuft auf http://localhost:3100");
await app.listen({ port: secrets.PORT, host: secrets.HOST });
console.log(`🚀 Server läuft auf http://${secrets.HOST}:${secrets.PORT}`);
} catch (err) {
app.log.error(err);
process.exit(1);

View File

@@ -1,6 +1,7 @@
import { FastifyInstance } from "fastify";
import fp from "fastify-plugin";
import jwt from "jsonwebtoken";
import {secrets} from "../utils/secrets";
export default fp(async (server: FastifyInstance) => {
server.addHook("preHandler", async (req, reply) => {
@@ -28,7 +29,7 @@ export default fp(async (server: FastifyInstance) => {
}
const payload = jwt.verify(token, process.env.JWT_SECRET!) as {
const payload = jwt.verify(token, secrets.JWT_SECRET!) as {
user_id: string;
email: string;
tenant_id?: string;

View File

@@ -1,11 +1,11 @@
import { FastifyInstance } from "fastify";
import fp from "fastify-plugin";
import { createClient, SupabaseClient } from "@supabase/supabase-js";
import {secrets} from "../utils/secrets";
export default fp(async (server: FastifyInstance) => {
const supabaseUrl = process.env.SUPABASE_URL || "https://uwppvcxflrcsibuzsbil.supabase.co";
const supabaseServiceKey = process.env.SUPABASE_SERVICE_ROLE_KEY || "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InV3cHB2Y3hmbHJjc2lidXpzYmlsIiwicm9sZSI6InNlcnZpY2Vfcm9sZSIsImlhdCI6MTcwMDkzODE5NCwiZXhwIjoyMDE2NTE0MTk0fQ.6hOkD1J8XBkVJUm-swv0ngLQ74xrEYr28EEbo0rUrts";
const supabaseUrl = secrets.SUPABASE_URL
const supabaseServiceKey = secrets.SUPABASE_SERVICE_ROLE_KEY
const supabase: SupabaseClient = createClient(supabaseUrl, supabaseServiceKey);
// Fastify um supabase erweitern

View File

@@ -3,6 +3,7 @@ import bcrypt from "bcrypt";
import jwt from "jsonwebtoken";
import { generateRandomPassword, hashPassword } from "../../utils/password"
import { sendMail } from "../../utils/mailer"
import {secrets} from "../../utils/secrets";
export default async function authRoutes(server: FastifyInstance) {
// Registrierung
@@ -140,7 +141,7 @@ export default async function authRoutes(server: FastifyInstance) {
} else {
const token = jwt.sign(
{ user_id: user.id, email: user.email, tenant_id: req.tenant ? req.tenant.id : null },
process.env.JWT_SECRET!,
secrets.JWT_SECRET!,
{ expiresIn: "3h" }
);

View File

@@ -7,6 +7,7 @@ import {GetObjectCommand, PutObjectCommand} from "@aws-sdk/client-s3"
import {getSignedUrl} from "@aws-sdk/s3-request-presigner";
import dayjs from "dayjs";
import {randomUUID} from "node:crypto";
import {secrets} from "../utils/secrets";
const createExport = async (server:FastifyInstance,req:any,startDate,endDate,beraternr,mandantennr) => {
console.log(startDate,endDate,beraternr,mandantennr)
@@ -22,7 +23,7 @@ const createExport = async (server:FastifyInstance,req:any,startDate,endDate,ber
// 3) In S3 hochladen
await s3.send(
new PutObjectCommand({
Bucket: process.env.S3_BUCKET || "FEDEO",
Bucket: secrets.S3_BUCKET,
Key: fileKey,
Body: buffer,
ContentType: "application/zip",
@@ -33,7 +34,7 @@ const createExport = async (server:FastifyInstance,req:any,startDate,endDate,ber
const url = await getSignedUrl(
s3,
new GetObjectCommand({
Bucket: process.env.S3_BUCKET || "FEDEO",
Bucket: secrets.S3_BUCKET,
Key: fileKey,
}),
{ expiresIn: 60 * 60 * 24 }

View File

@@ -4,6 +4,7 @@ import { s3 } from "../utils/s3"
import {GetObjectCommand, PutObjectCommand} from "@aws-sdk/client-s3"
import {getSignedUrl} from "@aws-sdk/s3-request-presigner";
import archiver from "archiver"
import {secrets} from "../utils/secrets"
export default async function fileRoutes(server: FastifyInstance) {
await server.register(multipart,{
@@ -59,7 +60,7 @@ export default async function fileRoutes(server: FastifyInstance) {
const fileKey = `${tenantId}/filesbyid/${createdFileData.id}/${data.filename}`
await s3.send(new PutObjectCommand({
Bucket: process.env.S3_BUCKET || "FEDEO",
Bucket: secrets.S3_BUCKET,
Key: fileKey,
Body: fileBuffer,
ContentType: data.mimetype,
@@ -143,7 +144,7 @@ export default async function fileRoutes(server: FastifyInstance) {
}
const command = new GetObjectCommand({
Bucket: process.env.S3_BUCKET || "FEDEO",
Bucket: secrets.S3_BUCKET,
Key: data.path,
})
@@ -187,7 +188,7 @@ export default async function fileRoutes(server: FastifyInstance) {
for (const entry of supabaseFiles) {
const command = new GetObjectCommand({
Bucket: process.env.S3_BUCKET || "FEDEO",
Bucket: secrets.S3_BUCKET,
Key: entry.path,
})
@@ -217,7 +218,7 @@ export default async function fileRoutes(server: FastifyInstance) {
const {data,error} = await server.supabase.from("files").select("*").eq("id", id).single()
const command = new GetObjectCommand({
Bucket: process.env.S3_BUCKET || "FEDEO",
Bucket: secrets.S3_BUCKET,
Key: data.path,
});
@@ -256,7 +257,7 @@ export default async function fileRoutes(server: FastifyInstance) {
if(!key) console.log(file)
const command = new GetObjectCommand({
Bucket: process.env.S3_BUCKET || "FEDEO",
Bucket: secrets.S3_BUCKET,
Key: key,
})

View File

@@ -1,5 +1,6 @@
import { FastifyInstance } from "fastify";
import jwt from "jsonwebtoken";
import {secrets} from "../utils/secrets";
export default async function routes(server: FastifyInstance) {
server.get("/tenant", async (req) => {
@@ -45,7 +46,7 @@ export default async function routes(server: FastifyInstance) {
email: req.user.email,
tenant_id: body.tenant_id,
},
process.env.JWT_SECRET!,
secrets.JWT_SECRET!,
{ expiresIn: "3h" }
);

View File

@@ -5,6 +5,7 @@ import {BlobWriter, Data64URIReader, TextReader, TextWriter, ZipWriter} from "@z
import {FastifyInstance} from "fastify";
import {GetObjectCommand} from "@aws-sdk/client-s3";
import {s3} from "../s3";
import {secrets} from "../secrets";
dayjs.extend(isBetween)
const getCreatedDocumentTotal = (item) => {
@@ -92,7 +93,7 @@ export async function buildExportZip(server: FastifyInstance, tenant: number, st
const downloadFile = async (bucketName, filePath, downloadFilePath,fileId) => {
const command = new GetObjectCommand({
Bucket: process.env.S3_BUCKET || "FEDEO",
Bucket: secrets.S3_BUCKET,
Key: filePath,
})

View File

@@ -1,12 +1,13 @@
import nodemailer from "nodemailer"
import {secrets} from "./secrets"
const transporter = nodemailer.createTransport({
host: process.env.SMTP_HOST,
port: Number(process.env.SMTP_PORT) || 587,
secure: process.env.SMTP_SSL === "true", // true für 465, false für andere Ports
host: secrets.MAILER_SMTP_HOST,
port: Number(secrets.MAILER_SMTP_PORT) || 587,
secure: secrets.MAILER_SMTP_SSL === "true", // true für 465, false für andere Ports
auth: {
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASS,
user: secrets.MAILER_SMTP_USER,
pass: secrets.MAILER_SMTP_PASS,
},
})
@@ -17,7 +18,7 @@ export async function sendMail(
): Promise<{ success: boolean; info?: any; error?: any }> {
try {
const info = await transporter.sendMail({
from: process.env.MAIL_FROM,
from: secrets.MAILER_FROM,
to,
subject,
html,

View File

@@ -1,11 +1,18 @@
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3"
import {secrets} from "./secrets";
export const s3 = new S3Client({
endpoint: process.env.S3_ENDPOINT || "https://fedeo.nbg1.your-objectstorage.com", // z. B. http://localhost:9000 für MinIO
region: process.env.S3_REGION || "eu-central",
credentials: {
accessKeyId: process.env.S3_ACCESS_KEY || "RYOMQRW8KSTY3UQX7RPJ",
secretAccessKey: process.env.S3_SECRET_KEY || "aZ33xBv47sPPsHuFKeHSDiLagjqF7nShnuGkj7B1",
},
forcePathStyle: true, // wichtig für MinIO
})
export let s3 = null
export const initS3 = async () => {
s3 = new S3Client({
endpoint: secrets.S3_ENDPOINT, // z. B. http://localhost:9000 für MinIO
region: secrets.S3_REGION,
credentials: {
accessKeyId: secrets.S3_ACCESS_KEY,
secretAccessKey: secrets.S3_SECRET_KEY,
},
forcePathStyle: true, // wichtig für MinIO
})
}

29
src/utils/secrets.ts Normal file
View File

@@ -0,0 +1,29 @@
import {InfisicalSDK} from "@infisical/sdk"
const client = new InfisicalSDK({
siteUrl: "https://secrets.fedeo.io"
})
export let secrets = {}
export async function loadSecrets () {
await client.auth().universalAuth.login({
clientId: process.env.INFISICAL_CLIENT_ID,
clientSecret: process.env.INFISICAL_CLIENT_SECRET,
});
const allSecrets = await client.secrets().listSecrets({
environment: "dev", // stg, dev, prod, or custom environment slugs
projectId: "39774094-2aaf-49fb-a213-d6b2c10f6144"
});
allSecrets.secrets.forEach(secret => {
secrets[secret.secretKey] = secret.secretValue
})
console.log("✅ Secrets aus Infisical geladen");
}