nestjs-security-cli
Version:
Advanced IP blocking, role-based security, and attack detection for NestJS applications
272 lines (221 loc) โข 7.21 kB
Markdown
# NestJS Security CLI
Advanced IP blocking, role-based security, and attack detection for NestJS applications.
## Requirements
- Node.js >= 22.x
- NestJS >= 11.x
- TypeScript >= 5.x
- You'll need to maintain the `/cache-manager` and `cache-manager` packages.
## Installation
```bash
npm install nestjs-security-cli
```
## Quick Start
```typescript
import { MiddlewareConsumer, Module, RequestMethod } from '@nestjs/common'
import { MongooseModule } from '@nestjs/mongoose'
import { SecurityModule, BlacklistedIp, BlacklistedIpSchema, SecurityMiddleware } from 'nestjs-security-cli'
( {
imports: [
SecurityModule.forRootAsync( {
enableAdminPanel: true,
useFactory: () => ({
enableDatabase: true,
defaultBlockDurationHours: 24,
enableAutoBlocking: true
}),
imports: [ MongoDbModule ],
providers: [ ...IpBlockerProvider ]
} )
]
} )
export class AppModule {
configure(consumer: MiddlewareConsumer): void {
consumer
.apply( SecurityMiddleware )
.forRoutes( { path: '*', method: RequestMethod.ALL } )
}
}
```
## DATABASE_CONNECTION provider
if you're needing to use the database connection, and the import options isn't working, you can try to pass it directly
into the providers array.
```text
{
provide: 'DATABASE_CONNECTION',
inject: [ConfigService],
useFactory: (configService: ConfigService): Promise<typeof mongoose> => {
return mongoose.connect(configService.get<string>('DATABASE_HOST'), {
dbName: configService.get<string>('DATABASE_NAME')
})
}
```
## with forRoot
```typescript
import { MiddlewareConsumer, Module, RequestMethod } from '@nestjs/common'
import { ConfigModule, ConfigService } from '@nestjs/config'
import { MongooseModule } from '@nestjs/mongoose'
import { SecurityModule, BlacklistedIp, BlacklistedIpSchema } from 'nestjs-security-cli'
( {
imports: [
ConfigModule.forRoot(),
MongoDbModule,
SecurityModule.forRoot( {
enableDatabase: true,
defaultBlockDurationHours: 24,
enableAutoBlocking: true,
enableAdminPanel: true,
} ),
],
providers: [ ...IpBlockerProvider ], // Required if enableDatabase is true
} )
export class AppModule {
}
export class AppModule {
configure(consumer: MiddlewareConsumer): void {
consumer
.apply( SecurityMiddleware )
.forRoutes( { path: '*', method: RequestMethod.ALL } )
}
}
```
## Cache-Only Mode (No Database)
If you don't want to use MongoDB, you can skip the schema registration:
```typescript
import { Module } from '@nestjs/common'
import { SecurityModule } from 'nestjs-security-cli'
( {
imports: [
SecurityModule.forRoot( {
enableDatabase: false, // This will use only cache
defaultBlockDurationHours: 24,
enableAutoBlocking: true
} )
]
} )
export class AppModule {
configure(consumer: MiddlewareConsumer): void {
consumer
.apply( SecurityMiddleware )
.forRoutes( { path: '*', method: RequestMethod.ALL } )
}
}
````
## SecurityService
Since this has switched to using the ` ('IP_BLOCKER')` model to be registered in your app. So by passing the
IpBlockerProvider, it will automatically register the model. More on this down below.
## Clean up cron
There's a cron that runs to clean up old blocks. By default, it runs every 10 minutes. You can change this by setting
the
`CLEANUP_CRON` environment variable.
```text
// Cleanup expired entries (runs daily)
(CronExpression.EVERY_DAY_AT_MIDNIGHT)
async cleanupExpiredBlocks(): Promise<void> {
const result = await this.blacklistedIpModel.updateMany(
{ active: true, expiresAt: { $lt: new Date() } },
{ active: false }
)
console.log(`๐งน Cleaned up ${result.modifiedCount} expired IP blocks`)
}
```
## Role type
The roles that can be defined in your app. Persist the roles in your user model as an array of strings.
```text
export type Role = 'Admin' | 'User' | 'Moderator' | 'Guest'
```
## Register the IpBlacklistGuard globally
```typescript
import { Module, APP_GUARD } from '@nestjs/common'
/* other imports */
import { IpBlacklistGuard } from 'nestjs-security-cli'
( {
imports: [
/* other imports */
],
providers: [
{
provide: APP_GUARD,
useClass: IpBlacklistGuard // Register globally
}
]
} )
export class AppModule {
}
```
And then in your controllers simply use the ` (IpBlacklistGuard)` decorator.
## Admin & Roles guards
* The Admin guard accepts ONLY users with the role `Admin`.
* The Role guard accepts users with ane of (or all) the type "Roles" [as mentioned above](#role-type).
* To leverage the admin panel, you'll need to create a role called `Admin`. The user model in your app should have a
field called "Roles", which is an array of strings.
To use the `AdminGuard` just add the decorator to your controller method.
```typescript
( AdminGuard )
( 'my-contoller' )
```
To use the `RoleGuard` just add the decorator to your controller method.
```typescript
( 'Admin', 'User' )
( RoleGuard )
```
The `AdminGuard` uses both `JwtService` and `ConfigService` to verify the JWT token. So if you're using this in your
app,
just make sure that the env var is `JWT_SECRET` and this will work. ( This could be dynamic later ). Also, when passing
the token to the methods, you'll need to pass the token as `access_token` in either the request cookies,
or the header authorization bearer token.
```typescript
const user = await this.jwtService.verifyAsync( token, {
secret: this.configService.get<string>( 'JWT_SECRET' )
} )
```
## The admin panel
To use the built-in admin panel, you can set the `enableAdminPanel: true` in the
configs [as shown in the](#quick-start) to set the available endpoints.
Available endpoints:
- POST `/security/blacklist`. This will accept a JSON object with the following fields:
- `ip`: The IP address to blacklist
- `hours`: The duration of the blacklist in hours
- `reason`: The reason for the blacklist
- GET `/security/blacklist`. This will return a list of all blacklisted IPs
- GET `/security/blacklist/:ip`. This will return the details of a specific IP address
- DELETE `/security/blacklist/:ip`. This will delete a specific IP address
- GET `/security/analytics`. This will return analytics for the last 24 hours
## Features
- ๐ก๏ธ IP Blacklisting with MongoDB persistence
- ๐ซ Automatic attack pattern detection
- โก Redis/Memory caching for fast lookups
- ๐ฅ Role-based access control (RBAC)
- ๐ Security analytics and reporting
- โฐ Scheduled cleanup of expired blocks
## Configuration Options
```typescript
export interface SecurityConfigInterface {
enableDatabase?: boolean
mongooseConnection?: string
cache?: {
ttl?: number
max?: number
store?: any
}
enableAdminPanel?: boolean
adminPath?: string
enableAutoBlocking?: boolean
suspiciousPatterns?: Array<{
pattern: string
name: string
blockDurationHours?: number
}>
defaultBlockDurationHours?: number
enableRateLimit?: boolean
rateLimitOptions?: {
windowMs?: number
max?: number
}
enableLogging?: boolean
logLevel?: 'error' | 'warn' | 'info' | 'debug'
}
```
## API Documentation
[coming soon]
## License
MIT