docs: dbal,script,lua (2 files)

This commit is contained in:
2025-12-26 01:16:07 +00:00
parent 5d68cb89a4
commit 2292b843ba
2 changed files with 162 additions and 27 deletions

View File

@@ -18,28 +18,44 @@ namespace lua_script {
* Create a new Lua script in the store
*/
inline Result<LuaScript> create(InMemoryStore& store, const CreateLuaScriptInput& input) {
if (input.name.empty() || input.name.length() > 100) {
return Error::validationError("Name must be between 1 and 100 characters");
if (!validation::isValidLuaScriptName(input.name)) {
return Error::validationError("Lua script name must be 1-255 characters");
}
if (input.code.empty()) {
return Error::validationError("Script code cannot be empty");
if (!validation::isValidLuaScriptCode(input.code)) {
return Error::validationError("Lua script code must be a non-empty string");
}
if (!validation::isValidLuaSyntax(input.code)) {
return Error::validationError("Invalid Lua syntax");
if (!validation::isValidLuaTimeout(input.timeout_ms)) {
return Error::validationError("Timeout must be between 100 and 30000 ms");
}
if (input.created_by.empty()) {
return Error::validationError("created_by is required");
}
for (const auto& entry : input.allowed_globals) {
if (entry.empty()) {
return Error::validationError("allowed_globals must contain non-empty strings");
}
}
if (store.lua_script_names.find(input.name) != store.lua_script_names.end()) {
return Error::conflict("Lua script name already exists: " + input.name);
}
LuaScript script;
script.id = store.generateId("lua_script", ++store.lua_script_counter);
script.id = store.generateId("lua", ++store.lua_script_counter);
script.name = input.name;
script.description = input.description;
script.code = input.code;
script.category = input.category;
script.is_active = input.is_active;
script.is_sandboxed = input.is_sandboxed;
script.allowed_globals = input.allowed_globals;
script.timeout_ms = input.timeout_ms;
script.created_by = input.created_by;
script.created_at = std::chrono::system_clock::now();
script.updated_at = script.created_at;
store.lua_scripts[script.id] = script;
store.lua_script_names[script.name] = script.id;
return Result<LuaScript>(script);
}

View File

@@ -537,25 +537,144 @@ class SecurePathResolver {
- No server-side encryption enforcement
- No bucket policy validation for public access
**Recommendation**:
**🏰 Fort Knox Remediation**:
```typescript
async validateBucketSecurity(): Promise<void> {
const { GetBucketPolicyStatusCommand, GetBucketEncryptionCommand } =
await import('@aws-sdk/client-s3')
import {
S3Client,
GetBucketPolicyStatusCommand,
GetBucketEncryptionCommand,
GetBucketVersioningCommand,
GetBucketLoggingCommand,
GetPublicAccessBlockCommand
} from '@aws-sdk/client-s3'
/**
* Fort Knox S3 Security Validator
* Ensures bucket meets security requirements before any operation
*/
class S3SecurityValidator {
private s3Client: S3Client
private validatedBuckets = new Map<string, { timestamp: number; valid: boolean }>()
private static readonly VALIDATION_TTL_MS = 300_000 // 5 minutes
// Check bucket isn't public
const policyStatus = await this.s3Client.send(
new GetBucketPolicyStatusCommand({ Bucket: this.bucket })
)
if (policyStatus.PolicyStatus?.IsPublic) {
throw DBALError.internal('S3 bucket must not be public')
async validateBucketSecurity(bucket: string): Promise<void> {
// Check cache first
const cached = this.validatedBuckets.get(bucket)
if (cached && Date.now() - cached.timestamp < S3SecurityValidator.VALIDATION_TTL_MS) {
if (!cached.valid) {
throw DBALError.forbidden(`Bucket ${bucket} failed security validation`)
}
return
}
const violations: string[] = []
// CHECK 1: Public Access Block (must be enabled)
try {
const publicAccess = await this.s3Client.send(
new GetPublicAccessBlockCommand({ Bucket: bucket })
)
const config = publicAccess.PublicAccessBlockConfiguration
if (!config?.BlockPublicAcls ||
!config?.BlockPublicPolicy ||
!config?.IgnorePublicAcls ||
!config?.RestrictPublicBuckets) {
violations.push('Public access block not fully enabled')
}
} catch (error: any) {
if (error.name !== 'NoSuchPublicAccessBlockConfiguration') {
violations.push('Public access block not configured')
}
}
// CHECK 2: Bucket Policy Status (must not be public)
try {
const policyStatus = await this.s3Client.send(
new GetBucketPolicyStatusCommand({ Bucket: bucket })
)
if (policyStatus.PolicyStatus?.IsPublic) {
violations.push('Bucket policy allows public access')
}
} catch (error: any) {
// No policy is fine
}
// CHECK 3: Encryption (must be enabled with AES-256 or KMS)
try {
const encryption = await this.s3Client.send(
new GetBucketEncryptionCommand({ Bucket: bucket })
)
const rules = encryption.ServerSideEncryptionConfiguration?.Rules || []
const hasEncryption = rules.some(rule => {
const algo = rule.ApplyServerSideEncryptionByDefault?.SSEAlgorithm
return algo === 'AES256' || algo === 'aws:kms'
})
if (!hasEncryption) {
violations.push('Server-side encryption not enabled')
}
} catch (error: any) {
violations.push('Encryption configuration not found')
}
// CHECK 4: Versioning (recommended for data protection)
try {
const versioning = await this.s3Client.send(
new GetBucketVersioningCommand({ Bucket: bucket })
)
if (versioning.Status !== 'Enabled') {
// Warning only, not a blocking violation
console.warn(`[SECURITY] Bucket ${bucket}: versioning not enabled (recommended)`)
}
} catch {}
// CHECK 5: Access Logging (recommended for audit)
try {
const logging = await this.s3Client.send(
new GetBucketLoggingCommand({ Bucket: bucket })
)
if (!logging.LoggingEnabled) {
console.warn(`[SECURITY] Bucket ${bucket}: access logging not enabled (recommended)`)
}
} catch {}
// Cache result
const isValid = violations.length === 0
this.validatedBuckets.set(bucket, { timestamp: Date.now(), valid: isValid })
if (!isValid) {
this.logSecurityViolation('S3_BUCKET_SECURITY_FAILURE', { bucket, violations })
throw DBALError.forbidden(
`Bucket security validation failed: ${violations.join(', ')}`
)
}
}
// Verify encryption
const encryption = await this.s3Client.send(
new GetBucketEncryptionCommand({ Bucket: this.bucket })
)
// Validate encryption settings...
private logSecurityViolation(event: string, details: unknown): void {
console.error(JSON.stringify({
timestamp: new Date().toISOString(),
severity: 'CRITICAL',
event,
details
}))
}
}
// Integration: Call before every S3 operation
class SecureS3Storage implements BlobStorage {
private validator: S3SecurityValidator
async upload(key: string, data: Buffer, options: UploadOptions): Promise<BlobMetadata> {
await this.validator.validateBucketSecurity(this.bucket)
// Also enforce client-side encryption for sensitive data
const encryptedData = await this.encryptIfRequired(data, options)
return this.doUpload(key, encryptedData, {
...options,
ServerSideEncryption: 'aws:kms', // Force KMS encryption
BucketKeyEnabled: true, // Cost optimization
})
}
}
```