Skip to content

Commit

Permalink
Move bootstrap to the policy engine top level module
Browse files Browse the repository at this point in the history
Check encryption configuration at the bootstrap.
  • Loading branch information
wcalderipe committed Mar 21, 2024
1 parent 094e414 commit 9fbfc98
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 13 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { EncryptionException, EncryptionService } from '@narval/encryption-module'
import { ConfigModule } from '@nestjs/config'
import { Test } from '@nestjs/testing'
import { MockProxy, mock } from 'jest-mock-extended'
Expand All @@ -7,12 +8,14 @@ import { load } from '../../../../../policy-engine.config'
import { KeyValueRepository } from '../../../../../shared/module/key-value/core/repository/key-value.repository'
import { KeyValueService } from '../../../../../shared/module/key-value/core/service/key-value.service'
import { InMemoryKeyValueRepository } from '../../../../../shared/module/key-value/persistence/repository/in-memory-key-value.repository'
import { getTestRawAesKeyring } from '../../../../../shared/testing/encryption.testing'
import { BootstrapService } from '../../bootstrap.service'
import { TenantService } from '../../tenant.service'

describe(BootstrapService.name, () => {
let bootstrapService: BootstrapService
let tenantServiceMock: MockProxy<TenantService>
let encryptionServiceMock: MockProxy<EncryptionService>

const dataStore = {
entity: {
Expand Down Expand Up @@ -47,6 +50,9 @@ describe(BootstrapService.name, () => {
tenantServiceMock = mock<TenantService>()
tenantServiceMock.findAll.mockResolvedValue([tenantOne, tenantTwo])

encryptionServiceMock = mock<EncryptionService>()
encryptionServiceMock.getKeyring.mockReturnValue(getTestRawAesKeyring())

const module = await Test.createTestingModule({
imports: [
ConfigModule.forRoot({
Expand All @@ -66,6 +72,10 @@ describe(BootstrapService.name, () => {
{
provide: TenantService,
useValue: tenantServiceMock
},
{
provide: EncryptionService,
useValue: encryptionServiceMock
}
]
}).compile()
Expand All @@ -80,5 +90,19 @@ describe(BootstrapService.name, () => {
expect(tenantServiceMock.syncDataStore).toHaveBeenNthCalledWith(1, tenantOne.clientId)
expect(tenantServiceMock.syncDataStore).toHaveBeenNthCalledWith(2, tenantTwo.clientId)
})

it('checks if the encryption keyring is configured', async () => {
await bootstrapService.boot()

expect(encryptionServiceMock.getKeyring).toHaveBeenCalledTimes(1)
})

it('throws when encryption keyring is not configure', async () => {
encryptionServiceMock.getKeyring.mockImplementation(() => {
throw new EncryptionException('Something went wrong')
})

await expect(() => bootstrapService.boot()).rejects.toThrow('Something went wrong')
})
})
})
23 changes: 22 additions & 1 deletion apps/policy-engine/src/engine/core/service/bootstrap.service.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { EncryptionService } from '@narval/encryption-module'
import { FIXTURE } from '@narval/policy-engine-shared'
import { Injectable, Logger } from '@nestjs/common'
import { randomBytes } from 'crypto'
Expand All @@ -7,11 +8,16 @@ import { TenantService } from './tenant.service'
export class BootstrapService {
private logger = new Logger(BootstrapService.name)

constructor(private tenantService: TenantService) {}
constructor(
private tenantService: TenantService,
private encryptionService: EncryptionService
) {}

async boot(): Promise<void> {
this.logger.log('Start engine bootstrap')

await this.checkEncryptionConfiguration()

if (!(await this.tenantService.findByClientId(FIXTURE.ORGANIZATION.id))) {
await this.tenantService.onboard({
clientId: FIXTURE.ORGANIZATION.id,
Expand All @@ -36,6 +42,21 @@ export class BootstrapService {
await this.syncTenants()
}

private async checkEncryptionConfiguration(): Promise<void> {
this.logger.log('Check encryption configuration')

try {
this.encryptionService.getKeyring()
this.logger.log('Encryption keyring configured')
} catch (error) {
this.logger.error(
'Missing encryption keyring. Please provision the application with "make policy-engine/cli CMD=provision"'
)

throw error
}
}

private async syncTenants(): Promise<void> {
const tenants = await this.tenantService.findAll()

Expand Down
12 changes: 3 additions & 9 deletions apps/policy-engine/src/engine/engine.module.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { EncryptionModule } from '@narval/encryption-module'
import { HttpModule } from '@nestjs/axios'
import { Module, OnApplicationBootstrap, ValidationPipe } from '@nestjs/common'
import { Module, ValidationPipe } from '@nestjs/common'
import { ConfigModule, ConfigService } from '@nestjs/config'
import { APP_PIPE } from '@nestjs/core'
import { load } from '../policy-engine.config'
Expand Down Expand Up @@ -56,12 +56,6 @@ import { TenantRepository } from './persistence/repository/tenant.repository'
useClass: ValidationPipe
}
],
exports: [EngineService, ProvisionService]
exports: [EngineService, ProvisionService, BootstrapService]
})
export class EngineModule implements OnApplicationBootstrap {
constructor(private bootstrapService: BootstrapService) {}

async onApplicationBootstrap() {
await this.bootstrapService.boot()
}
}
export class EngineModule {}
12 changes: 9 additions & 3 deletions apps/policy-engine/src/policy-engine.module.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { EncryptionModule } from '@narval/encryption-module'
import { Module, ValidationPipe } from '@nestjs/common'
import { Module, OnApplicationBootstrap, ValidationPipe } from '@nestjs/common'
import { ConfigModule, ConfigService } from '@nestjs/config'
import { APP_PIPE } from '@nestjs/core'
import { BootstrapService } from './engine/core/service/bootstrap.service'
import { EngineService } from './engine/core/service/engine.service'
import { EngineModule } from './engine/engine.module'
import { load } from './policy-engine.config'
Expand All @@ -22,7 +23,6 @@ import { EncryptionModuleOptionFactory } from './shared/factory/encryption-modul

// Domain
EngineModule
// TenantModule
],
providers: [
{
Expand All @@ -31,4 +31,10 @@ import { EncryptionModuleOptionFactory } from './shared/factory/encryption-modul
}
]
})
export class PolicyEngineModule {}
export class PolicyEngineModule implements OnApplicationBootstrap {
constructor(private bootstrapService: BootstrapService) {}

async onApplicationBootstrap() {
await this.bootstrapService.boot()
}
}

0 comments on commit 9fbfc98

Please sign in to comment.