add security headers and CORS
This commit is contained in:
parent
1223bcbb19
commit
36e9789070
|
@ -31,6 +31,7 @@
|
|||
"bcrypt": "^5.0.1",
|
||||
"class-transformer": "^0.5.1",
|
||||
"class-validator": "^0.13.2",
|
||||
"fastify-helmet": "^7.0.1",
|
||||
"fastify-multipart": "^5.3.1",
|
||||
"fastify-static": "^4.6.1",
|
||||
"file-type": "^17.1.1",
|
||||
|
|
|
@ -4,6 +4,7 @@ import {
|
|||
FastifyAdapter,
|
||||
NestFastifyApplication
|
||||
} from '@nestjs/platform-fastify';
|
||||
import fastifyHelmet from 'fastify-helmet';
|
||||
import * as multipart from 'fastify-multipart';
|
||||
import { ValidateOptions } from 'picsur-shared/dist/util/validate';
|
||||
import { AppModule } from './app.module';
|
||||
|
@ -13,12 +14,14 @@ import { MainExceptionFilter } from './layers/httpexception/httpexception.filter
|
|||
import { SuccessInterceptor } from './layers/success/success.interceptor';
|
||||
import { PicsurLoggerService } from './logger/logger.service';
|
||||
import { MainAuthGuard } from './managers/auth/guards/main.guard';
|
||||
import { HelmetOptions } from './security';
|
||||
|
||||
async function bootstrap() {
|
||||
// Create fasify
|
||||
const fastifyAdapter = new FastifyAdapter();
|
||||
// TODO: generic error messages
|
||||
fastifyAdapter.register(multipart as any);
|
||||
await fastifyAdapter.register(multipart as any);
|
||||
await fastifyAdapter.register(fastifyHelmet, HelmetOptions);
|
||||
|
||||
// Create nest app
|
||||
const app = await NestFactory.create<NestFastifyApplication>(
|
||||
|
@ -28,16 +31,16 @@ async function bootstrap() {
|
|||
bufferLogs: true,
|
||||
},
|
||||
);
|
||||
// app.enableCors({
|
||||
// origin: 'self'
|
||||
// });
|
||||
|
||||
// Configure nest app
|
||||
app.useGlobalFilters(new MainExceptionFilter());
|
||||
app.useGlobalInterceptors(new SuccessInterceptor());
|
||||
app.useGlobalPipes(new ValidationPipe(ValidateOptions));
|
||||
app.useGlobalGuards(
|
||||
new MainAuthGuard(
|
||||
app.get(Reflector),
|
||||
app.get(UsersService),
|
||||
),
|
||||
new MainAuthGuard(app.get(Reflector), app.get(UsersService)),
|
||||
);
|
||||
|
||||
// Configure logger
|
||||
|
|
|
@ -17,6 +17,7 @@ import { Permission } from '../../models/dto/permissions.dto';
|
|||
import { ImageUploadDto } from '../../models/requests/imageroute.dto';
|
||||
import { ImageIdValidator } from './imageid.validator';
|
||||
|
||||
// This is the only controller with CORS enabled
|
||||
@Controller('i')
|
||||
@RequiredPermissions(Permission.ImageView)
|
||||
export class ImageController {
|
||||
|
|
|
@ -1,12 +1,22 @@
|
|||
import { Module } from '@nestjs/common';
|
||||
import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
|
||||
import cors from 'cors';
|
||||
import { DecoratorsModule } from '../../decorators/decorators.module';
|
||||
import { ImageManagerModule } from '../../managers/imagemanager/imagemanager.module';
|
||||
import { ImageIdValidator } from './imageid.validator';
|
||||
import { ImageController } from './imageroute.controller';
|
||||
|
||||
const corsConfig = cors({
|
||||
// 48 hours
|
||||
maxAge: 1728000,
|
||||
});
|
||||
|
||||
@Module({
|
||||
imports: [ImageManagerModule, DecoratorsModule],
|
||||
providers: [ImageIdValidator],
|
||||
controllers: [ImageController],
|
||||
})
|
||||
export class ImageModule {}
|
||||
export class ImageModule implements NestModule {
|
||||
configure(consumer: MiddlewareConsumer) {
|
||||
consumer.apply(corsConfig).forRoutes('/i');
|
||||
}
|
||||
}
|
||||
|
|
45
backend/src/security.ts
Normal file
45
backend/src/security.ts
Normal file
|
@ -0,0 +1,45 @@
|
|||
import { FastifyHelmetOptions } from 'fastify-helmet';
|
||||
|
||||
export const HelmetOptions: FastifyHelmetOptions = {
|
||||
contentSecurityPolicy: {
|
||||
directives: {
|
||||
'default-src': ["'self'"],
|
||||
'base-uri': ["'self'"],
|
||||
'block-all-mixed-content': [],
|
||||
'form-action': ["'self'"],
|
||||
'frame-ancestors': ["'self'"],
|
||||
'img-src': ["'self'", 'data:', 'blob:'],
|
||||
'object-src': ["'none'"],
|
||||
'script-src': ["'self'"],
|
||||
'style-src': ["'self'", "'unsafe-inline'"],
|
||||
'upgrade-insecure-requests': [],
|
||||
},
|
||||
useDefaults: false,
|
||||
reportOnly: false,
|
||||
},
|
||||
// Require any external content to have CORS set
|
||||
crossOriginEmbedderPolicy: true,
|
||||
// Destroy reference to global object on new page
|
||||
crossOriginOpenerPolicy: true,
|
||||
crossOriginResourcePolicy: true,
|
||||
// Dont fully understand the purpose of this
|
||||
// But pretty sure we dont need it
|
||||
expectCt: false,
|
||||
// Do not send referrer header
|
||||
referrerPolicy: true,
|
||||
// Ensure browser doesnt connect with HTTP
|
||||
hsts: true,
|
||||
noSniff: true,
|
||||
originAgentCluster: true,
|
||||
// Prevent prefetching of dns
|
||||
dnsPrefetchControl: true,
|
||||
// We aint targeting IE, but it cant hurt
|
||||
ieNoOpen: true,
|
||||
// Only allow in iframe of same origin
|
||||
frameguard: true,
|
||||
permittedCrossDomainPolicies: true,
|
||||
hidePoweredBy: true,
|
||||
// Requires nonce for every stylesheet, this is too much work so we disable it
|
||||
enableCSPNonces: false,
|
||||
xssFilter: true,
|
||||
};
|
13
yarn.lock
13
yarn.lock
|
@ -4029,6 +4029,14 @@ fastify-formbody@5.2.0:
|
|||
dependencies:
|
||||
fastify-plugin "^3.0.0"
|
||||
|
||||
fastify-helmet@^7.0.1:
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/fastify-helmet/-/fastify-helmet-7.0.1.tgz#506c288dc5a5bea4d7332c1b5aed8f69a3fe383b"
|
||||
integrity sha512-/PSKDJZkBhJ0ioY1swOUfYNYQRfRnXD5X2eKD9TSVBuPKbH+OYg/IYBxad33uaOGlWn28MNOd+kw5sQKSWY1yA==
|
||||
dependencies:
|
||||
fastify-plugin "^3.0.0"
|
||||
helmet "^5.0.1"
|
||||
|
||||
fastify-multipart@^5.3.1:
|
||||
version "5.3.1"
|
||||
resolved "https://registry.yarnpkg.com/fastify-multipart/-/fastify-multipart-5.3.1.tgz#05254d8aa43dc02af6ce01f4e513a6c30bea2886"
|
||||
|
@ -4462,6 +4470,11 @@ hdr-histogram-percentiles-obj@^3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/hdr-histogram-percentiles-obj/-/hdr-histogram-percentiles-obj-3.0.0.tgz#9409f4de0c2dda78e61de2d9d78b1e9f3cba283c"
|
||||
integrity sha512-7kIufnBqdsBGcSZLPJwqHT3yhk1QTsSlFsVD3kx5ixH/AlgBs9yM1q6DPhXZ8f8gtdqgh7N7/5btRLpQsS2gHw==
|
||||
|
||||
helmet@^5.0.1:
|
||||
version "5.0.2"
|
||||
resolved "https://registry.yarnpkg.com/helmet/-/helmet-5.0.2.tgz#3264ec6bab96c82deaf65e3403c369424cb2366c"
|
||||
integrity sha512-QWlwUZZ8BtlvwYVTSDTBChGf8EOcQ2LkGMnQJxSzD1mUu8CCjXJZq/BXP8eWw4kikRnzlhtYo3lCk0ucmYA3Vg==
|
||||
|
||||
hexoid@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/hexoid/-/hexoid-1.0.0.tgz#ad10c6573fb907de23d9ec63a711267d9dc9bc18"
|
||||
|
|
Loading…
Reference in a new issue