Files
headlamp-sealed-secrets-plugin/src/lib/validators.ts
T
DevContainer User 9d9bc5f22f fix: remove any types, dead code, unused exports; add comprehensive tests
- Fix handleRotate bug ignoring Result from rotateSealedSecret()
- Fix dead code branch in useControllerHealth
- Replace all `any` types with `unknown` + type guards
- Delete unused functions/exports (452 lines removed)
- Add 18 new test files covering all hooks, libs, and components
- 233 tests passing, zero tsc errors, zero lint issues

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 17:13:00 +00:00

159 lines
4.0 KiB
TypeScript

/**
* Runtime validators and type guards
*
* Provides validation functions for user input, configuration values,
* and runtime type checking for SealedSecret objects.
*/
/**
* Validate Kubernetes resource name
*
* Must match DNS-1123 subdomain:
* - lowercase alphanumeric characters, '-' or '.'
* - start and end with alphanumeric character
* - max 253 characters
*
* @param name Name to validate
* @returns true if valid Kubernetes resource name
*/
function isValidK8sName(name: string): boolean {
if (!name || name.length === 0 || name.length > 253) {
return false;
}
// DNS-1123 subdomain format
return /^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$/.test(name);
}
/**
* Validate Kubernetes label/annotation key
*
* @param key Key to validate
* @returns true if valid Kubernetes key
*/
function isValidK8sKey(key: string): boolean {
if (!key || key.length === 0 || key.length > 253) {
return false;
}
// Simple alphanumeric key validation
return /^[a-zA-Z0-9]([-_.a-zA-Z0-9]*[a-zA-Z0-9])?$/.test(key);
}
/**
* Validate PEM certificate format
*
* Checks for BEGIN/END CERTIFICATE markers and basic structure
*
* @param value String to validate
* @returns true if valid PEM format
*/
function isValidPEM(value: string): boolean {
if (!value || typeof value !== 'string') {
return false;
}
// Check for PEM markers and basic structure
const pemRegex = /^-----BEGIN CERTIFICATE-----\s+[\s\S]+\s+-----END CERTIFICATE-----\s*$/;
return pemRegex.test(value.trim());
}
/**
* Validation result with error message
*/
export interface ValidationResult {
valid: boolean;
error?: string;
}
/**
* Validate secret name with detailed error message
*
* @param name Secret name to validate
* @returns Validation result with error message if invalid
*/
export function validateSecretName(name: string): ValidationResult {
if (!name || name.trim().length === 0) {
return { valid: false, error: 'Secret name is required' };
}
if (name.length > 253) {
return { valid: false, error: 'Secret name must be 253 characters or less' };
}
if (!isValidK8sName(name)) {
return {
valid: false,
error:
'Secret name must be lowercase alphanumeric, may contain hyphens and dots, and must start/end with alphanumeric',
};
}
return { valid: true };
}
/**
* Validate secret key name with detailed error message
*
* @param key Key name to validate
* @returns Validation result with error message if invalid
*/
export function validateSecretKey(key: string): ValidationResult {
if (!key || key.trim().length === 0) {
return { valid: false, error: 'Key name is required' };
}
if (key.length > 253) {
return { valid: false, error: 'Key name must be 253 characters or less' };
}
if (!isValidK8sKey(key)) {
return {
valid: false,
error: 'Key name must be alphanumeric and may contain hyphens, underscores, and dots',
};
}
return { valid: true };
}
/**
* Validate secret value (plaintext)
*
* @param value Secret value to validate
* @returns Validation result with error message if invalid
*/
export function validateSecretValue(value: string): ValidationResult {
if (!value || value.trim().length === 0) {
return { valid: false, error: 'Secret value is required' };
}
// Check for reasonable size limit (1MB)
if (value.length > 1024 * 1024) {
return { valid: false, error: 'Secret value must be less than 1MB' };
}
return { valid: true };
}
/**
* Validate PEM certificate with detailed error message
*
* @param pem PEM certificate to validate
* @returns Validation result with error message if invalid
*/
export function validatePEMCertificate(pem: string): ValidationResult {
if (!pem || pem.trim().length === 0) {
return { valid: false, error: 'Certificate is required' };
}
if (!isValidPEM(pem)) {
return {
valid: false,
error: 'Invalid PEM format. Must contain BEGIN CERTIFICATE and END CERTIFICATE markers',
};
}
return { valid: true };
}