Skip to content

Commit

Permalink
feat(ec2): added tests and ip function
Browse files Browse the repository at this point in the history
  • Loading branch information
ctrlc03 committed Jun 21, 2023
1 parent debed05 commit 2658c1a
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 34 deletions.
2 changes: 1 addition & 1 deletion packages/actions/.env.default
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ AWS_ACCESS_KEY_ID="YOUR-AWS-ACCESS-KEY-ID"
AWS_SECRET_ACCESS_KEY="YOUR-AWS-SECRET-ACCESS-KEY"
# The AWS region where your buckets are located.
AWS_REGION="YOUR-AWS-REGION"
# The AWS AMI ID (default to Ubuntu 22.04 LTS).
# The AWS AMI ID (default to Ubuntu 22.04 LTS in us-east-1).
AWS_AMI_ID="ami-007855ac798b5175e"
# The EC2 instance role to access S3
AWS_ROLE_ARN="YOUR-AWS-ROLE-ARN"
Expand Down
44 changes: 16 additions & 28 deletions packages/actions/src/helpers/ec2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@ import {
RunInstancesCommand,
StartInstancesCommand,
StopInstancesCommand,
TerminateInstancesCommand
TerminateInstancesCommand,
DescribeInstancesCommand
} from "@aws-sdk/client-ec2"
import { Functions } from "firebase/functions"
import { P0tionEC2Instance } from "../types"
import dotenv from "dotenv"
import { downloadCeremonyArtifact } from "./storage"
import fs from "fs"
dotenv.config()

/**
Expand Down Expand Up @@ -218,7 +216,6 @@ export const checkEC2Status = async (ec2Client: EC2Client, instanceId: string) =
if (response.$metadata.httpStatusCode !== 200) {
throw new Error("Could not get the status of the EC2 instance")
}
console.log(response)
return response.InstanceStatuses![0].InstanceState!.Name === "running"

}
Expand Down Expand Up @@ -278,32 +275,23 @@ export const terminateEC2Instance = async (ec2: EC2Client, instanceId: string) =
}
}

// To retrieve the document from S3 we should time how long it takes to verify a zKey
// idea is to verify the coordinator zKey when a ceremony is setup
// this way we can time that
// and run a cloud function every x minutes
// or even better we make a script that writes to firestore after the verification is done
// store the serviceAccountKey in AWS KMS and then use it to write to firestore

/**
* Retrieves the verification result
* @param userFunctions <Functions> the Firebase functions
* @param bucketName <string> the name of the bucket
* @param verificationTranscriptPath <string> the path to the verification transcript
* Get the EC2 public ip
* @notice At each restart, the EC2 instance gets a new IP
* @param ec2 <EC2Client> the EC2 client to talk to AWS
* @param instanceId <string> the id of the instance to get the IP of
* @returns <Promise<string>> the IP of the instance
*/
export const getVerificationResult = async (userFunctions: Functions, bucketName: string, verificationTranscriptPath: string) => {
const filePath = "/tmp/verification.txt"
// download the file
await downloadCeremonyArtifact(userFunctions, bucketName, verificationTranscriptPath, filePath)
export const getEC2Ip = async (ec2: EC2Client, instanceId: string): Promise<string> => {
const command = new DescribeInstancesCommand({
InstanceIds: [instanceId]
})

const pattern = "ZKey Ok!"
const fileData = fs.readFileSync(filePath, "utf-8").toString()
const response = await ec2.send(command)

// delete the file
fs.unlinkSync(filePath)
if (response.$metadata.httpStatusCode !== 200) {
throw new Error("Could not get the EC2 instance")
}

// a successful verification file will have written "Zkey Ok!"
if (fileData.includes(pattern)) return true
// we need to make sure to delete the artifacts
return false
return response.Reservations![0].Instances![0].PublicIpAddress
}
24 changes: 19 additions & 5 deletions packages/actions/test/unit/ec2.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
checkEC2Status,
createEC2Client,
createEC2Instance,
getEC2Ip,
startEC2Instance,
stopEC2Instance,
terminateEC2Instance
Expand All @@ -17,6 +18,7 @@ chai.use(chaiAsPromised)
describe("EC2", () => {
let instance: P0tionEC2Instance
let ec2: EC2Client
let previousIp: string

beforeAll(async () => {
ec2 = await createEC2Client()
Expand All @@ -34,17 +36,29 @@ describe("EC2", () => {
expect(response).to.be.true
})

it.skip("stopEC2Instance should stop an instance", async () => {
it("getEC2Ip should return an ip", async () => {
const ip = await getEC2Ip(ec2, instance.InstanceId!)
expect(ip).to.not.be.undefined
previousIp = ip
})

it("stopEC2Instance should stop an instance", async () => {
await expect(stopEC2Instance(ec2, instance.InstanceId!)).to.be.fulfilled
await sleep(200000)
})

it.skip("checkEC2Status should return false for an instance that is running", async () => {
const response = await checkEC2Status(ec2, instance.InstanceId!)
expect(response).to.be.false
it("checkEC2Status should throw for an instance that is stopped", async () => {
await expect(checkEC2Status(ec2, instance.InstanceId!)).to.be.rejected
})

it.skip("startEC2Instance should start an instance", async () => {
it("startEC2Instance should start an instance", async () => {
await expect(startEC2Instance(ec2, instance.InstanceId!)).to.be.fulfilled
await sleep(200000)
})

it("should get a different ip address after a restart", async () => {
const ip = getEC2Ip(ec2, instance.InstanceId!)
expect(previousIp).to.not.equal(ip)
})

it("terminateEC2Instance should terminate an instance", async () => {
Expand Down
6 changes: 6 additions & 0 deletions packages/backend/.default.env
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ AWS_REGION="YOUR-AWS-REGION"
AWS_PRESIGNED_URL_EXPIRATION="900"
# The postfix used to create S3 buckets for storing the ceremonies artifacts.
AWS_CEREMONY_BUCKET_POSTFIX="-ph2-ceremony"
# The AWS AMI ID (default to Ubuntu 22.04 LTS in us-east-1).
AWS_AMI_ID="ami-007855ac798b5175e"
# The EC2 instance role to access S3
AWS_ROLE_ARN="YOUR-AWS-ROLE-ARN"
# The SSH key to access the EC2 instance
AWS_KEY_NAME="YOUR-AWS-SSH-KEY-NAME"

### GENERIC ###
### These configs are generic and not tied to Firebase or AWS services.
Expand Down

0 comments on commit 2658c1a

Please sign in to comment.