Skip to content

Commit

Permalink
Protect lambda function URL with a verify header
Browse files Browse the repository at this point in the history
  • Loading branch information
unstubbable committed Mar 14, 2024
1 parent bbaea61 commit b1981bf
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 4 deletions.
11 changes: 10 additions & 1 deletion apps/aws-app/cdk/stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import path from 'path';
import * as cdk from 'aws-cdk-lib';
import type {Construct} from 'constructs';

const verifyHeader = process.env.AWS_HANDLER_VERIFY_HEADER;
const distDirname = path.join(import.meta.dirname, `../dist/`);

export class Stack extends cdk.Stack {
Expand All @@ -15,7 +16,10 @@ export class Stack extends cdk.Stack {
entry: path.join(distDirname, `handler/index.js`),
runtime: cdk.aws_lambda.Runtime.NODEJS_20_X,
bundling: {format: cdk.aws_lambda_nodejs.OutputFormat.ESM},
timeout: cdk.Duration.seconds(28),
timeout: cdk.Duration.minutes(1),
environment: verifyHeader
? {AWS_HANDLER_VERIFY_HEADER: verifyHeader}
: undefined,
},
);

Expand All @@ -39,6 +43,11 @@ export class Stack extends cdk.Stack {
defaultBehavior: {
origin: new cdk.aws_cloudfront_origins.FunctionUrlOrigin(
lambdaFunctionUrl,
{
customHeaders: verifyHeader
? {'X-Origin-Verify': verifyHeader}
: undefined,
},
),
allowedMethods: cdk.aws_cloudfront.AllowedMethods.ALLOW_ALL,
cachePolicy: new cdk.aws_cloudfront.CachePolicy(this, `cache-policy`, {
Expand Down
13 changes: 13 additions & 0 deletions apps/aws-app/dev-server/auth-middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import type {MiddlewareHandler} from 'hono';

const verifyHeader = process.env.AWS_HANDLER_VERIFY_HEADER;

export const authMiddleware: MiddlewareHandler = async (context, next) => {
if (verifyHeader) {
context.req.raw.headers.set(`X-Origin-Verify`, verifyHeader);
} else {
console.warn(`process.env.AWS_HANDLER_VERIFY_HEADER is undefined`);
}

return next();
};
2 changes: 2 additions & 0 deletions apps/aws-app/dev-server/run.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import {serve} from '@hono/node-server';
import {serveStatic} from '@hono/node-server/serve-static';
import {Hono} from 'hono';
import {authMiddleware} from './auth-middleware.js';
import './stub-awslambda.js';

// @ts-ignore
const handlerModule = await import(`../dist/handler/index.js`);
const {app: handlerApp} = handlerModule as {app: Hono};
const app = new Hono();

app.use(authMiddleware);
app.use(`/client/*`, serveStatic({root: `dist/static`}));
app.route(`/`, handlerApp);

Expand Down
12 changes: 12 additions & 0 deletions apps/aws-app/src/handler/auth-middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type {MiddlewareHandler} from 'hono';

export const authMiddleware: MiddlewareHandler = async (context, next) => {
if (
context.req.header(`X-Origin-Verify`) !==
process.env.AWS_HANDLER_VERIFY_HEADER
) {
return context.text(`Unauthorized`, 401);
}

return next();
};
6 changes: 4 additions & 2 deletions apps/aws-app/src/handler/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import {streamHandle} from 'hono/aws-lambda';
import * as React from 'react';
import type {ReactFormState} from 'react-dom/server';
import {App} from './app.js';
import {logger} from './logger.js';
import {authMiddleware} from './auth-middleware.js';
import {loggerMiddleware} from './logger-middleware.js';
import {
cssManifest,
jsManifest,
Expand All @@ -22,7 +23,8 @@ import {

export const app = new Hono();

app.use(logger);
app.use(authMiddleware);
app.use(loggerMiddleware);
app.get(`/*`, async (context) => handleGet(context.req.raw));
app.post(`/*`, async (context) => handlePost(context.req.raw));

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type {LambdaFunctionURLEvent} from 'aws-lambda';
import type {MiddlewareHandler} from 'hono';

export const logger: MiddlewareHandler<{
export const loggerMiddleware: MiddlewareHandler<{
Bindings: {
// Not available in dev server.
event?: LambdaFunctionURLEvent;
Expand Down

0 comments on commit b1981bf

Please sign in to comment.