Skip to content

Commit

Permalink
OLH-1828 - Upgrade the frontend to AWS SDK v3
Browse files Browse the repository at this point in the history
  • Loading branch information
peterfajemisincabinetoffice committed Jun 19, 2024
1 parent e5f3797 commit 4364c7e
Show file tree
Hide file tree
Showing 12 changed files with 750 additions and 3,486 deletions.
4,091 changes: 665 additions & 3,426 deletions package-lock.json

Large diffs are not rendered by default.

10 changes: 6 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,14 @@
},
"dependencies": {
"@aws-crypto/client-node": "^4.0.0",
"@aws-sdk/client-dynamodb": "^3.598.0",
"@aws-sdk/client-sqs": "^3.598.0",
"@aws-sdk/util-dynamodb": "^3.598.0",
"@aws-sdk/client-dynamodb": "^3.600.0",
"@aws-sdk/client-sqs": "^3.600.0",
"@aws-sdk/util-dynamodb": "^3.600.0",
"@aws-sdk/client-kms": "^3.600.0",
"@aws-sdk/client-sns": "^3.600.0",
"@aws-sdk/util-base64-browser": "^3.209.0",
"@govuk-one-login/frontend-analytics": "1.0.3",
"@govuk-one-login/frontend-language-toggle": "^1.1.0",
"aws-sdk": "2.1642.0",
"axios": "^1.7.2",
"base64url": "3.0.1",
"body-parser": "^1.20.2",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
getDynamoActivityLogStoreTableName,
getOIDCClientId,
} from "../../config";
import { DynamoDB } from "aws-sdk";
import { QueryCommandInput } from "@aws-sdk/client-dynamodb";
import { dynamoDBService } from "../../utils/dynamo";
import { getSNSSuspicousActivityTopic } from "../../config";
import { ActivityLogEntry, FormattedActivityLog } from "../../utils/types";
Expand All @@ -15,11 +15,12 @@ import { formatActivityLogs } from "../../utils/activityHistory";
import { decryptData } from "../../utils/decrypt-data";
import { snsService } from "../../utils/sns";
import { getTxmaHeader } from "../../utils/txma-header";
import { unmarshall } from "@aws-sdk/util-dynamodb";

