Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/stage-3-build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,6 @@ jobs:
- name: "Checkout code"
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
- name: "Build docs"
uses: NHSDigital/nhs-notify-shared-modules/.github/actions/build-docs@3.0.0
uses: NHSDigital/nhs-notify-shared-modules/.github/actions/build-docs@3.1.3
with:
version: "${{ inputs.version }}"
4 changes: 2 additions & 2 deletions docs/Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ GEM
ast (2.4.3)
base64 (0.3.0)
bigdecimal (4.1.2)
cgi (0.5.0)
cgi (0.5.1)
colorator (1.1.0)
concurrent-ruby (1.3.6)
connection_pool (3.0.2)
Expand All @@ -28,7 +28,7 @@ GEM
em-websocket (0.5.3)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0)
erb (4.0.4)
erb (4.0.4.1)
cgi (>= 0.3.3)
eventmachine (1.2.7)
ffi (1.17.2-aarch64-linux-gnu)
Expand Down
3 changes: 1 addition & 2 deletions lambdas/key-generation/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@
"dependencies": {
"date-fns": "^4.1.0",
"esbuild": "^0.25.9",
"node-jose": "^2.2.0",
"jose": "^5.10.0",
"utils": "*"
},
"devDependencies": {
"@tsconfig/node22": "^22.0.2",
"@types/aws-lambda": "^8.10.148",
"@types/jest": "^29.5.14",
"@types/node": "^24.0.10",
"@types/node-jose": "^1.1.13",
"jest": "^29.7.0",
"jest-mock-extended": "^3.0.7",
"typescript": "^5.8.2"
Expand Down
35 changes: 18 additions & 17 deletions lambdas/key-generation/src/__tests__/refresh-keystores.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { JWK } from 'node-jose';
import {
Key,
createKeyStore,
deleteKey,
generateNewKey,
logger,
Expand All @@ -10,7 +11,6 @@ import {
import { cleanAndRefreshKeystores } from 'refresh-keystores';
import { loadConfig } from 'config';

jest.mock('node-jose');
jest.mock('utils', () => {
const originalModule = jest.requireActual('utils');

Expand All @@ -19,6 +19,7 @@ jest.mock('utils', () => {
parameterStore: {
getAllParameters: jest.fn(),
},
createKeyStore: jest.fn(),
deleteKey: jest.fn(),
generateNewKey: jest.fn(),
uploadPublicKeystoreToS3: jest.fn(),
Expand All @@ -30,10 +31,10 @@ jest.mock('config');
const setupMocks = (preExistingKeys?: string[]) => {
const mockKeyStore = {
add: jest.fn(),
all: jest.fn().mockReturnValue(['']),
all: jest.fn().mockReturnValue([{ toJSON: () => ({ kid: 'mock-kid' }) }]),
};

(JWK.createKeyStore as jest.Mock).mockImplementation(() => mockKeyStore);
(createKeyStore as jest.Mock).mockImplementation(() => mockKeyStore);

(loadConfig as jest.Mock).mockReturnValue({
environment: 'env',
Expand Down Expand Up @@ -94,7 +95,7 @@ describe('cleanAndRefreshKeystores', () => {

mockValidatePrivateKey.mockResolvedValue({
valid: true,
keyJwk: {} as JWK.Key,
keyJwk: {} as unknown as Key,
keyDate: new Date('2021-02-24'),
});

Expand Down Expand Up @@ -127,7 +128,7 @@ describe('cleanAndRefreshKeystores', () => {

mockValidatePrivateKey.mockResolvedValue({
valid: false,
keyJwk: {} as JWK.Key,
keyJwk: {} as unknown as Key,
keyDate: new Date('2021-02-24'),
});

Expand Down Expand Up @@ -160,7 +161,7 @@ describe('cleanAndRefreshKeystores', () => {

mockValidatePrivateKey.mockResolvedValue({
valid: true,
keyJwk: {} as JWK.Key,
keyJwk: {} as unknown as Key,
keyDate: new Date('2021-02-23'),
});

Expand Down Expand Up @@ -195,7 +196,7 @@ describe('cleanAndRefreshKeystores', () => {

mockValidatePrivateKey.mockResolvedValue({
valid: true,
keyJwk: {} as JWK.Key,
keyJwk: {} as unknown as Key,
keyDate: new Date('2024-07-27'),
});

Expand Down Expand Up @@ -236,7 +237,7 @@ describe('cleanAndRefreshKeystores', () => {

mockValidatePrivateKey.mockResolvedValue({
valid: true,
keyJwk: {} as JWK.Key,
keyJwk: {} as unknown as Key,
keyDate: new Date('2024-06-30'),
});

Expand Down Expand Up @@ -279,12 +280,12 @@ describe('cleanAndRefreshKeystores', () => {
mockValidatePrivateKey
.mockResolvedValueOnce({
valid: false,
keyJwk: {} as JWK.Key,
keyJwk: {} as unknown as Key,
keyDate: new Date('2024-07-30'),
})
.mockResolvedValueOnce({
valid: true,
keyJwk: {} as JWK.Key,
keyJwk: {} as unknown as Key,
keyDate: new Date('2024-08-27'),
});

Expand Down Expand Up @@ -332,7 +333,7 @@ describe('cleanAndRefreshKeystores', () => {

mockValidatePrivateKey.mockResolvedValue({
valid: true,
keyJwk: { kid: 'key-1' } as JWK.Key,
keyJwk: { kid: 'key-1' } as unknown as Key,
keyDate: new Date('2024-09-01'), // 24 days old < 28 days threshold
});

Expand Down Expand Up @@ -361,12 +362,12 @@ describe('cleanAndRefreshKeystores', () => {
mockValidatePrivateKey
.mockResolvedValueOnce({
valid: true,
keyJwk: { kid: 'key1' } as JWK.Key,
keyJwk: { kid: 'key1' } as unknown as Key,
keyDate: new Date('2024-07-15'), // newer key first
})
.mockResolvedValueOnce({
valid: true,
keyJwk: { kid: 'key2' } as JWK.Key,
keyJwk: { kid: 'key2' } as unknown as Key,
keyDate: new Date('2024-06-01'), // older key second — should not update youngestKeyDate
});

Expand All @@ -390,12 +391,12 @@ describe('cleanAndRefreshKeystores', () => {
mockValidatePrivateKey
.mockResolvedValueOnce({
valid: true,
keyJwk: { kid: 'key1' } as JWK.Key,
keyJwk: { kid: 'key1' } as unknown as Key,
keyDate: new Date('2024-06-01'),
})
.mockResolvedValueOnce({
valid: true,
keyJwk: { kid: 'key2' } as JWK.Key,
keyJwk: { kid: 'key2' } as unknown as Key,
keyDate: new Date('2024-07-15'), // later
});

Expand All @@ -415,7 +416,7 @@ describe('cleanAndRefreshKeystores', () => {

mockValidatePrivateKey.mockResolvedValue({
valid: false,
keyJwk: { kid: 'ignored' } as JWK.Key,
keyJwk: { kid: 'ignored' } as unknown as Key,
keyDate: new Date('2000-01-01'),
});

Expand Down
6 changes: 3 additions & 3 deletions lambdas/key-generation/src/refresh-keystores.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { JWK } from 'node-jose';
import { isBefore, subDays } from 'date-fns';
import {
NonNullSSMParam,
createKeyStore,
deleteKey,
generateNewKey,
logger,
Expand All @@ -23,7 +23,7 @@ const deleteInvalidKeysAndCreateKeystore = async ({
now,
ssmPath,
}: DeleteInvalidKeysAndCreateKeystoreParams) => {
const keystore = JWK.createKeyStore();
const keystore = createKeyStore();
let youngestKeyDate: Date | null = null;

const allParams = await parameterStore.getAllParameters(ssmPath);
Expand Down Expand Up @@ -104,6 +104,6 @@ export const cleanAndRefreshKeystores = async ({
logger.info({
description: `Email auth keygen refresh complete: current key IDs: ${keystore
.all()
.map((key) => key.kid)}`,
.map((key) => key.toJSON().kid)}`,
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
import { randomUUID } from 'node:crypto';

jest.mock('node:crypto', () => ({
...jest.requireActual('node:crypto'),
randomUUID: jest.fn(),
}));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const logger = mock<Logger>();
const eventPublisher = mock<EventPublisher>();

jest.mock('node:crypto', () => ({
...jest.requireActual('node:crypto'),
randomUUID: jest.fn(),
}));

Expand Down
Loading
Loading