Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add AWS+MySQL Rotator Agent #2

Merged
merged 5 commits into from
Aug 8, 2022
Merged
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
25 changes: 17 additions & 8 deletions agent-core/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import https from "https";
import * as jose from "jose";
import { z } from "zod";
import { AgentError, jsonifyError } from "./utils";
import { RequestSchema, Request, Response, RequestHandler } from "./models";
import { AgentError, jsonifyError } from "./utils.js";
import { RequestSchema, Request, Response, RequestHandler } from "./models.js";

export { AgentError, Request, Response, RequestHandler };

export type ProcessRequestOptions = { overrideKeySetURL?: string };
export type JWKSOption = { type: "remote"; url: string } | { type: "local"; keySet: Record<string, unknown> };

export type ProcessRequestOptions = {
overrideKeySet?: JWKSOption;
};

const MAX_ABS_REQUEST_AGE_MS = 30 * 1000; // 30 seconds

Expand All @@ -20,12 +24,17 @@ async function verifySignature(signature: string, options: ProcessRequestOptions

z.enum(["ES512"]).parse(decodedHeader.alg);

const keySet = jose.createRemoteJWKSet(
new URL(options.overrideKeySetURL ?? "https://keys.doppler.com/secret-agents/jwks.json"),
{
const keySetOption = options.overrideKeySet ?? { type: "remote", url: "https://keys.doppler.com/secret-agents/jwks.json" };

let keySet;
if (keySetOption.type === "remote") {
keySet = jose.createRemoteJWKSet(new URL("https://keys.doppler.com/secret-agents/jwks.json"), {
agent: new https.Agent({ minVersion: "TLSv1.3" }),
}
);
});
} else {
keySet = jose.createLocalJWKSet(keySetOption.keySet as unknown as jose.JSONWebKeySet);
}

return await jose.compactVerify(signature, keySet);
}

Expand Down
38 changes: 38 additions & 0 deletions apps/aws-mysql-rotator/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
FROM node:16-alpine as build

WORKDIR /usr/src/app

# Copy package files and install all dependencies
COPY ./package*.json ./
COPY ./agent-core/package*.json ./agent-core/
COPY ./rotators/mysql/package*.json ./rotators/mysql/
COPY ./utils/aws/package*.json ./utils/aws/
COPY ./apps/aws-mysql-rotator/package*.json ./apps/aws-mysql-rotator/
RUN npm install --workspace apps/aws-mysql-rotator

# Copy sources
COPY ./tsconfig* ./
COPY ./agent-core ./agent-core
COPY ./rotators/mysql ./rotators/mysql
COPY ./utils/aws ./utils/aws
COPY ./apps/aws-mysql-rotator ./apps/aws-mysql-rotator

# Build dependencies and app
RUN npm --prefix ./agent-core run build
RUN npm --prefix ./rotators/mysql run build
RUN npm --prefix ./utils/aws run build
RUN npm --prefix ./apps/aws-mysql-rotator run build

# Remove node_modules to be reinstalled later
RUN rm -r node_modules

FROM public.ecr.aws/lambda/nodejs:16
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this Dockerfile is still meant to build a deployable image. We're currently considering switching to S3-based code bundle deployments. If we go that route, not much will change other than this file and some additional deploy scripts.


WORKDIR ${LAMBDA_TASK_ROOT}

COPY --from=build /usr/src/app .

# Only install production dependencies
RUN npm clean-install --production

CMD [ "apps/aws-mysql-rotator/dist/app.handler" ]
13 changes: 13 additions & 0 deletions apps/aws-mysql-rotator/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { JWKSOption, processRequest } from "agent-core";
import mysqlHandler from "mysql-rotator";
import { fetchS3KeySet } from "aws-utils";

export async function handler(event: { body: string }) {
let keySetOption: JWKSOption;
if (process.env.OVERRIDE_KEY_SET) {
keySetOption = { type: "local", keySet: JSON.parse(process.env.OVERRIDE_KEY_SET) };
} else {
keySetOption = { type: "local", keySet: await fetchS3KeySet(process.env.OVERRIDE_KEY_SET_S3_BUCKET) };
}
return await processRequest(event.body, mysqlHandler, { overrideKeySet: keySetOption });
}
25 changes: 25 additions & 0 deletions apps/aws-mysql-rotator/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"name": "aws-mysql-rotator",
"version": "1.0.0",
"type": "module",
"description": "",
"main": "dist/app.js",
"types": "dist/app.d.ts",
"engines": {
"node": "16.x"
},
"scripts": {
"build": "tsc",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "Apache-2.0",
"devDependencies": {
"typescript": "^4.6.4"
},
"dependencies": {
"agent-core": "*",
"mysql-rotator": "*",
"aws-utils": "*"
}
}
7 changes: 7 additions & 0 deletions apps/aws-mysql-rotator/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "dist"
},
"references": [{ "path": "../../agent-core" }, { "path": "../../rotators/mysql" }, { "path": "../../utils/aws" }]
}
2 changes: 1 addition & 1 deletion apps/http-postgres-rotator/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,4 @@ COPY --from=build /usr/src/app .
# Only install production dependencies
RUN npm install --production

CMD [ "node", "--experimental-specifier-resolution=node", "./apps/http-postgres-rotator/dist/index.js" ]
CMD [ "node", "./apps/http-postgres-rotator/dist/index.js" ]
4 changes: 3 additions & 1 deletion apps/http-postgres-rotator/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ app.use(express.text());
app.use(express.text({ limit: "50kb" }));

app.post("/", async (req, res) => {
const response = await processRequest(req.body, postgresHandler, { overrideKeySetURL: process.env.OVERRIDE_KEY_SET_URL });
const response = await processRequest(req.body, postgresHandler, {
overrideKeySet: process.env.OVERRIDE_KEY_SET_URL ? { type: "remote", url: process.env.OVERRIDE_KEY_SET_URL } : undefined,
});
res.send(response);
});

Expand Down
Loading