117 lines
2.7 KiB
TypeScript
117 lines
2.7 KiB
TypeScript
|
|
import type { TSecretResolver } from './interfaces.js';
|
||
|
|
|
||
|
|
/**
|
||
|
|
* RADIUS Shared Secrets Manager
|
||
|
|
* Manages per-client shared secrets for RADIUS authentication
|
||
|
|
*/
|
||
|
|
export class RadiusSecrets {
|
||
|
|
private readonly secrets: Map<string, string> = new Map();
|
||
|
|
private defaultSecret?: string;
|
||
|
|
private customResolver?: TSecretResolver;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Create a new secrets manager
|
||
|
|
*/
|
||
|
|
constructor(options?: {
|
||
|
|
defaultSecret?: string;
|
||
|
|
secrets?: Record<string, string>;
|
||
|
|
resolver?: TSecretResolver;
|
||
|
|
}) {
|
||
|
|
if (options?.defaultSecret) {
|
||
|
|
this.defaultSecret = options.defaultSecret;
|
||
|
|
}
|
||
|
|
if (options?.secrets) {
|
||
|
|
for (const [ip, secret] of Object.entries(options.secrets)) {
|
||
|
|
this.secrets.set(ip, secret);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (options?.resolver) {
|
||
|
|
this.customResolver = options.resolver;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Set secret for a specific client IP
|
||
|
|
*/
|
||
|
|
public setClientSecret(clientIp: string, secret: string): void {
|
||
|
|
this.secrets.set(clientIp, secret);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Remove secret for a specific client IP
|
||
|
|
*/
|
||
|
|
public removeClientSecret(clientIp: string): boolean {
|
||
|
|
return this.secrets.delete(clientIp);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Set the default secret
|
||
|
|
*/
|
||
|
|
public setDefaultSecret(secret: string): void {
|
||
|
|
this.defaultSecret = secret;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Set a custom resolver
|
||
|
|
*/
|
||
|
|
public setResolver(resolver: TSecretResolver): void {
|
||
|
|
this.customResolver = resolver;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get secret for a client IP
|
||
|
|
* Priority: 1. Custom resolver, 2. Per-client secret, 3. Default secret
|
||
|
|
*/
|
||
|
|
public getSecret(clientIp: string): string | undefined {
|
||
|
|
// Try custom resolver first
|
||
|
|
if (this.customResolver) {
|
||
|
|
const resolved = this.customResolver(clientIp);
|
||
|
|
if (resolved !== undefined) {
|
||
|
|
return resolved;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Try per-client secret
|
||
|
|
const clientSecret = this.secrets.get(clientIp);
|
||
|
|
if (clientSecret !== undefined) {
|
||
|
|
return clientSecret;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Fall back to default secret
|
||
|
|
return this.defaultSecret;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Check if a client is known (has a secret)
|
||
|
|
*/
|
||
|
|
public isKnownClient(clientIp: string): boolean {
|
||
|
|
return this.getSecret(clientIp) !== undefined;
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Get all registered client IPs
|
||
|
|
*/
|
||
|
|
public getClientIps(): string[] {
|
||
|
|
return Array.from(this.secrets.keys());
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Clear all per-client secrets
|
||
|
|
*/
|
||
|
|
public clearClientSecrets(): void {
|
||
|
|
this.secrets.clear();
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Set secrets from a CIDR range (simplified - just IP addresses)
|
||
|
|
* For actual CIDR support, use a custom resolver
|
||
|
|
*/
|
||
|
|
public setSecretsForNetwork(network: string, secret: string): void {
|
||
|
|
// For simplicity, this just sets a single IP
|
||
|
|
// Real CIDR support would require a resolver
|
||
|
|
this.secrets.set(network, secret);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
export default RadiusSecrets;
|