Skip to content

Commit

Permalink
Merge pull request #65 from bcgov/feat/security-audit-log
Browse files Browse the repository at this point in the history
Security Audit Logs
  • Loading branch information
hannah-macdonald1 authored Jan 8, 2025
2 parents f71cf09 + 6083060 commit 0b51c50
Show file tree
Hide file tree
Showing 6 changed files with 106 additions and 32 deletions.
41 changes: 26 additions & 15 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"luxon": "^3.5.0",
"nestjs-pino": "^4.1.0",
"pino-http": "^10.3.0",
"pino-std-serializers": "^7.0.0",
"reflect-metadata": "^0.2.0",
"rxjs": "^7.8.1",
"save": "^2.9.0"
Expand Down
52 changes: 52 additions & 0 deletions src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ import { HelpersModule } from './helpers/helpers.module';
import { LoggerModule } from 'nestjs-pino';
import { CacheModule } from '@nestjs/cache-manager';
import { ExternalApiModule } from './external-api/external-api.module';
import {
wrapRequestSerializer,
wrapResponseSerializer,
} from 'pino-std-serializers';

@Module({
imports: [
Expand All @@ -23,15 +27,63 @@ import { ExternalApiModule } from './external-api/external-api.module';
customSuccessObject: (req, res, loggableObject) => {
return {
...loggableObject,
res,
buildNumber: configService.get('buildInfo.buildNumber'),
};
},
customErrorObject: (req, res, loggableObject) => {
return {
...loggableObject,
res,
buildNumber: configService.get('buildInfo.buildNumber'),
};
},
customReceivedObject: (req, res, loggableObject) => {
return {
...loggableObject,
buildNumber: configService.get('buildInfo.buildNumber'),
msg: 'Request received',
};
},
serializers: {
req: wrapRequestSerializer((req) => {
return {
id: req.raw.id,
method: req.raw.method,
path: req.raw.url,
query: req.query,
params: req.params,
// Allowlist useful headers
headers: {
host: req.raw.headers.host,
connection: req.raw.headers.connection,
'x-forwarded-proto': req.raw.headers['x-forwarded-proto'],
'x-forwarded-host': req.raw.headers['x-forwarded-host'],
'x-forwarded-port': req.raw.headers['x-forwarded-port'],
'x-forwarded-path': req.raw.headers['x-forwarded-path'],
'x-real-ip': req.raw.headers['x-real-ip'],
'user-agent': req.raw.headers['user-agent'],
accept: req.raw.headers.accept,
'accept-language': req.raw.headers['accept-language'],
'x-credential-identifier':
req.raw.headers['x-credential-identifier'],
'x-idir-username': req.raw.headers['x-idir-username'],
'x-authenticated-groups':
req.raw.headers['x-authenticated-groups'],
'kong-request-id': req.raw.headers['kong-request-id'],
referer: req.raw.headers.referer,
},
remoteAddress: req.remoteAddress,
remotePort: req.remotePort,
};
}),
res: wrapResponseSerializer((res) => {
return {
statusCode: res.raw.statusCode,
headers: res.headers,
};
}),
},
},
}),
}),
Expand Down
19 changes: 17 additions & 2 deletions src/common/guards/auth/auth.guard.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import {
CanActivate,
ExecutionContext,
Injectable,
Logger,
} from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { AuthService } from './auth.service';

@Injectable()
export class AuthGuard implements CanActivate {
skip;
private readonly logger = new Logger(AuthGuard.name);
constructor(
private readonly authService: AuthService,
private readonly configService: ConfigService,
Expand All @@ -20,6 +26,15 @@ export class AuthGuard implements CanActivate {
const request = context.switchToHttp().getRequest();
const controllerPath =
Reflect.getMetadata('path', context.getClass()) || '';
return await this.authService.getRecordAndValidate(request, controllerPath);
const isAuthorized = await this.authService.getRecordAndValidate(
request,
controllerPath,
);
if (isAuthorized) {
this.logger.log({ msg: `Auth status: 200`, authStatusCode: 200 });
} else {
this.logger.log({ msg: `Auth status: 403`, authStatusCode: 403 });
}
return isAuthorized;
}
}
21 changes: 10 additions & 11 deletions src/common/guards/auth/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,12 @@ export class AuthService {
if (upstreamResult === undefined) {
this.logger.log(`Cache not hit, going upstream...`);
upstreamResult = await this.getAssignedIdirUpstream(id, recordType);
await this.cacheManager.set(key, upstreamResult, this.cacheTime);
if (upstreamResult !== null) {
await this.cacheManager.set(key, upstreamResult, this.cacheTime);
}
this.logger.log(`Upstream result: '${upstreamResult}'`);
} else {
this.logger.log(`Cache hit! Result: ${upstreamResult}`);
this.logger.log(`Cache hit! Result: '${upstreamResult}'`);
}
if (upstreamResult !== idir) {
return false;
Expand Down Expand Up @@ -118,16 +121,12 @@ export class AuthService {
response = await firstValueFrom(
this.httpService.get(url, { params, headers }),
);
this.logger.log(response);
const idir =
response.data['items'][0][
this.configService.get<string>(`upstreamAuth.${recordType}.idirField`)
];
this.logger.log(idir);
const fieldName = this.configService.get<string>(
`upstreamAuth.${recordType}.idirField`,
);
const idir = response.data['items'][0][`${fieldName}`];
if (idir === undefined) {
this.logger.error(
`${this.configService.get<string>(`upstreamAuth.${recordType}.idirField`)} field not found in request`,
);
this.logger.error(`${fieldName} field not found in request`);
return null;
}
return idir;
Expand Down
4 changes: 0 additions & 4 deletions src/external-api/token-refresher/token-refresher.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,6 @@ export class TokenRefresherService {
response = await firstValueFrom(
this.httpService.post(this.accessTokenUrl, data, { headers }),
);
this.logger.log({
functionName: 'authenticateUpstream',
data: response.data,
});
const access_token = response.data['access_token'];
const token_type = response.data['token_type'];
const expirySeconds = response.data['expires_in'];
Expand Down

0 comments on commit 0b51c50

Please sign in to comment.