Skip to content

Commit

Permalink
OS-1795 - add build scripts and CFN templates polish
Browse files Browse the repository at this point in the history
  • Loading branch information
Pedro Carreira committed Apr 11, 2023
1 parent 2379d24 commit 70fd025
Show file tree
Hide file tree
Showing 50 changed files with 3,005 additions and 1,319 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
node_modules
jspm_packages

# Serverless directories
.serverless

# IDE
/.vscode
.idea/
Expand All @@ -22,3 +25,5 @@ applications/junit.xml

# OS X files
.DS_Store

build/
438 changes: 435 additions & 3 deletions README.md

Large diffs are not rendered by default.

21 changes: 7 additions & 14 deletions applications/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
# SIM Retrieval Service

## Description
The responsibility of this service is to retrieve all customer SIM cards through the management API, compare the results with the open source project database and create SQS events for the new and removed SIMs.

## Requirements
- `zip` command - used to compress code to upload to AWS Lambda
```
Expand All @@ -14,13 +9,13 @@ brew install zip
```

## Environment variables
| Name | Description | Example |
| ------------------------------------- | --------------------------------------------- | --------------------------------------------------------- |
| MANAGEMENT_API_URL | 1nce management API URL | https://api-prod.1nce.com/management-api |
| MANAGEMENT_API_CREDENTIALS_SECRET_ARN | ID of secret with API credentials | arn:aws:secretsmanager:REGION:ACCOUNT-ID:secret:ID |
| SIMS_TABLE | Table used to store SIMs data | sim-metastore |
| SIM_CREATE_QUEUE_URL | SQS queue URL to upload new SIMs data | https://sqs.REGION.amazonaws.com/ACCOUNT/sims-create.fifo |
| SIM_DELETE_QUEUE_URL | SQS queue URL to upload deleted SIMs data | https://sqs.REGION.amazonaws.com/ACCOUNT/sims-delete.fifo |
| Name | Description | Example |
| ------------------------------------- | --------------------------------------------- | ---------------------------------------------------------- |
| MANAGEMENT_API_URL | 1nce management API URL | https://api-prod.1nce.com/management-api |
| MANAGEMENT_API_CREDENTIALS_SECRET_ARN | ID of secret with API credentials | arn:aws:secretsmanager:REGION:ACCOUNT-ID:secret:ID |
| SIMS_TABLE | Table used to store SIMs data | sim-metastore |
| SIM_CREATE_QUEUE_URL | SQS queue URL to upload new SIMs data | https://sqs.REGION.amazonaws.com/ACCOUNT/sims-create.fifo |
| SIM_DISABLE_QUEUE_URL | SQS queue URL to upload SIMs data to disable | https://sqs.REGION.amazonaws.com/ACCOUNT/sims-disable.fifo |

## How to run unit tests
```
Expand Down Expand Up @@ -61,5 +56,3 @@ npm run zip
```

3) Inside the `dist` folder you will find the `sim-retrieval.zip` file ready to upload to AWS Lambda


2 changes: 1 addition & 1 deletion applications/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"test:watch": "jest --watch",
"test:coverage": "jest --coverage",
"zip:lambda": "cd dist/${LAMBDA} && zip ${LAMBDA}.zip index.js",
"zip:all": "LAMBDA=sim-retrieval npm run zip:lambda && LAMBDA=device-onboarding npm run zip:lambda && LAMBDA=create-sim npm run zip:lambda"
"zip:all": "LAMBDA=sim-retrieval npm run zip:lambda && LAMBDA=device-onboarding npm run zip:lambda && LAMBDA=create-sim npm run zip:lambda && LAMBDA=disable-sim npm run zip:lambda"
},
"author": "",
"license": "ISC",
Expand Down
161 changes: 89 additions & 72 deletions applications/src/create-sim/create-sim.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import { mocked } from "jest-mock";
import { marshall } from "@aws-sdk/util-dynamodb";
import { handler } from "./create-sim";
import { putItem } from "../shared/utils/dynamoHelper";
import { type SQSEvent } from "aws-lambda";
import { publishErrorToSnsTopic } from "../shared/services/errorHandlingService";
import { IoTCoreCertificate } from "../shared/types/iotCoreCertificate";
import { deleteIotCertificate, deleteIotThing } from "../shared/services/iotCoreService";
import { IoTCoreThing } from "../shared/types/iotCoreThing";
import { publishRegistrationToMqtt, publishSuccessSummaryToSns } from "../shared/services/successMessageService";
import { buildSqsEvent } from "../shared/test/sqs.fixture";

