feat: add member portal and auth hardening

This commit is contained in:
defiQUG
2026-04-18 12:05:17 -07:00
parent c80b2a543a
commit 468bc05b78
59 changed files with 4066 additions and 604 deletions

View File

@@ -11,6 +11,8 @@ export interface ProxmoxConfig {
username: string;
password: string;
realm?: string;
tokenName?: string;
tokenValue?: string;
}
export interface ContainerSpec {
@@ -57,6 +59,17 @@ export class ProxmoxVEIntegration {
* Authenticate with Proxmox VE
*/
async authenticate(): Promise<void> {
if (this.config.tokenName && this.config.tokenValue) {
this.token = `PVEAPIToken=${this.config.username}!${this.config.tokenName}=${this.config.tokenValue}`;
this.tokenExpiry = new Date(Date.now() + 24 * 60 * 60 * 1000);
logger.info('Proxmox VE token authentication configured', {
host: this.config.host,
username: this.config.username,
tokenName: this.config.tokenName,
});
return;
}
await proxmoxCircuitBreaker.execute(async () => {
return await retryWithBackoff(
async () => {
@@ -240,7 +253,9 @@ export class ProxmoxVEIntegration {
const options: RequestInit = {
method,
headers: {
'Cookie': `PVEAuthCookie=${this.token}`,
...(this.config.tokenName && this.config.tokenValue
? { Authorization: this.token || '' }
: { 'Cookie': `PVEAuthCookie=${this.token}` }),
},
};
@@ -281,19 +296,22 @@ export class ProxmoxVEIntegration {
// Validate required Proxmox environment variables
function getProxmoxConfig(): ProxmoxConfig {
const host = process.env.PROXMOX_HOST;
const username = process.env.PROXMOX_USERNAME;
const username = process.env.PROXMOX_USERNAME || process.env.PROXMOX_USER;
const password = process.env.PROXMOX_PASSWORD;
const tokenName = process.env.PROXMOX_TOKEN_NAME;
const tokenValue = process.env.PROXMOX_TOKEN_VALUE;
if (process.env.NODE_ENV === 'production') {
if (!host) {
throw new Error('PROXMOX_HOST environment variable is required in production');
}
if (!username) {
throw new Error('PROXMOX_USERNAME environment variable is required in production');
}
if (!password) {
throw new Error('PROXMOX_PASSWORD environment variable is required in production');
}
const hasPasswordAuth = Boolean(host && username && password);
const hasTokenAuth = Boolean(host && username && tokenName && tokenValue);
if (process.env.NODE_ENV === 'production' && !hasPasswordAuth && !hasTokenAuth) {
logger.warn('Proxmox integration environment is incomplete; IRU deployment features will remain unavailable', {
hasHost: Boolean(host),
hasUsername: Boolean(username),
hasPassword: Boolean(password),
hasTokenName: Boolean(tokenName),
hasTokenValue: Boolean(tokenValue),
});
}
return {
@@ -302,6 +320,8 @@ function getProxmoxConfig(): ProxmoxConfig {
username: username || 'root',
password: password || '',
realm: process.env.PROXMOX_REALM || 'pam',
tokenName,
tokenValue,
};
}