# AWS SAM template: an HTTP API whose routes require the TrustPin attestation
# authorizer. `npm install --omit=dev && sam deploy --guided`. Replace the
# parameters and point the integration at your API.
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Parameters:
  JwksUrl: { Type: String, Default: "https://attest.example.com/.well-known/jwks.json" }
  Issuer: { Type: String, Default: "https://attest.example.com" }
  Audience: { Type: String, Default: "tprn::project::org_example::prj_example" }
  # Expected tp.prj; empty means the audience when it is a tprn::project:: name.
  Project: { Type: String, Default: "" }
  # "true" refuses tokens without bind (attestation policy tokens.binding: required).
  RequireBind: { Type: String, Default: "false", AllowedValues: ["true", "false"] }
  BackendUrl: { Type: String, Default: "https://api.example.com" }
Resources:
  Authorizer:
    Type: AWS::Serverless::Function
    Properties:
      Runtime: nodejs22.x
      Handler: index.handler
      CodeUri: .
      MemorySize: 256
      Timeout: 5
      Environment:
        Variables:
          TRUSTPIN_JWKS_URL: !Ref JwksUrl
          TRUSTPIN_ISSUER: !Ref Issuer
          TRUSTPIN_AUDIENCE: !Ref Audience
          TRUSTPIN_PROJECT: !Ref Project
          TRUSTPIN_REQUIRE_BIND: !Ref RequireBind
  Api:
    Type: AWS::Serverless::HttpApi
    Properties:
      Auth:
        DefaultAuthorizer: TrustPinAttestation
        Authorizers:
          TrustPinAttestation:
            FunctionArn: !GetAtt Authorizer.Arn
            AuthorizerPayloadFormatVersion: "2.0"
            EnableSimpleResponses: true
            # Never cache: the decision depends on the binding to the
            # Authorization header, not only on the token.
            FunctionInvokeRole: !GetAtt AuthorizerInvokeRole.Arn
            Identity:
              Headers: [TrustPin-Attestation, Authorization]
              ReauthorizeEvery: 0
      DefinitionBody:
        openapi: "3.0.1"
        info: { title: api, version: "1" }
        paths:
          /{proxy+}:
            x-amazon-apigateway-any-method:
              x-amazon-apigateway-integration:
                type: http_proxy
                httpMethod: ANY
                uri: !Sub "${BackendUrl}/{proxy}"
                payloadFormatVersion: "1.0"
  AuthorizerInvokeRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Effect: Allow
            Principal: { Service: apigateway.amazonaws.com }
            Action: sts:AssumeRole
      Policies:
        - PolicyName: invoke-authorizer
          PolicyDocument:
            Version: "2012-10-17"
            Statement:
              - Effect: Allow
                Action: lambda:InvokeFunction
                Resource: !GetAtt Authorizer.Arn
