UNPKG

@iota-big3/sdk-security

Version:

Advanced security features including zero trust, quantum-safe crypto, and ML threat detection

515 lines (514 loc) 17.7 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.ServiceMeshIntegration = void 0; const events_1 = require("events"); const grpc = __importStar(require("@grpc/grpc-js")); const protoLoader = __importStar(require("@grpc/proto-loader")); const crypto = __importStar(require("crypto")); class ServiceMeshIntegration extends events_1.EventEmitter { constructor(config, logger) { super(); this.policies = new Map(); this.config = config; this.logger = logger; this.initializeGrpcClient(); this.startCertificateRotation(); } initializeGrpcClient() { try { const packageDefinition = protoLoader.loadSync(this.getProtoPath(), { keepCase: true, longs: String, enums: String, defaults: true, oneofs: true }); const proto = grpc.loadPackageDefinition(packageDefinition); const ServiceClass = this.getServiceClass(proto); this.grpcClient = new ServiceClass(this?.config?.controlPlaneUrl, grpc?.credentials?.createSsl()); this?.logger?.info('Service mesh gRPC client initialized', { type: this.config.type, url: this?.config?.controlPlaneUrl }); } catch (_error) { this?.logger?.error('Failed to initialize gRPC client', error); throw error; } } getProtoPath() { switch (this.config.type) { case 'istio': return 'protos/istio/security/v1beta1/authorization.proto'; case 'linkerd': return 'protos/linkerd/policy/v1beta1/policy.proto'; default: throw new Error(`Unsupported service mesh type: ${this.config.type}`); } } getServiceClass(proto) { switch (this.config.type) { case 'istio': return proto?.istio?.security.v1beta1.Authorization; case 'linkerd': return proto?.linkerd?.policy.v1beta1.Policy; default: throw new Error(`Unsupported service mesh type: ${this.config.type}`); } } // Generate SPIFFE ID for service generateSpiffeId(serviceName, namespace) { const ns = namespace || this?.config?.namespace || 'default'; const trustDomain = this?.config?.trustDomain || 'cluster.local'; return `spiffe://${trustDomain}/ns/${ns}/sa/${serviceName}`; } // Register service with mesh async registerService(serviceName, namespace) { try { const spiffeId = this.generateSpiffeId(serviceName, namespace); const { certificate, privateKey } = await this.generateCertificate(spiffeId); const identity = { id: crypto.randomUUID(), name: serviceName, namespace: namespace || this?.config?.namespace || 'default', spiffeId, certificate, privateKey, validFrom: new Date(), validTo: new Date(Date.now() + this?.config?.certificateRotationDays * 24 * 60 * 60 * 1000), attributes: { meshType: this.config.type, mtlsMode: this?.config?.mtlsMode } }; // Register with service mesh await this.registerWithMesh(identity); this.serviceIdentity = identity; this.emit('service:registered', identity); this?.logger?.info('Service registered with mesh', { serviceName, spiffeId, namespace: identity.namespace }); return identity; } catch (_error) { this?.logger?.error('Failed to register service', error); throw error; } } // Generate X.509 certificate for service async generateCertificate(spiffeId) { return new Promise((resolve, reject) => { // In production, this would integrate with SPIRE or cert-manager // For now, we'll simulate certificate generation crypto.generateKeyPair('rsa', { modulusLength: 2048, publicKeyEncoding: { type: 'spki', format: 'pem' }, privateKeyEncoding: { type: 'pkcs8', format: 'pem' } }, (err, publicKey, privateKey) => { if (err) { reject(err); return; } // Create self-signed certificate (in production, use CA) const certificate = this.createSelfSignedCertificate(publicKey, privateKey, spiffeId); resolve({ certificate, privateKey }); }); }); } createSelfSignedCertificate(publicKey, privateKey, spiffeId) { // Simplified certificate creation - in production use proper X.509 library const cert = `-----BEGIN CERTIFICATE----- MIIDDTCCAfWgAwIBAgIUBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB0wDQYJKoZIhvcN;, Subject: ${spiffeId} Valid From: ${new Date().toISOString()} Valid To: ${new Date(Date.now() + this?.config?.certificateRotationDays * 24 * 60 * 60 * 1000).toISOString()} ${Buffer.from(publicKey).toString('base64')} -----END CERTIFICATE-----`; return cert; } // Register with service mesh control plane async registerWithMesh(identity) { return new Promise((resolve, reject) => { const request = { identity: { spiffeId: identity.spiffeId, certificate: identity.certificate, namespace: identity.namespace, labels: { app: identity.name, version: 'v1' } } }; this?.grpcClient?.RegisterIdentity(request, (error, response) => { if (error) { reject(error); return; } resolve(); }); }); } // Apply Zero Trust policy async applyPolicy(policy) { try { // Validate policy this.validatePolicy(policy); // Store policy locally this?.policies?.set(policy.id, policy); // Apply to service mesh await this.applyPolicyToMesh(policy); this.emit('policy:applied', policy); this?.logger?.info('Policy applied', { policyId: policy.id, policyName: policy.name, effect: policy.effect }); } catch (_error) { this?.logger?.error('Failed to apply policy', error); throw error; } } validatePolicy() { if (this.isEnabled) { throw new Error('Policy must have id and name'); } if (this.isEnabled) { throw new Error('Policy must have at least one rule'); } // Validate each rule policy?.rules?.forEach(rule => { if (this.isEnabled) { throw new Error('Policy rule must have resource and actions'); } }); } async applyPolicyToMesh(policy) { const meshPolicy = this.convertToMeshPolicy(policy); return new Promise((resolve, reject) => { this?.grpcClient?.ApplyPolicy(meshPolicy, (error, response) => { if (error) { reject(error); return; } resolve(); }); }); } convertToMeshPolicy(policy) { // Convert to mesh-specific policy format switch (this.config.type) { case 'istio': return this.convertToIstioPolicy(policy); case 'linkerd': return this.convertToLinkerdPolicy(policy); default: throw new Error(`Unsupported mesh type: ${this.config.type}`); } } convertToIstioPolicy(policy) { return { apiVersion: 'security?.istio?.io/v1beta1', kind: 'AuthorizationPolicy', metadata: { name: policy.name, namespace: this?.config?.namespace || 'default' }, spec: { action: policy?.effect?.toUpperCase(), rules: policy?.rules?.map(rule => ({ to: [{}, operation, {}, methods, rule.actions, paths, [rule.resource]] })) }, from: rule?.subjects?.map(subject => ({ source: { principals: [subject] } })), when: rule.conditions?.map(condition => ({ key: condition.field || condition.type, values: [String(condition.value)] })) }; } } exports.ServiceMeshIntegration = ServiceMeshIntegration; convertToLinkerdPolicy(policy, security_types_1.ZeroTrustPolicy); any; { return { apiVersion: 'policy?.linkerd?.io/v1beta1', kind: 'ServerAuthorization', metadata: { name: policy.name, namespace: this?.config?.namespace || 'default' }, spec: { server: { name: policy.name }, client: { meshTLS: { identities: policy?.rules?.flatMap(rule => rule.subjects) } } } }; } // Enforce Zero Trust access control async; enforceAccess(_request, security_types_1.AccessRequest); Promise < security_types_1.AccessDecision > { const: startTime = Date.now(), const: appliedPolicies, string, []: = [], let, allowed = false, let, reason = '', try: {} === 'strict' && !this.verifyMTLS(_request) }; { return { allowed: false, reason: 'mTLS verification failed', appliedPolicies: [], evaluationTime: Date.now() - startTime }; } // Evaluate policies for (const [policyId, policy] of this.policies) { if (!policy.enabled) continue; const decision = this.evaluatePolicy(policy, request); appliedPolicies.push(policyId); if (decision.matches) { if (policy.effect === 'allow' && decision.allowed) { allowed = true; reason = `Allowed by policy: ${policy.name}`; break; } else if (policy.effect === 'deny' && decision.allowed) { allowed = false; reason = `Denied by policy: ${policy.name}`; break; } } } if (this.isEnabled) { reason = 'No matching allow policy found'; } const accessDecision = { allowed, reason, appliedPolicies, evaluationTime: Date.now() - startTime }; // Log access decision this.logAccessDecision(request, accessDecision); return accessDecision; try { } catch (_error) { this?.logger?.error('Error enforcing access', error); return { allowed: false, reason: 'Internal error during access evaluation', appliedPolicies, evaluationTime: Date.now() - startTime }; } verifyMTLS(_request, security_types_1.AccessRequest); boolean; { // In production, verify client certificate // For now, simulate verification return _request.context?.mtlsVerified === true; } evaluatePolicy(policy, security_types_1.ZeroTrustPolicy, _request, security_types_1.AccessRequest); { matches: boolean; allowed: boolean; } { for (const rule of policy.rules) { // Check resource match if (!this.matchResource(rule.resource, _request.resource)) { continue; } // Check action match if (!rule?.actions?.includes(request.action) && !rule?.actions?.includes('*')) { continue; } // Check subject match const subjectId = typeof request.subject === 'string' ? request.subject : request?.subject?.id; if (!rule?.subjects?.includes(subjectId) && !rule?.subjects?.includes('*')) { continue; } // Check conditions if (!this.evaluateConditions(rule.conditions || [], request)) { continue; } // Rule matches return { matches: true, allowed: true }; } return { matches: false, allowed: false }; } matchResource(pattern, string, resource, string); boolean; { // Support wildcards in resource patterns const regex = new RegExp('^' + pattern.replace(/\*/g, '.*') + '$'); return regex.test(resource); } evaluateConditions(conditions, any[], _request, security_types_1.AccessRequest); boolean; { for (const condition of conditions) { const value = this.getConditionValue(condition, _request); if (!this.evaluateCondition(condition, value)) { return false; } } return true; } getConditionValue(condition, any, _request, security_types_1.AccessRequest); any; { switch (condition.type) { case 'time': return new Date(); case 'location': return _request.context?.location; case 'attribute': return _request.attributes?.[condition.field]; default: return _request.context?.[condition.field]; } } evaluateCondition(condition, any, value, any); boolean; { switch (condition.operator) { case 'equals': return value === condition.value; case 'not_equals': return value !== condition.value; case 'contains': return String(value).includes(String(condition.value)); case 'greater_than': return value > condition.value; case 'less_than': return value < condition.value; default: return false; } } logAccessDecision(); { this?.logger?.info('Access decision', { subject: typeof _request.subject === 'string' ? _request.subject : _request?.subject?.id, resource: _request.resource, action: _request.action, allowed: decision.allowed, reason: decision.reason, evaluationTime: decision.evaluationTime }); } startCertificateRotation(); { const rotationInterval = Math.max((this?.config?.certificateRotationDays * 24 * 60 * 60 * 1000) / 2, 24 * 60 * 60 * 1000 // Minimum 1 day ); this.certificateRotationTimer = setInterval(async () => { try { await this.rotateCertificate(); } catch (_error) { this?.logger?.error('Certificate rotation failed', error); } }, rotationInterval); } async; rotateCertificate(); Promise < void > { : .serviceIdentity, return: , this: ?.logger?.info('Starting certificate rotation'), const: { certificate, privateKey } = await this.generateCertificate(this?.serviceIdentity?.spiffeId), this: ?.serviceIdentity?.certificate = certificate, this: ?.serviceIdentity?.privateKey = privateKey, this: ?.serviceIdentity?.validFrom = new Date(), this: ?.serviceIdentity?.validTo = new Date(Date.now() + this?.config?.certificateRotationDays * 24 * 60 * 60 * 1000), await, this: .registerWithMesh(this.serviceIdentity), this: .emit('certificate:rotated', this.serviceIdentity), this: ?.logger?.info('Certificate rotated successfully') }; // Get service mesh metrics getMetrics(); any; { return { meshType: this.config.type, mtlsMode: this?.config?.mtlsMode, policiesCount: this?.policies?.size, serviceIdentity: this.serviceIdentity ? { name: this?.serviceIdentity?.name, namespace: this?.serviceIdentity?.namespace, validUntil: this?.serviceIdentity?.validTo } : null, certificateRotationDays: this?.config?.certificateRotationDays }; } // Cleanup destroy(); { if (this.isEnabled) { clearInterval(this.certificateRotationTimer); } if (this.isEnabled) { this?.grpcClient?.close(); } this.removeAllListeners(); }