pulumi / pulumi-aws-apigateway

Apache License 2.0
12 stars 5 forks source link

Simplify crafting Authorizer Lambdas #152

Open flostadler opened 3 months ago

flostadler commented 3 months ago

Hello!

Issue details

In awsx-classic, we offered utility functions and types for crafting authorization lambdas. Those resources helped users define their API GW authorization configuration. Those helpers were dropped when moving to pulumi-aws-apigateway.

E.g.

Creating authorization configuration for API GWs is more complex with pulumi-aws-apigateway now.

This is what's required right now to craft a sample authorizer:

const authorizer = {
    authType: "custom",
    authorizerName: "jwt-rsa-custom-authorizer",
    parameterName: "Authorization",
    identityValidationExpression: "^Bearer [-0-9a-zA-Z\._]*$",
    type: "token",
    parameterLocation: "header",
    authorizerResultTtlInSeconds: 300,
    handler: new aws.lambda.CallbackFunction("authorizer", {
        callback: authorizerLambda(authParams),
    }),
}

const api = new apigateway.RestAPI("my-api", {
    stageName: "my-api",
    routes: [{
        path: "/{proxy+}",
        method: "ANY",
        eventHandler: apiHandler,
        authorizers: [authorizer]
    }],
});

We don't have an example of how an API GW with Lambda authorizer looks like with pulumi-aws-apigateway. We should add an example to make migration easier. Optionally we could add additional resources to make crafting those authorizers easier.

Affected area/feature

flostadler commented 3 months ago

I actually found that we still have those types in pulumi-aws-apigateway, they're just not exported anymore because the node sdk is autogenerated now: https://github.com/pulumi/pulumi-aws-apigateway/blob/4d6c45875cc125bc0ee095dc4753111d0691667a/provider/cmd/pulumi-resource-aws-apigateway/apigateway/lambdaAuthorizer.ts#L25

We should clean this up

El-Fitz commented 1 month ago

Hi!

I discovered Pulumi two days ago, somehow ended up using @pulumi/awsx in addition to both @pulumi/aws-native and @pulumi/aws(you guys have many, many, packages, and it's hard to tell them apart), and have spent most of today wondering why my authorizer failed at runtime (Error: Cannot find module '@pulumi/awsx/classic/index.js), even though as you can see it was quite straightforward:

import * as awsx from "@pulumi/awsx/classic";

export interface Props {
    // JWKS URI, etc
}

export const authorize = (props: Props) => async (event: awsx.apigateway.AuthorizerEvent) => {
    try {
            return await authenticate(props)(event);
    }
    catch (err) {
            console.log(err);
            // Tells API Gateway to return a 401 Unauthorized response
            throw new Error("Unauthorized");
    }
}

// Always allow
const authenticate = (props: Props) => async (event: awsx.apigateway.AuthorizerEvent): Promise<awsx.apigateway.AuthorizerResponse> => {
    const { } = props;
    return awsx.classic.apigateway.authorizerResponse("", 'Allow', event.methodArn);
}

From what I've come to understand, "pulumi will not include @pulumi/... packages with the Lambda", hence my crash, I should use [@pulumi/pulumi-aws-api-gateway rather than @pulumi/awsx/classic], and @pulumi/pulumi-aws-api-gateway doesn't seem to have comparable convenience methods for crafting lambda authorizers.

Is that accurate?

flostadler commented 1 month ago

Hey @El-Fitz, you're correct that @pulumi/awsx/classic has been deprecated and will only receive updates for critical security fixes. The helper methods we're removed, but they were mostly just thin wrappers around objects.

Have a look at this example, it shows how to set up an API gateway with auth: https://github.com/pulumi/pulumi-aws-apigateway/tree/10dbb407b5136c227e2874ff1d1b4f0fe3e93782/examples/apigateway-auth

El-Fitz commented 1 month ago

Hi @flostadler! Yes, I found the example.

On the topic of Authorizer lambdas convenience, how would you reuse an authorizer across multiple methods or endpoints? It seems setting it the way shown in the example will create a new authorizer each time, and I haven't found a way to reference and reuse it. It would seem so fare that reusability requires using a much more boilerplate-heavy syntax. Is that accurate?

flostadler commented 4 weeks ago

@El-Fitz authorizers should get re-used if you pass them to multiple routes. Here's an example of that: https://github.com/pulumi/pulumi-aws-apigateway/blob/10dbb407b5136c227e2874ff1d1b4f0fe3e93782/examples/apigateway-multi-auth/index.ts#L31-L49