const activityLogDynamoDBRequest = (
subjectId: string,
eventId: string
): DynamoDB.Types.QueryInput => ({
): QueryCommandInput => ({
TableName: getDynamoActivityLogStoreTableName(),
KeyConditionExpression: "user_id = :user_id AND event_id = :event_id ",
ExpressionAttributeValues: {
Expand Down Expand Up @@ -91,9 +92,7 @@ export async function reportSuspiciousActivityGet(
);
return next();
}
activityLog = DynamoDB.Converter.unmarshall(
response.Items[0]
) as ActivityLogEntry;
activityLog = unmarshall(response.Items[0]) as ActivityLogEntry;
} catch (err) {
req.log.error(err.message);
return next(err);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ import { expect } from "chai";
import * as dynamo from "../../../utils/dynamo";
import * as sns from "../../../utils/sns";
import { DynamoDBService } from "../../../utils/types";
import { DynamoDB } from "aws-sdk";
import {
GetItemCommandOutput,
QueryCommandOutput,
} from "@aws-sdk/client-dynamodb";
import { logger } from "../../../utils/logger";
import { AwsConfig } from "../../../config/aws";

Expand All @@ -18,7 +21,7 @@ describe("report suspicious activity controller", () => {
let req: Partial<Request>;
let res: Partial<Response>;
let next: any;
let dynamodbQueryOutput: DynamoDB.Types.QueryOutput;
let dynamodbQueryOutput: QueryCommandOutput;
let loggerSpy: sinon.SinonSpy;
let errorLoggerSpy: sinon.SinonSpy;
let mockDynamoDBService: DynamoDBService;
Expand Down Expand Up @@ -60,6 +63,7 @@ describe("report suspicious activity controller", () => {
};
next = sandbox.fake(() => {});
dynamodbQueryOutput = {
$metadata: undefined,
Items: [
{
event_id: { S: "event-id" },
Expand All @@ -72,10 +76,10 @@ describe("report suspicious activity controller", () => {
],
};
mockDynamoDBService = {
getItem(): Promise<DynamoDB.GetItemOutput> {
getItem(): Promise<GetItemCommandOutput> {
return Promise.resolve(undefined);
},
queryItem(): Promise<DynamoDB.Types.QueryOutput> {
queryItem(): Promise<QueryCommandOutput> {
return Promise.resolve(dynamodbQueryOutput);
},
};
Expand Down Expand Up @@ -108,6 +112,7 @@ describe("report suspicious activity controller", () => {
// Arrange
req.query = { event: "event-id", reported: "true" };
dynamodbQueryOutput = {
$metadata: undefined,
Items: [
{
event_id: { S: "event-id" },
Expand Down Expand Up @@ -150,7 +155,7 @@ describe("report suspicious activity controller", () => {
describe("Sorry, there is a problem with the service", () => {
it("event param can't be found for this user", async () => {
// Arrange
dynamodbQueryOutput = { Items: [] };
dynamodbQueryOutput = { $metadata: undefined, Items: [] };
req.query = { event: "event-id", reported: "false" };

// Act
Expand All @@ -163,10 +168,10 @@ describe("report suspicious activity controller", () => {
it("activity log can't be retrieved for this user", async () => {
// Arrange
mockDynamoDBService = {
getItem(): Promise<DynamoDB.GetItemOutput> {
getItem(): Promise<GetItemCommandOutput> {
throw new Error("DynamoDB error");
},
queryItem(): Promise<DynamoDB.Types.QueryOutput> {
queryItem(): Promise<QueryCommandOutput> {
throw new Error("DynamoDB error");
},
};
Expand Down
7 changes: 3 additions & 4 deletions src/config/aws.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { Endpoint } from "aws-sdk";
import { DynamoDBClientConfig } from "@aws-sdk/client-dynamodb";
import {
isLocalEnv,
Expand All @@ -22,7 +21,7 @@ export interface SnsConfig {
}

export interface AwsConfig {
endpoint?: Endpoint;
endpoint?: string;
accessKeyId?: string;
secretAccessKey?: string;
region: string;
Expand All @@ -37,7 +36,7 @@ function getLocalStackKmsConfig() {

function getLocalStackAWSConfig(): AwsConfig {
return {
endpoint: new Endpoint(getLocalStackBaseUrl()),
endpoint: getLocalStackBaseUrl(),
accessKeyId: "na",
secretAccessKey: "na",
region: getAwsRegion(),
Expand Down Expand Up @@ -139,7 +138,7 @@ export function getDBConfig(
}

if (config.endpoint) {
dbConfig.endpoint = `${config.endpoint.protocol}//${config.endpoint.host}`;
dbConfig.endpoint = config.endpoint;
}

if (config.region) {
Expand Down
11 changes: 5 additions & 6 deletions src/utils/activityHistory.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { DynamoDB } from "aws-sdk";
import { QueryCommandInput } from "@aws-sdk/client-dynamodb";
import { unmarshall } from "@aws-sdk/util-dynamodb";
import {
activityLogItemsPerPage,
getDynamoActivityLogStoreTableName,
Expand Down Expand Up @@ -194,9 +195,7 @@ export const formatActivityLogs = (
return formattedData;
};

const activityLogDynamoDBRequest = (
user_id: string
): DynamoDB.Types.QueryInput => ({
const activityLogDynamoDBRequest = (user_id: string): QueryCommandInput => ({
TableName: getDynamoActivityLogStoreTableName(),
KeyConditionExpression: "user_id = :user_id",
ExpressionAttributeValues: {
Expand All @@ -213,8 +212,8 @@ export const getActivityLogEntry = async (
const response = await dynamoDBService().queryItem(
activityLogDynamoDBRequest(user_id)
);
const unmarshalledItems = response.Items?.map((item) =>
DynamoDB.Converter.unmarshall(item)
const unmarshalledItems = response.Items?.map((item: any) =>
unmarshall(item)
) as ActivityLogEntry[];
return unmarshalledItems;
} catch (err) {
Expand Down
20 changes: 13 additions & 7 deletions src/utils/dynamo.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,30 @@
import { DynamoDB } from "aws-sdk";
import {
DynamoDB,
GetItemCommandInput,
GetItemCommandOutput,
QueryCommandInput,
QueryCommandOutput,
} from "@aws-sdk/client-dynamodb";
import { DynamoDBService } from "./types";
import { getAWSConfig, AwsConfig } from "../config/aws";

export function dynamoDBService(
awsConfig: AwsConfig = getAWSConfig()
): DynamoDBService {
const getItem = async function (
request: DynamoDB.Types.GetItemInput
): Promise<DynamoDB.Types.GetItemOutput> {
request: GetItemCommandInput
): Promise<GetItemCommandOutput> {
const dynamoDb = new DynamoDB(awsConfig);

return await dynamoDb.getItem(request).promise();
return await dynamoDb.getItem(request);
};

const queryItem = async function (
request: DynamoDB.Types.QueryInput
): Promise<DynamoDB.Types.QueryOutput> {
request: QueryCommandInput
): Promise<QueryCommandOutput> {
const dynamoDb = new DynamoDB(awsConfig);

return await dynamoDb.query(request).promise();
return await dynamoDb.query(request);
};

return {
Expand Down
15 changes: 8 additions & 7 deletions src/utils/kms.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
import { KMS } from "aws-sdk";
import { KMS, SignCommandInput, SignCommandOutput } from "@aws-sdk/client-kms";
import { KmsService } from "./types";
import { getKMSConfig, KmsConfig } from "../config/aws";

export function kmsService(config: KmsConfig = getKMSConfig()): KmsService {
const sign = async function (
payload: string
): Promise<KMS.Types.SignResponse> {
const sign = async function (payload: string): Promise<SignCommandOutput> {
const kms = new KMS(config.awsConfig);

const request: KMS.SignRequest = {
const encoder = new TextEncoder();
const encodedPayload = encoder.encode(payload);

const request: SignCommandInput = {
KeyId: config.kmsKeyId,
Message: payload,
Message: encodedPayload,
SigningAlgorithm: "RSASSA_PKCS1_V1_5_SHA_512",
MessageType: "RAW",
};

return await kms.sign(request).promise();
return await kms.sign(request);
};

return {
Expand Down
10 changes: 7 additions & 3 deletions src/utils/oidc.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { Issuer, Client, custom, generators } from "openid-client";
import { Client, custom, generators, Issuer } from "openid-client";
import { OIDCConfig } from "../types";
import memoize from "fast-memoize";
import { ClientAssertionServiceInterface, KmsService } from "./types";
import { kmsService } from "./kms";
import base64url from "base64url";
import { createRemoteJWKSet, decodeJwt } from "jose";
import random = generators.random;
import { decodeJwt, createRemoteJWKSet } from "jose";

const { toBase64 } = require("@aws-sdk/util-base64-browser");

custom.setHttpOptionsDefaults({
timeout: 20000,
Expand Down Expand Up @@ -82,12 +84,14 @@ function clientAssertionGenerator(

const sig = await kms.sign(message);

const base64SignatureString = toBase64(sig.Signature.toString());

return (
token_components.header +
"." +
token_components.payload +
"." +
sig.Signature.toString("base64")
base64SignatureString
.replace(/\+/g, "-")
.replace(/\//g, "_")
.replace(/=/g, "")
Expand Down
12 changes: 8 additions & 4 deletions src/utils/sns.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
import { SNS } from "aws-sdk";
import {
PublishCommandInput,
PublishCommandOutput,
SNS,
} from "@aws-sdk/client-sns";
import { SnsService } from "./types";
import { getSNSConfig, SnsConfig } from "../config/aws";

export function snsService(config: SnsConfig = getSNSConfig()): SnsService {
const publish = async function (
topic_arn: string,
message: string
): Promise<SNS.Types.PublishResponse> {
): Promise<PublishCommandOutput> {
const sns = new SNS(config.awsConfig);

const request: SNS.PublishInput = {
const request: PublishCommandInput = {
TopicArn: topic_arn,
Message: message,
};

return await sns.publish(request).promise();
return await sns.publish(request);
};
return {
publish,
Expand Down
22 changes: 13 additions & 9 deletions src/utils/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
import { DynamoDB, KMS, SNS } from "aws-sdk";
import {
GetItemCommandInput,
GetItemCommandOutput,
QueryCommandInput,
QueryCommandOutput,
} from "@aws-sdk/client-dynamodb";

import { SignCommandOutput } from "@aws-sdk/client-kms";
import { PublishCommandOutput } from "@aws-sdk/client-sns";
import { MfaMethod } from "./mfa/types";

type ClientId = string;
Expand All @@ -23,7 +31,7 @@ export interface YourServices {
}

export interface KmsService {
sign: (payload: string) => Promise<KMS.Types.SignResponse>;
sign: (payload: string) => Promise<SignCommandOutput>;
}

export interface ActivityLogEntry {
Expand Down Expand Up @@ -58,20 +66,16 @@ export interface SnsService {
publish: (
topic_arn: string,
message: string
) => Promise<SNS.Types.PublishResponse>;
) => Promise<PublishCommandOutput>;
}

export interface SqsService {
send: (message: string, trace: string) => Promise<string | undefined>;
}

export interface DynamoDBService {
getItem: (
getCommand: DynamoDB.Types.GetItemInput
) => Promise<DynamoDB.Types.GetItemOutput>;
queryItem: (
queryCommand: DynamoDB.Types.QueryInput
) => Promise<DynamoDB.Types.QueryOutput>;
getItem: (getCommand: GetItemCommandInput) => Promise<GetItemCommandOutput>;
queryItem: (queryCommand: QueryCommandInput) => Promise<QueryCommandOutput>;
}

export interface AwsConfig {
Expand Down
10 changes: 6 additions & 4 deletions src/utils/yourServices.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { DynamoDB } from "aws-sdk";
import { AttributeValue, GetItemCommandInput } from "@aws-sdk/client-dynamodb";
import { dynamoDBService } from "./dynamo";
import { unmarshall } from "@aws-sdk/util-dynamodb";
import {
getDynamoServiceStoreTableName,
getAllowedAccountListClientIDs,
Expand All @@ -12,15 +13,16 @@ import pino from "pino";

const serviceStoreDynamoDBRequest = (
subjectId: string
): DynamoDB.Types.GetItemInput => ({
): GetItemCommandInput => ({
TableName: getDynamoServiceStoreTableName(),
Key: {
user_id: { S: subjectId },
},
});

const unmarshallDynamoData = (dynamoDBResponse: DynamoDB.Types.AttributeMap) =>
DynamoDB.Converter.unmarshall(dynamoDBResponse);
const unmarshallDynamoData = (
dynamoDBResponse: Record<string, AttributeValue>
) => unmarshall(dynamoDBResponse);

export const getServices = async (
subjectId: string,
Expand Down

0 comments on commit 4364c7e

Please sign in to comment.