jest.mock("../shared/utils/dynamoHelper");
jest.mock("../shared/services/errorHandlingService");
Expand All @@ -34,14 +34,18 @@ const mockIotCoreThingCreate = mocked(IoTCoreThing.create);

console.error = jest.fn();
console.log = jest.fn();
const mockDate = new Date("2022-04-02T09:00:00.000Z");

describe("Create SIM", () => {
let iotCertificate: IoTCoreCertificate;
let iotThing: IoTCoreThing;

beforeAll(() => {
jest.useFakeTimers();
jest.setSystemTime(new Date("2022-04-02T09:00:00.000Z"));
jest.useFakeTimers(
{
now: mockDate.getTime(),
},
);
});

afterAll(() => {
Expand All @@ -58,8 +62,8 @@ describe("Create SIM", () => {
PK: "IP#10.0.0.0",
SK: "P#MQTT",
crt: "pem",
ct: "2022-04-02T09:00:00.000Z",
ut: "2022-04-02T09:00:00.000Z",
ct: mockDate.toISOString(),
ut: mockDate.toISOString(),
i: "123456789",
ip: "10.0.0.0",
prk: "private-key",
Expand Down Expand Up @@ -90,29 +94,24 @@ describe("Create SIM", () => {
],
});

expect(console.error).toHaveBeenCalledWith("error parsing SQS record body: invalid JSON", expect.any(SyntaxError));
expect(console.error).toHaveBeenCalledWith("error parsing SQS record body", expect.any(SyntaxError));
expect(console.log).not.toHaveBeenCalled();
});
});

describe("when device certificate is not properly generated", () => {
describe("when SIM certificate is not properly generated", () => {
it("should log creation error", async () => {
const error = "Certificate generation error";
mockIotCoreCertCreate.mockRejectedValueOnce(error);
mockPublishErrorToSnsTopic.mockResolvedValueOnce();

await handler(buildSqsEvent("123456789", "10.0.0.0"));
const event = buildSqsEvent("123456789", "10.0.0.0");
await handler(event);

expect(mockIotCoreCertCreate).toHaveBeenCalled();
expect(mockPublishErrorToSnsTopic).toHaveBeenCalledWith(error, {
iccid: "123456789",
ip: "10.0.0.0",
createdTime: new Date("2022-04-02T09:00:00.000Z"),
updatedTime: new Date("2022-04-02T09:00:00.000Z"),
});
expect(console.error).toHaveBeenCalledTimes(2);
expect(console.error).toHaveBeenCalledWith("Error creating SIM", error);
expect(console.error).toHaveBeenNthCalledWith(2, "FAILURE device not created", { iccid: "123456789", ip: "10.0.0.0" });
expect(mockPublishErrorToSnsTopic).toHaveBeenCalledWith("SIM enable failed", error, undefined);
expect(console.error).toHaveBeenCalledTimes(1);
expect(console.error).toHaveBeenNthCalledWith(1, "FAILURE SIM not created", error, event.Records[0]);
expect(console.log).not.toHaveBeenCalled();
});
});
Expand All @@ -129,17 +128,24 @@ describe("Create SIM", () => {

expect(mockIotCoreCertCreate).toHaveBeenCalled();
expect(mockIoTCoreCertAttachPolicy).toHaveBeenCalledWith("IOT_CORE_POLICY_NAME");
expect(mockPublishErrorToSnsTopic).toHaveBeenCalledWith(error, {
expect(mockPublishErrorToSnsTopic).toHaveBeenCalledWith("SIM enable failed", error, {
iccid: "123456789",
ip: "10.0.0.0",
createdTime: new Date("2022-04-02T09:00:00.000Z"),
updatedTime: new Date("2022-04-02T09:00:00.000Z"),
certificate: "pem",
privateKey: "private-key",
active: true,
createdTime: mockDate,
updatedTime: mockDate,
});
expect(console.error).toHaveBeenCalledTimes(2);
expect(console.error).toHaveBeenNthCalledWith(1, "Error creating SIM", error);
expect(console.error).toHaveBeenNthCalledWith(2, "FAILURE device not created", {
expect(console.error).toHaveBeenCalledTimes(1);
expect(console.error).toHaveBeenNthCalledWith(1, "FAILURE SIM not created", error, {
iccid: "123456789",
ip: "10.0.0.0",
certificate: "pem",
privateKey: "private-key",
active: true,
createdTime: mockDate,
updatedTime: mockDate,
});
expect(console.log).not.toHaveBeenCalled();
});
Expand All @@ -160,18 +166,26 @@ describe("Create SIM", () => {
expect(mockIotCoreCertCreate).toHaveBeenCalled();
expect(mockIoTCoreCertAttachPolicy).toHaveBeenCalledWith("IOT_CORE_POLICY_NAME");
expect(mockIotCoreThingCreate).toHaveBeenCalledWith("123456789");
expect(mockPublishErrorToSnsTopic).toHaveBeenCalledWith(error, {
expect(mockPublishErrorToSnsTopic).toHaveBeenCalledWith("SIM enable failed", error, {
iccid: "123456789",
ip: "10.0.0.0",
certificate: "pem",
privateKey: "private-key",
createdTime: new Date("2022-04-02T09:00:00.000Z"),
updatedTime: new Date("2022-04-02T09:00:00.000Z"),
active: true,
createdTime: mockDate,
updatedTime: mockDate,
});
expect(mockDeleteIotCertificate).toHaveBeenCalledWith(iotCertificate);
expect(console.error).toHaveBeenCalledTimes(2);
expect(console.error).toHaveBeenCalledWith("Error creating SIM", error);
expect(console.error).toHaveBeenNthCalledWith(2, "FAILURE device not created", { iccid: "123456789", ip: "10.0.0.0" });
expect(console.error).toHaveBeenCalledTimes(1);
expect(console.error).toHaveBeenNthCalledWith(1, "FAILURE SIM not created", error, {
iccid: "123456789",
ip: "10.0.0.0",
certificate: "pem",
privateKey: "private-key",
active: true,
createdTime: mockDate,
updatedTime: mockDate,
});
expect(console.log).not.toHaveBeenCalled();
});
});
Expand All @@ -195,19 +209,27 @@ describe("Create SIM", () => {
expect(mockIoTCoreCertAttachPolicy).toHaveBeenCalledWith("IOT_CORE_POLICY_NAME");
expect(mockIotCoreThingCreate).toHaveBeenCalledWith("123456789");
expect(mockIoTCoreThingAttachCert).toHaveBeenCalledWith("arn");
expect(mockPublishErrorToSnsTopic).toHaveBeenCalledWith(error, {
expect(mockPublishErrorToSnsTopic).toHaveBeenCalledWith("SIM enable failed", error, {
iccid: "123456789",
ip: "10.0.0.0",
certificate: "pem",
privateKey: "private-key",
createdTime: new Date("2022-04-02T09:00:00.000Z"),
updatedTime: new Date("2022-04-02T09:00:00.000Z"),
active: true,
createdTime: mockDate,
updatedTime: mockDate,
});
expect(mockDeleteIotCertificate).toHaveBeenCalledWith(iotCertificate);
expect(mockDeleteIotThing).toHaveBeenCalledWith(iotThing, iotCertificate);
expect(console.error).toHaveBeenCalledTimes(2);
expect(console.error).toHaveBeenCalledWith("Error creating SIM", error);
expect(console.error).toHaveBeenNthCalledWith(2, "FAILURE device not created", { iccid: "123456789", ip: "10.0.0.0" });
expect(console.error).toHaveBeenCalledTimes(1);
expect(console.error).toHaveBeenNthCalledWith(1, "FAILURE SIM not created", error, {
iccid: "123456789",
ip: "10.0.0.0",
certificate: "pem",
privateKey: "private-key",
active: true,
createdTime: mockDate,
updatedTime: mockDate,
});
expect(console.log).not.toHaveBeenCalled();
});
});
Expand All @@ -233,25 +255,33 @@ describe("Create SIM", () => {
expect(mockIotCoreThingCreate).toHaveBeenCalledWith("123456789");
expect(mockIoTCoreThingAttachCert).toHaveBeenCalledWith("arn");
expect(mockPutItem).toHaveBeenCalledWith({ TableName: "SIMS_TABLE", Item: marshall(dynamoDbSimItem) });
expect(mockPublishErrorToSnsTopic).toHaveBeenCalledWith(new Error(error), {
expect(mockPublishErrorToSnsTopic).toHaveBeenCalledWith("SIM enable failed", new Error(error), {
iccid: "123456789",
ip: "10.0.0.0",
certificate: "pem",
privateKey: "private-key",
createdTime: new Date("2022-04-02T09:00:00.000Z"),
updatedTime: new Date("2022-04-02T09:00:00.000Z"),
active: true,
createdTime: mockDate,
updatedTime: mockDate,
});
expect(mockDeleteIotCertificate).toHaveBeenCalledWith(iotCertificate);
expect(mockDeleteIotThing).toHaveBeenCalledWith(iotThing, iotCertificate);
expect(console.error).toHaveBeenCalledTimes(2);
expect(console.error).toHaveBeenNthCalledWith(1, "Error creating SIM", new Error(error));
expect(console.error).toHaveBeenNthCalledWith(2, "FAILURE device not created", { iccid: "123456789", ip: "10.0.0.0" });
expect(console.error).toHaveBeenCalledTimes(1);
expect(console.error).toHaveBeenNthCalledWith(1, "FAILURE SIM not created", new Error(error), {
iccid: "123456789",
ip: "10.0.0.0",
certificate: "pem",
privateKey: "private-key",
active: true,
createdTime: mockDate,
updatedTime: mockDate,
});
expect(console.log).not.toHaveBeenCalled();
});
});

describe("when the creation process is completed sucessfully", () => {
it("should log device created successfully", async () => {
it("should log SIM created successfully", async () => {
mockIotCoreCertCreate.mockResolvedValueOnce(iotCertificate);
mockCertificateInstance();
mockIoTCoreCertAttachPolicy.mockResolvedValueOnce({});
Expand All @@ -274,49 +304,36 @@ describe("Create SIM", () => {
ip: "10.0.0.0",
certificate: "pem",
privateKey: "private-key",
createdTime: new Date("2022-04-02T09:00:00.000Z"),
updatedTime: new Date("2022-04-02T09:00:00.000Z"),
});
active: true,
createdTime: mockDate,
updatedTime: mockDate,
}, "SIM enabled");
expect(mockPublishSuccessSummaryToSns).toHaveBeenCalledWith({
iccid: "123456789",
ip: "10.0.0.0",
certificate: "pem",
privateKey: "private-key",
createdTime: new Date("2022-04-02T09:00:00.000Z"),
updatedTime: new Date("2022-04-02T09:00:00.000Z"),
});
active: true,
createdTime: mockDate,
updatedTime: mockDate,
}, "SIM enabled");
expect(mockDeleteIotCertificate).toHaveBeenCalledTimes(0);
expect(mockDeleteIotThing).toHaveBeenCalledTimes(0);
expect(console.error).not.toHaveBeenCalled();
expect(console.log).toHaveBeenCalledTimes(1);
expect(console.log).toHaveBeenCalledWith("SUCCESS device created", { iccid: "123456789", ip: "10.0.0.0" });
expect(console.log).toHaveBeenCalledWith("SUCCESS SIM created", {
iccid: "123456789",
ip: "10.0.0.0",
certificate: "pem",
privateKey: "private-key",
active: true,
createdTime: mockDate,
updatedTime: mockDate,
});
});
});
});

function buildSqsEvent(iccid: string, ip: string): SQSEvent {
return {
Records: [
{
messageId: "id",
body: JSON.stringify({ iccid, ip }),
receiptHandle: "handle",
attributes: {
ApproximateReceiveCount: "0",
SentTimestamp: "timestamp",
SenderId: "sender-id",
ApproximateFirstReceiveTimestamp: "timestamp",
},
messageAttributes: {},
md5OfBody: "md5",
eventSource: "source",
eventSourceARN: "arn",
awsRegion: "region",
},
],
};
}

function mockCertificateInstance(): void {
const mockIoTCoreCertInstance = mockIoTCoreCert.mock.instances[0];
mockIoTCoreCertInstance.attachPolicy = mockIoTCoreCertAttachPolicy;
Expand Down
Loading

0 comments on commit 70fd025

Please sign in to comment.