crowdsec-http-middleware
Version:
HTTP server middleware that can act as a crowdsec bouncer/watcher
8 lines (7 loc) • 40.5 kB
Source Map (JSON)
{
"version": 3,
"sources": ["../../src/pkg.ts", "../../src/Validate.ts", "../../src/CrowdSecHTTPBouncerMiddleware.ts", "../../src/IpObjectsCacher.ts", "../../src/utils.ts", "../../src/globals.ts", "../../src/CommonsMiddleware.ts", "../../src/CrowdSecHTTPWatcherMiddleware.ts", "../../src/CrowdSecHTTPMiddleware.ts", "../../src/index.ts"],
"sourcesContent": ["export const pkg = { name: 'crowdsec-http-middleware', version: '0.0.8' };\n", "const stringToBooleanMap = new Map<string, boolean>([\n ['true', true],\n ['y', true],\n ['yes', true],\n ['oui', true],\n ['on', true],\n ['1', true],\n ['false', false],\n ['n', false],\n ['no', false],\n ['non', false],\n ['off', false],\n ['0', false]\n]);\n\nexport type MustBeNullable<T> = null extends T ? T : undefined extends T ? T : never;\n\nexport class Validate {\n public static mail(mail: string): boolean {\n return Validate.isString(mail) && !!/^([\\w.%+-]+)@([\\w-]+\\.)+(\\w{2,})$/i.exec(mail);\n }\n\n public static uuid(uuid: string): boolean {\n return Validate.isString(uuid) && !!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89AB][0-9a-f]{3}-[0-9a-f]{12}$/i.exec(uuid);\n }\n\n // Returns if a value is a string\n public static isString(value: unknown): value is string {\n return typeof value === 'string' || value instanceof String;\n }\n // Returns if a value is really a number\n public static isNumber(value: unknown): value is number {\n return typeof value === 'number' && isFinite(value);\n }\n\n // Returns if a value is a function\n public static isFunction(value: unknown): value is Function {\n return typeof value === 'function';\n }\n // Returns if a value is an object\n public static isObject(value: unknown): value is object {\n return value != undefined && typeof value === 'object' && value.constructor === Object;\n }\n // Returns if a value is null\n public static isNull(value: unknown): value is null {\n return value === null;\n }\n\n // Returns if a value is undefined\n public static isUndefined(value: unknown): value is undefined {\n return typeof value === 'undefined';\n }\n\n // in typescript, the equivalent is\n // const a = undefined ?? bar\n public static isDefinedNotNull<T>(value: unknown): value is NonNullable<MustBeNullable<T>> {\n return value !== undefined && value !== null;\n }\n\n // Returns if a value is a boolean\n public static isBoolean(value: unknown): value is boolean {\n return typeof value === 'boolean';\n }\n // Returns if a value is a regexp\n public static isRegExp(value: unknown): value is RegExp {\n return value != undefined && typeof value === 'object' && value.constructor === RegExp;\n }\n // Returns if value is an error object\n public static isError(value: unknown): value is Error {\n return value instanceof Error && typeof value.message !== 'undefined';\n }\n // Returns if value is a date\n public static isDate(value: unknown, acceptTimestamp = true): value is Date {\n return (\n value instanceof Date ||\n (Validate.isString(value) && !Number.isNaN(Date.parse(value.toString()))) ||\n (acceptTimestamp && Validate.isNumber(value) && !Number.isNaN(new Date(value)))\n );\n }\n // Returns if value is a Buffer\n public static isBuffer(value: unknown): value is Buffer {\n return Buffer.isBuffer(value);\n }\n // Returns if a Symbol\n public static isSymbol(value: unknown): value is symbol {\n return typeof value === 'symbol';\n }\n\n public static implementsTKeys<T>(obj: any, keys: Array<keyof T>): obj is T {\n if (!obj || !Array.isArray(keys) || Validate.isString(obj) || Validate.isNumber(obj) || Validate.isBoolean(obj)) {\n return false;\n }\n\n return keys.reduce((impl, key) => impl && key in obj, true);\n }\n\n public static isType<T>(obj: any, condition: boolean): obj is T {\n return condition;\n }\n\n /**\n * Return a boolean depending on the string . (\"true\", \"y\", \"yes\", \"oui\", \"on\" return true, else it's return false)\n * @param {string} str\n * @param {boolean} strict return null instead of false if not in list\n * @return {boolean}\n */\n public static stringToBoolean(str?: string, strict = false): boolean | null {\n return stringToBooleanMap.get((str || '').toLowerCase()) ?? (strict ? null : false);\n }\n}\n\nexport default Validate;\n", "import { getCurrentIpFn, ICrowdSecHTTPBouncerMiddlewareOptions, ICrowdSecHTTPMiddlewareOptions } from './ICrowdSecHTTPMiddlewareOptions.js';\nimport Validate from './Validate.js';\nimport {\n BouncerClient,\n Decision,\n DecisionsStream,\n IBouncerAuthentication,\n ICrowdSecClientOptions,\n ITLSAuthentication\n} from 'crowdsec-client';\nimport { AddressObject } from './utils.js';\nimport { IpObjectsCacher } from './IpObjectsCacher.js';\nimport { IncomingMessage, ServerResponse } from 'http';\nimport { CommonsMiddleware } from './CommonsMiddleware.js';\n\ntype decisionScope = 'ip' | 'range';\ntype decisionType = Decision<decisionScope>;\n\nexport class CrowdSecHTTPBouncerMiddleware extends CommonsMiddleware {\n private readonly clientOptions: ICrowdSecClientOptions;\n public readonly client: BouncerClient;\n\n //TODO store this on updates\n public get decisionsCount(): number {\n return Object.keys(this.decisions || {}).reduce((previousValue, key) => previousValue + (this.decisions[key]?.length || 0), 0);\n }\n\n private decisions: Record<string, Array<{ selector: AddressObject; decision: decisionType }>> = {};\n private options: ICrowdSecHTTPBouncerMiddlewareOptions;\n private ipObjectCache: IpObjectsCacher;\n\n /**\n * allow to listen to decision events\n */\n get decisionStream(): DecisionsStream<decisionScope> | undefined {\n return this._decisionStream;\n }\n private _decisionStream?: DecisionsStream<decisionScope>;\n\n constructor(options: ICrowdSecHTTPBouncerMiddlewareOptions, clientOptions: ICrowdSecClientOptions, cache?: IpObjectsCacher) {\n super('CrowdSecHTTPBouncerMiddleware', options.logger);\n this.logger.debug('construct');\n\n this.options = options;\n this.clientOptions = clientOptions;\n\n const auth = this.getBouncerAuthentication(options);\n this.client = new BouncerClient({\n url: this.clientOptions.url,\n userAgent: this.clientOptions.userAgent,\n timeout: this.clientOptions.timeout,\n strictSSL: this.clientOptions.strictSSL,\n auth\n });\n\n this.ipObjectCache = cache ?? new IpObjectsCacher(options.maxIpCache);\n }\n\n private getBouncerAuthentication(bouncerOptions: ICrowdSecHTTPMiddlewareOptions['bouncer']) {\n this.logger.debug('getBouncerAuthentication');\n if (Validate.implementsTKeys<ITLSAuthentication>(bouncerOptions, ['key', 'ca', 'cert'])) {\n return {\n cert: bouncerOptions.cert,\n key: bouncerOptions.key,\n ca: bouncerOptions.ca\n } as ITLSAuthentication;\n }\n\n if (Validate.implementsTKeys<IBouncerAuthentication>(bouncerOptions, ['apiKey'])) {\n return {\n apiKey: bouncerOptions.apiKey\n } as IBouncerAuthentication;\n }\n\n throw new Error('bad client configuration');\n }\n\n public async start() {\n this.logger.info('start');\n await this.client.login();\n\n this._decisionStream = this.client.Decisions.getStream({\n interval: this.options?.pollingInterval,\n scopes: ['ip', 'range']\n });\n\n this._decisionStream.on('error', (e) => {\n this.logger.error('client stream error', e);\n });\n\n let timeout: NodeJS.Timeout | undefined;\n this._decisionStream.on('added', (decision) => {\n try {\n // TODO this method doesn't support range including multiple top level group\n const ipObject = this.ipObjectCache.getIpObjectWithCache(decision.value);\n const decisionId = ipObject.parsedAddress[0];\n\n if (!this.decisions[decisionId]) {\n this.decisions[decisionId] = [];\n }\n\n if (!this.decisions[decisionId].find(({ decision: d }) => this.isSameDecision(d, decision))) {\n this.decisions[decisionId].push({ decision, selector: this.ipObjectCache.getIpObjectWithCache(decision.value) });\n }\n } catch (e) {\n this.logger.error('fail to add decision', e, decision);\n }\n });\n\n this._decisionStream.on('deleted', (decision) => {\n const ipObject = this.ipObjectCache.getIpObjectWithCache(decision.value);\n const decisionId = ipObject.parsedAddress[0];\n this.decisions[decisionId] = (this.decisions[decisionId] || []).filter(({ decision: d }) => !this.isSameDecision(d, decision));\n });\n\n this._decisionStream.resume();\n }\n\n private isSameDecision(d1: Decision<any>, d2: Decision<any>) {\n return d1.value === d2.value && d1.type === d2.type;\n }\n\n public async stop() {\n this.logger.info('stop');\n return this.client.stop();\n }\n\n public middleware(ip: string, req: IncomingMessage & { decision?: Decision<any> }) {\n const localDebug = this.logger.extend('bouncerMiddleware');\n localDebug.debug('start');\n\n const currentAddress = this.ipObjectCache.getIpObjectWithCache(ip);\n\n localDebug.debug('bouncerMiddleware receive request from %s', currentAddress.addressMinusSuffix);\n localDebug.debug('start decision loop');\n const decision = (this.decisions[currentAddress.parsedAddress[0]] || []).find(({ selector }) =>\n currentAddress.isInSubnet(selector)\n );\n localDebug.debug('end decision loop');\n\n if (decision) {\n req.decision = decision.decision;\n }\n localDebug.debug('end');\n }\n\n public getMiddleware(getIpFromRequest: getCurrentIpFn) {\n return (req: IncomingMessage, res: ServerResponse) => {\n const ip = getIpFromRequest(req);\n\n this.middleware(ip, req);\n };\n }\n}\n", "import { LRUCache } from 'lru-cache';\nimport { AddressObject, getIpObject } from './utils.js';\nimport { MAX_IP_CACHE } from './globals.js';\n\nexport class IpObjectsCacher {\n private ipObjectCache: LRUCache<string, AddressObject, unknown>;\n constructor(max: number = MAX_IP_CACHE) {\n this.ipObjectCache = new LRUCache<string, AddressObject>({\n max\n });\n }\n\n public getIpObjectWithCache(value: string): AddressObject {\n const cachedIp = this.ipObjectCache.get(value);\n if (cachedIp) {\n return cachedIp;\n }\n\n const ip = getIpObject(value);\n\n this.ipObjectCache.set(value, ip);\n return ip;\n }\n}\n", "import createDebug, { Debugger } from 'debug';\nimport { pkg } from './pkg.js';\nimport { Address4, Address6 } from 'ip-address';\n\nconst debug = createDebug(pkg.name);\n\n/**\n * create a debugger extending the default debugger\n * @param name - name for the debugger\n */\nexport const createDebugger = (name: string): Debugger => {\n if (!name) {\n throw new Error('name is mandatory');\n }\n return debug.extend(name);\n};\n\nexport type AddressObject = Address4 | Address6;\n\nexport const getIpObject = (ip: string): AddressObject => {\n try {\n //check if it's a valid IPv4\n return new Address4(ip);\n } catch (e) {\n //e is not instance of AddressError\n if ((e as { name: string }).name === 'AddressError') {\n //maybe it's a valid IPv6\n return new Address6(ip);\n } else {\n throw e;\n }\n }\n};\n", "export const MAX_IP_CACHE = 50000;\n", "import { logger, loggerOption } from './ICrowdSecHTTPMiddlewareOptions.js';\nimport { createDebugger } from './utils.js';\n\nexport class CommonsMiddleware {\n protected logger: Required<logger>;\n\n constructor(name: string, options?: loggerOption) {\n this.logger = this.getLogger(name, options);\n }\n\n getLogger(name: string, options?: loggerOption, extendedName?: string): Required<logger> {\n const defaultExtend = (extendName: string) => this.getLogger(name, options, extendName);\n if (!options) {\n const _debug = createDebugger(name);\n const debug = extendedName ? _debug.extend(extendedName) : _debug;\n return {\n warn: (...args) => debug('warning : %s', ...args),\n debug: debug,\n info: debug,\n error: (...args) => debug('error : %s', ...args),\n extend: defaultExtend\n };\n }\n\n if (typeof options === 'function') {\n return {\n extend: defaultExtend,\n ...options(name)\n };\n }\n\n return {\n extend: defaultExtend,\n ...options\n };\n }\n}\n", "import { getCurrentIpFn, ICrowdSecHTTPMiddlewareOptions, ICrowdSecHTTPWatcherMiddlewareOptions } from './ICrowdSecHTTPMiddlewareOptions.js';\nimport Validate from './Validate.js';\nimport { APITypes, Decision, ICrowdSecClientOptions, ITLSAuthentication, IWatcherAuthentication, WatcherClient } from 'crowdsec-client';\nimport { IpObjectsCacher } from './IpObjectsCacher.js';\nimport { IncomingMessage } from 'http';\nimport { BaseScenario, IIpExtractionResult, IScenario, IScenarioConstructor, MAX_CONFIDENCE } from 'crowdsec-client-scenarios';\nimport { CommonsMiddleware } from './CommonsMiddleware.js';\n\nconst SCENARIOS_PACKAGE_NAME = 'crowdsec-client-scenarios';\n\n/**\n * TODO\n *\n * only ip extraction was tested\n */\n\nexport class CrowdSecHTTPWatcherMiddleware extends CommonsMiddleware {\n private readonly clientOptions: ICrowdSecClientOptions;\n public readonly client: WatcherClient;\n private scenarios: Array<IScenario> = [];\n private defaultScenarios: Array<IScenarioConstructor> = [];\n private options: ICrowdSecHTTPWatcherMiddlewareOptions;\n private ipObjectCache: IpObjectsCacher;\n\n constructor(options: ICrowdSecHTTPWatcherMiddlewareOptions, clientOptions: ICrowdSecClientOptions, cache?: IpObjectsCacher) {\n super('CrowdSecHTTPWatcherMiddleware', options.logger);\n this.logger.debug('construct');\n\n this.options = options;\n this.clientOptions = clientOptions;\n\n const auth = this.getWatcherAuthentication(options);\n\n this.client = new WatcherClient({\n url: this.clientOptions.url,\n userAgent: this.clientOptions.userAgent,\n timeout: this.clientOptions.timeout,\n strictSSL: this.clientOptions.strictSSL,\n heartbeat: options?.heartbeat,\n auth\n });\n\n this.ipObjectCache = cache ?? new IpObjectsCacher(options.maxIpCache);\n }\n\n private getWatcherAuthentication(\n watcherOptions: ICrowdSecHTTPMiddlewareOptions['watcher']\n ): IWatcherAuthentication | ITLSAuthentication {\n this.logger.debug('getWatcherAuthentication');\n if (Validate.implementsTKeys<ITLSAuthentication>(watcherOptions, ['key', 'ca', 'cert'])) {\n return {\n cert: watcherOptions.cert,\n key: watcherOptions.key,\n ca: watcherOptions.ca\n } as ITLSAuthentication;\n }\n if (Validate.implementsTKeys<IWatcherAuthentication>(watcherOptions, ['password', 'machineID'])) {\n return {\n machineID: watcherOptions.machineID,\n password: watcherOptions.password,\n autoRenew: watcherOptions.autoRenew ?? true\n } as IWatcherAuthentication;\n }\n\n throw new Error('bad client configuration');\n }\n\n public async start() {\n this.logger.info('start');\n\n await this.loadDefaultsScenarios(true);\n if (this.options.scenarios) {\n this.options.scenarios.forEach((scenario) =>\n this.addScenario(typeof scenario === 'string' ? scenario : this.initScenario(scenario))\n );\n } else {\n this.logger.debug(`add (${this.defaultScenarios.length}) default scenarios`);\n this.defaultScenarios.forEach((scenario) => this.addScenario(this.initScenario(scenario)));\n }\n\n if (this.scenarios?.length > 0) {\n this.logger.debug(`start to load (${this.scenarios.length}) scenarios`);\n await Promise.all(this.scenarios.map((s) => (s.loaded === false && s.load ? s.load() : Promise.resolve())));\n }\n\n this.logger.debug('login');\n await this.client.login();\n }\n\n public async loadDefaultsScenarios(allowFail = false) {\n this.logger.info('loadDefaultsScenarios');\n let defaultScenariosPackage: { scenarios: Array<new (options: any) => BaseScenario> };\n try {\n defaultScenariosPackage = await import(SCENARIOS_PACKAGE_NAME);\n } catch (e) {\n this.logger.error('fail to load defaultScenarios', e);\n if (allowFail) {\n return;\n }\n\n throw new Error(`fail to load \"${SCENARIOS_PACKAGE_NAME}\". You need to install ${SCENARIOS_PACKAGE_NAME} first`);\n }\n\n if (!defaultScenariosPackage.scenarios) {\n throw new Error('fail to correctly load default scenarios');\n }\n\n this.defaultScenarios = defaultScenariosPackage.scenarios;\n }\n\n private _addScenario(scenario: IScenario) {\n this.logger.debug('_addScenario', scenario.name);\n if (!this.client) {\n throw new Error('client need to be configured to register scenario');\n }\n this.scenarios.push(scenario);\n if (scenario.announceToLAPI) {\n this.client.scenarios.push(scenario.name);\n }\n }\n\n public addScenario(scenario: IScenario | string) {\n if (!scenario) {\n throw new Error('scenario is needed');\n }\n\n this.logger.debug('add scenario', typeof scenario === 'string' ? scenario : scenario.name);\n\n let currentScenario: IScenario;\n if (typeof scenario === 'string') {\n if (!this.defaultScenarios) {\n throw new Error(`defaultScenarios are not loaded . Did you call loadDefaultsScenarios() before ?`);\n }\n\n const defaultScenario = this.defaultScenarios.find((s) => s.name === scenario);\n if (!defaultScenario) {\n throw new Error(`no scenario found with name \"${scenario}\"`);\n }\n\n currentScenario = this.initScenario(defaultScenario);\n } else {\n currentScenario = scenario;\n }\n\n this._addScenario(currentScenario);\n }\n\n private initScenario(scenarioConstructor: IScenarioConstructor): IScenario {\n const scenarioOptions = this.options?.scenariosOptions;\n return new scenarioConstructor(scenarioOptions);\n }\n\n public async stop() {\n this.logger.info('stop');\n return this.client.stop();\n }\n\n public extractIp(req: IncomingMessage): string | undefined {\n const localDebug = this.logger.extend('extractIp');\n localDebug.debug('start extracting ip from request');\n\n const othersIpsFound: Array<IIpExtractionResult> = [];\n const ip = this.scenarios.reduce((currentIp: string | undefined, currentScenario) => {\n if (currentIp || !currentScenario.extractIp) {\n return currentIp;\n }\n\n const ipExtracted = currentScenario.extractIp(req);\n\n // confidence = 10 => we are sure of the ip\n if (ipExtracted?.confidence === MAX_CONFIDENCE) {\n return ipExtracted.ip;\n }\n\n if (ipExtracted) {\n othersIpsFound.push(ipExtracted);\n }\n\n return undefined;\n }, undefined);\n\n if (!ip && othersIpsFound.length > 0) {\n localDebug.debug('no ip found with max confidence, check with less confidence');\n return [...othersIpsFound].sort((a, b) => b.confidence - a.confidence)[0]?.ip;\n }\n localDebug.debug('ip found');\n return ip;\n }\n\n /**\n * Middleware function that processes incoming requests and checks for alerts based on IP address and request data.\n *\n * @param {string} ip - The IP address of the incoming request.\n * @param {IncomingMessage & { decision?: Decision<any> }} req - The incoming request object.\n */\n public middleware(ip: string, req: IncomingMessage & { decision?: Decision<any> }): void {\n const localDebug = this.logger.extend('watcherMiddleware');\n localDebug.debug('start');\n try {\n const currentAddress = this.ipObjectCache.getIpObjectWithCache(ip);\n localDebug.debug('watcherMiddleware receive request from ', currentAddress.addressMinusSuffix);\n localDebug.debug('start check');\n const alerts = this.scenarios\n .map((scenario) => {\n const alerts = scenario.check?.(currentAddress, req);\n if (!alerts) {\n return undefined;\n }\n\n return Array.isArray(alerts) ? alerts : [alerts];\n })\n .flat()\n .filter((v) => !!v) as Array<APITypes.Alert>;\n\n localDebug.debug('end check');\n\n if (alerts.length === 0) {\n return;\n }\n\n localDebug.debug('start enrich');\n const enrichedAlerts = alerts\n .map((alert) => {\n return this.scenarios.reduce((previousValue: APITypes.Alert | undefined, scenario: IScenario) => {\n if (!scenario.enrich || !previousValue) {\n return previousValue;\n }\n\n return scenario.enrich(previousValue, req);\n }, alert);\n })\n .filter((v) => !!v) as Array<APITypes.Alert>;\n localDebug.debug('end enrich');\n\n if (enrichedAlerts.length === 0) {\n return;\n }\n\n this.logger.debug(`ip ${ip} triggers alerts on scenarios : ${enrichedAlerts.map(({ scenario }) => scenario).join(', ')}`);\n\n this.client.Alerts.pushAlerts(enrichedAlerts).catch((e) => console.error('fail to push alert', e));\n } finally {\n localDebug.debug('end');\n }\n }\n\n public getMiddleware(getIpFromRequest: getCurrentIpFn) {\n return (req: IncomingMessage) => {\n const ip = getIpFromRequest(req);\n\n this.middleware(ip, req);\n };\n }\n}\n", "import { ICommonOptions, ICrowdSecHTTPMiddlewareOptions } from './ICrowdSecHTTPMiddlewareOptions.js';\nimport { ICrowdSecClientOptions } from 'crowdsec-client';\nimport { pkg } from './pkg.js';\nimport { AddressObject } from './utils.js';\nimport type { IncomingMessage, ServerResponse } from 'http';\nimport { CrowdSecHTTPBouncerMiddleware } from './CrowdSecHTTPBouncerMiddleware.js';\nimport { IpObjectsCacher } from './IpObjectsCacher.js';\nimport { CrowdSecHTTPWatcherMiddleware } from './CrowdSecHTTPWatcherMiddleware.js';\nimport { CommonsMiddleware } from './CommonsMiddleware.js';\n\nconst defaultClientOptions: Partial<ICrowdSecHTTPMiddlewareOptions['clientOptions']> = {\n userAgent: `${pkg.name}/v${pkg.version}`\n};\n\nexport class CrowdSecHTTPMiddleware extends CommonsMiddleware {\n private readonly clientOptions: ICrowdSecClientOptions;\n private options: ICrowdSecHTTPMiddlewareOptions;\n\n public readonly watcher?: CrowdSecHTTPWatcherMiddleware;\n public readonly bouncer?: CrowdSecHTTPBouncerMiddleware;\n private ipObjectCache: IpObjectsCacher;\n\n constructor(options: ICrowdSecHTTPMiddlewareOptions) {\n super('CrowdSecHTTPMiddleware', options.logger);\n this.logger.debug('construct');\n\n this.options = {\n protectedByHeader: true,\n ...options\n };\n this.clientOptions = {\n ...defaultClientOptions,\n ...options.clientOptions,\n url: options.url\n };\n\n this.ipObjectCache = new IpObjectsCacher(options.maxIpCache);\n\n const commonsOptions: ICommonOptions = {\n logger: options.logger,\n maxIpCache: options.maxIpCache\n };\n\n if (options.watcher) {\n this.watcher = new CrowdSecHTTPWatcherMiddleware({ ...commonsOptions, ...options.watcher }, this.clientOptions);\n }\n\n if (options.bouncer) {\n this.bouncer = new CrowdSecHTTPBouncerMiddleware({ ...commonsOptions, ...options.bouncer }, this.clientOptions);\n }\n }\n\n public async start() {\n this.logger.info('start');\n\n this.logger.debug('login');\n await Promise.all([\n this.bouncer ? this.bouncer.start() : Promise.resolve(),\n this.watcher ? this.watcher.start() : Promise.resolve()\n ]);\n }\n\n /**\n * extract current ip from the request .\n * First try the option getCurrentIp, second check if a scenario allow to extractIp\n * @param req\n * @private\n */\n private getCurrentIpFromRequest(req: IncomingMessage): string {\n if (this.options.getCurrentIp) {\n return this.options.getCurrentIp(req);\n }\n\n const ip = this.watcher?.extractIp(req);\n\n if (!ip) {\n throw new Error('no scenario can extract the ip from this request . And no option \"getCurrentIp\" to extract it');\n }\n\n return ip;\n }\n\n private getIpObjectFromReq(req: IncomingMessage & { ip?: string }): AddressObject {\n const ip = this.getCurrentIpFromRequest(req);\n\n req.ip = ip;\n\n return this.ipObjectCache.getIpObjectWithCache(ip);\n }\n\n protected middlewareFunction = (req: IncomingMessage, res?: ServerResponse) => {\n const currentIp = this.getIpObjectFromReq(req);\n\n if (!currentIp.addressMinusSuffix) {\n // checking the code of the lib, it seems that this will never happen\n // https://github.com/beaugunderson/@laverdet/beaugunderson-ip-address/issues/143\n throw new Error('fail to get address without suffix');\n }\n\n this.bouncer?.middleware(currentIp.addressMinusSuffix, req);\n\n this.watcher?.middleware(currentIp.addressMinusSuffix, req);\n\n if (this.options.protectedByHeader && res) {\n res.appendHeader('X-Protected-By', 'CrowdSec');\n }\n };\n\n public getMiddleware() {\n this.logger.debug('getMiddleware');\n return this.middlewareFunction;\n }\n\n public async stop() {\n this.logger.info('stop');\n await Promise.all([this.bouncer?.stop(), this.watcher?.stop()]);\n }\n}\n", "import { pkg } from './pkg.js';\n\nexport * from './CrowdSecHTTPMiddleware.js';\nexport * from './ICrowdSecHTTPMiddlewareOptions.js';\n\nexport * from 'crowdsec-client';\n\nexport const VERSION = pkg.version;\n"],
"mappings": "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",
"names": ["debug", "alerts"]
}