Skip to content

Instantly share code, notes, and snippets.

@chris
Created May 21, 2021 17:25
Show Gist options
  • Save chris/75f2bbbc2d2d743b39aa92b8d84372da to your computer and use it in GitHub Desktop.
Save chris/75f2bbbc2d2d743b39aa92b8d84372da to your computer and use it in GitHub Desktop.
Lambda custom authorizer example
package main
import (
"context"
"errors"
"strings"
"github.com/aws/aws-lambda-go/events"
"github.com/aws/aws-lambda-go/lambda"
)
const (
APIKeyHeader = "x-api-key"
AppIDHeader = "x-app-id"
// APIKey is our one and only API key for now
// TODO: in real life you probably want to fetch these from a DB or whatever your source of API keys is
APIKey = "some-api-key-text-goes-here"
// AppID is our only allowed app for now
AppID = "myapp"
)
func validAPIKey(apiKey, appID string) bool {
return apiKey == APIKey && appID == AppID
}
// resourceWildcard returns a wildcard resource specifier for the policy document
// so that we authorize the API key user for all API's in this system with a
// single call. This is desired because API Gateway caches this policy, so if
// we use the exact methodArn of the HTTP call, it winds up then blocking that
// same user from calling other APIs because the policy for their API key is
// cached with just the first API call's methodArn. See:
// https://forum.serverless.com/t/help-really-weird-access-denied-issue/12676/6
// It strips off everything after the first encountered slash, and set that to
// the wildcard. e.g. a methodArn of:
// arn:aws:execute-api:us-east-2:123456789000:abcde12345/dev/POST/widgets
// will be converted to:
// arn:aws:execute-api:us-east-2:123456789000:abcde12345/*
func resourceWildcard(methodArn string) string {
parts := strings.Split(methodArn, "/")
return parts[0] + "/*"
}
func generatePolicy(principalID, effect, resource string) events.APIGatewayCustomAuthorizerResponse {
authResponse := events.APIGatewayCustomAuthorizerResponse{PrincipalID: principalID}
if effect != "" && resource != "" {
authResponse.PolicyDocument = events.APIGatewayCustomAuthorizerPolicy{
Version: "2012-10-17",
Statement: []events.IAMPolicyStatement{
{
Action: []string{"execute-api:Invoke"},
Effect: effect,
Resource: []string{resource},
},
},
}
}
return authResponse
}
func handler(ctx context.Context, request events.APIGatewayCustomAuthorizerRequestTypeRequest) (events.APIGatewayCustomAuthorizerResponse, error) {
if validAPIKey(request.Headers[APIKeyHeader], request.Headers[AppIDHeader]) {
return generatePolicy("user", "Allow", resourceWildcard(request.MethodArn)), nil
}
return events.APIGatewayCustomAuthorizerResponse{}, errors.New("Unauthorized")
}
func main() {
lambda.Start(handler)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment