Skip to content

Commit ae4553a

Browse files
committed
CCM-11600: header references, format, name consistency
1 parent 096fe7d commit ae4553a

5 files changed

Lines changed: 41 additions & 39 deletions

File tree

infrastructure/terraform/components/api/module_authorizer_lambda.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ module "authorizer_lambda" {
3838
lambda_env_vars = {
3939
CLOUDWATCH_NAMESPACE = "/aws/api-gateway/supplier/alarms",
4040
CLIENT_CERTIFICATE_EXPIRATION_ALERT_DAYS = 14,
41-
APIM_APPLICATION_ID_HEADER = "NHSD-Supplier-ID",
41+
APIM_SUPPLIER_ID_HEADER = "NHSD-Supplier-ID",
4242
SUPPLIERS_TABLE_NAME = aws_dynamodb_table.suppliers.name
4343
}
4444
}

infrastructure/terraform/components/api/resources/spec.tmpl.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"securitySchemes": {
44
"LambdaAuthorizer": {
55
"in": "header",
6-
"name": "apim-application-id",
6+
"name": "NHSD-Supplier-ID",
77
"type": "apiKey",
88
"x-amazon-apigateway-authorizer": {
99
"authorizerCredentials": "${APIG_EXECUTION_ROLE_ARN}",

lambdas/authorizer/src/__tests__/index.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const mockedDeps: jest.Mocked<Deps> = {
99
env: {
1010
CLOUDWATCH_NAMESPACE: 'cloudwatch-namespace',
1111
CLIENT_CERTIFICATE_EXPIRATION_ALERT_DAYS: 14,
12-
APIM_APPLICATION_ID_HEADER: 'apim-application-id'
12+
APIM_SUPPLIER_ID_HEADER: 'NHSD-Supplier-ID'
1313
} as unknown as EnvVars,
1414
supplierRepo: {
1515
getSupplierByApimId: jest.fn(),
@@ -121,7 +121,7 @@ describe('Authorizer Lambda Function', () => {
121121
}));
122122
});
123123

124-
it('Should deny the request when the APIM application ID header is absent', async () => {
124+
it('Should deny the request when the Supplier ID header is absent', async () => {
125125
mockEvent.headers = {'x-apim-correlation-id': 'correlation-id'};
126126

127127
const handler = createAuthorizerHandler(mockedDeps);
@@ -140,7 +140,7 @@ describe('Authorizer Lambda Function', () => {
140140
});
141141

142142
it('Should deny the request when no supplier ID is found', async () => {
143-
mockEvent.headers = { 'apim-application-id': 'unknown-apim-id' };
143+
mockEvent.headers = { 'NHSD-Supplier-ID': 'unknown-apim-id' };
144144
(mockedDeps.supplierRepo.getSupplierByApimId as jest.Mock).mockRejectedValue(new Error('Supplier not found'));
145145

146146
const handler = createAuthorizerHandler(mockedDeps);
@@ -159,7 +159,7 @@ describe('Authorizer Lambda Function', () => {
159159
});
160160

161161
it('Should allow the request when the supplier ID is found', async () => {
162-
mockEvent.headers = { 'apim-application-id': 'valid-apim-id' };
162+
mockEvent.headers = { 'NHSD-Supplier-ID': 'valid-apim-id' };
163163
(mockedDeps.supplierRepo.getSupplierByApimId as jest.Mock).mockResolvedValue({
164164
id: 'supplier-123',
165165
apimApplicationId: 'valid-apim-id',
@@ -184,7 +184,7 @@ describe('Authorizer Lambda Function', () => {
184184
});
185185

186186
it('Should allow the request when the supplier ID case mismatches', async () => {
187-
mockEvent.headers = { 'apim-application-id': 'Valid-Apim-Id' };
187+
mockEvent.headers = { 'NHSD-Supplier-ID': 'Valid-Apim-Id' };
188188
(mockedDeps.supplierRepo.getSupplierByApimId as jest.Mock).mockResolvedValue({
189189
id: 'supplier-123',
190190
apimApplicationId: 'valid-apim-id',
@@ -211,7 +211,7 @@ describe('Authorizer Lambda Function', () => {
211211
});
212212

213213
it('Should deny the request the supplier is disabled', async () => {
214-
mockEvent.headers = { 'apim-application-id': 'unknown-apim-id' };
214+
mockEvent.headers = { 'NHSD-Supplier-ID': 'unknown-apim-id' };
215215
(mockedDeps.supplierRepo.getSupplierByApimId as jest.Mock).mockResolvedValue({
216216
id: 'supplier-123',
217217
apimApplicationId: 'valid-apim-id',

lambdas/authorizer/src/authorizer.ts

Lines changed: 32 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1-
import {APIGatewayAuthorizerResult, APIGatewayEventClientCertificate, APIGatewayRequestAuthorizerEvent, APIGatewayRequestAuthorizerEventHeaders, APIGatewayRequestAuthorizerHandler,
2-
Callback, Context } from 'aws-lambda';
1+
import {
2+
APIGatewayAuthorizerResult, APIGatewayEventClientCertificate, APIGatewayRequestAuthorizerEvent, APIGatewayRequestAuthorizerEventHeaders, APIGatewayRequestAuthorizerHandler,
3+
Callback, Context
4+
} from 'aws-lambda';
35
import { Deps } from './deps';
46
import { Supplier } from '@internal/datastore';
57

68
export function createAuthorizerHandler(deps: Deps): APIGatewayRequestAuthorizerHandler {
79

8-
return (
10+
return (
911
event: APIGatewayRequestAuthorizerEvent,
1012
context: Context,
1113
callback: Callback<APIGatewayAuthorizerResult>
@@ -29,41 +31,41 @@ export function createAuthorizerHandler(deps: Deps): APIGatewayRequestAuthorizer
2931

3032
async function getSupplier(headers: APIGatewayRequestAuthorizerEventHeaders | null, deps: Deps): Promise<Supplier> {
3133
const apimId = Object.entries(headers || {})
32-
.find(([headerName, _]) => headerName.toLowerCase() === deps.env.APIM_APPLICATION_ID_HEADER.toLowerCase())?.[1] as string;
34+
.find(([headerName, _]) => headerName.toLowerCase() === deps.env.APIM_SUPPLIER_ID_HEADER.toLowerCase())?.[1] as string;
3335

34-
if(!apimId) {
36+
if (!apimId) {
3537
throw new Error('No APIM application ID found in header');
3638
}
3739
const supplier = await deps.supplierRepo.getSupplierByApimId(apimId);
3840
if (supplier.status === 'DISABLED') {
39-
throw new Error(`Supplier ${supplier.id} is disabled`);
41+
throw new Error(`Supplier ${supplier.id} is disabled`);
4042
}
4143
return supplier;
4244
}
4345

4446

45-
// Helper function to generate an IAM policy
46-
function generatePolicy(
47-
principalId: string,
48-
effect: 'Allow' | 'Deny',
49-
resource: string
50-
): APIGatewayAuthorizerResult {
51-
// Required output:
52-
const authResponse: APIGatewayAuthorizerResult = {
53-
principalId,
54-
policyDocument: {
55-
Version: '2012-10-17',
56-
Statement: [
57-
{
58-
Action: 'execute-api:Invoke',
59-
Effect: effect,
60-
Resource: resource,
61-
},
62-
],
63-
},
64-
};
65-
return authResponse;
66-
}
47+
// Helper function to generate an IAM policy
48+
function generatePolicy(
49+
principalId: string,
50+
effect: 'Allow' | 'Deny',
51+
resource: string
52+
): APIGatewayAuthorizerResult {
53+
// Required output:
54+
const authResponse: APIGatewayAuthorizerResult = {
55+
principalId,
56+
policyDocument: {
57+
Version: '2012-10-17',
58+
Statement: [
59+
{
60+
Action: 'execute-api:Invoke',
61+
Effect: effect,
62+
Resource: resource,
63+
},
64+
],
65+
},
66+
};
67+
return authResponse;
68+
}
6769

6870
function generateAllow(resource: string, supplierId: string): APIGatewayAuthorizerResult {
6971
return generatePolicy(supplierId, 'Allow', resource);
@@ -76,7 +78,7 @@ function generateDeny(resource: string): APIGatewayAuthorizerResult {
7678
function getCertificateExpiryInDays(certificate: APIGatewayEventClientCertificate): number {
7779
const now = new Date().getTime();
7880
const expiry = new Date(certificate.validity.notAfter).getTime();
79-
return (expiry - now) / (1000 * 60 * 60 * 24);
81+
return (expiry - now) / (1000 * 60 * 60 * 24);
8082
}
8183

8284
async function checkCertificateExpiry(certificate: APIGatewayEventClientCertificate | null, deps: Deps): Promise<void> {
@@ -117,7 +119,7 @@ async function checkCertificateExpiry(certificate: APIGatewayEventClientCertific
117119
],
118120
},
119121
'SUBJECT_DN': certificate.subjectDN,
120-
'NOT_AFTER': certificate.validity.notAfter,
122+
'NOT_AFTER': certificate.validity.notAfter,
121123
'apim-client-certificate-near-expiry': 1,
122124
};
123125
}

lambdas/authorizer/src/env.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {z} from 'zod';
33
const EnvVarsSchema = z.object({
44
SUPPLIERS_TABLE_NAME: z.string(),
55
CLOUDWATCH_NAMESPACE: z.string(),
6-
APIM_APPLICATION_ID_HEADER: z.string(),
6+
APIM_SUPPLIER_ID_HEADER: z.string(),
77
CLIENT_CERTIFICATE_EXPIRATION_ALERT_DAYS: z.coerce.number().int()
88
});
99

0 commit comments

Comments
 (0)