dherault / serverless-offline

Emulate AWS λ and API Gateway locally when developing your Serverless project
MIT License
5.19k stars 795 forks source link

clientCert property is undefined when client certificates are used #1730

Open dylanlt opened 1 year ago

dylanlt commented 1 year ago

Bug Report

Current Behavior

When a client certificate is used to call a lambda HTTP handler, the clientCert property of the event is undefined when the code runs on serverless-offline but the clientCert is defined when running on AWS.

Sample Code

Client code:

        const ca = await fsPromises.readFile(workingDirectory('ca.pem'));
        const cert = await fsPromises.readFile(workingDirectory('client.pem'));
        const key = await fsPromises.readFile(workingDirectory('client.key'));

                import { Client } from 'undici';
        const apiClient = new Client(apiUrl, {
            connect: { ca, cert, key },
        });
        const apiResponse = await apiClient.request({
            path: '/',
            method: 'POST',
            body: JSON.stringify(payload),
        });

Server code:

    handler: async (event: APIGatewayProxyEvent, _context: Context, _callback: any) => {
        logger.info({ event }, 'Event received');
        // certificate info is a distinguished name in clientCert
        // v1 is .identity.clientCert but v2 is .authentication.clientCert
        if (!event.requestContext.identity?.clientCert)
            throw new Error('A client certificate is required on this endpoint');
                }
        }

file: serverless.js

module.exports = {
    configValidationMode: 'error',
    service: 'myLambda',
    plugins: ['serverless-offline'],
    useDotenv: true,
    custom: {
        'serverless-offline': {
            noPrependStageInUrl: true,
            allowCache: true,
            httpsProtocol: 'ssl',
        },
    },

    provider: {
        name: 'aws',
        runtime: 'nodejs18.x',
        timeout: 30,
        stage: 'api',
        region: 'ap-southeast-2',
        environment: {
            LOGGING_LEVEL: 'trace',
        },
    },

    package: {
        individually: true,
        excludeDevDependencies: true,
        exclude: ['**'],
    },

    functions: {
        api: {
            handler: `lib/index.handler`,
            package: {
                include: [`lib/index.js`, `node_modules/**`],
            },

            events: [
                {
                    http: {
                        path: '/',
                        method: 'ANY',
                        cors: false,
                    },
                },
            ],
        },
    },
};

Expected behavior/code

The error "'A client certificate is required on this endpoint" is not thrown.

Environment

Additional context/Screenshots

Log output of event object from the code example above:

image