0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Lambda Function URLをCloudFormationやCDKで作る

Posted at

はじめに

Lambdaを、API Gatewayを用いずに、URLで実行できる機能があります。

これをCloudFormation(とSAM)、CDKで作るサンプルをまとめてみました。
認証タイプは2つありますが、今回は「NONE」の例だけです。

参考

CloudFormation

昔書いた以下のテンプレートを用います。

最後に以下を加えただけです。

  • AWS::Lambda::Url
  • AWS::Lambda::Permission
  • 出力
    • スタックからURLがわかるようにするためだけ
    • Lambda関数のプロパティから確認可能
AWSTemplateFormatVersion: 2010-09-09

Parameters:
  LambdaFunctionName:
    Type: String
    Default: function-https

Resources:
  FunctionLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub "/aws/lambda/${LambdaFunctionName}"
      RetentionInDays: 3653   # 未指定時は「失効しない」

  FunctionRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub "for-lambdafunction-${LambdaFunctionName}"
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: '/service-role/'
      Policies:
        # CloudWatch
        - PolicyName: write-cloudwatchlogs
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action: 
                  - 'logs:CreateLogStream'
                  - 'logs:PutLogEvents'
                Resource: !Sub "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${LambdaFunctionName}:*"    

  TargetFunction:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: !Ref LambdaFunctionName
      Role: !GetAtt FunctionRole.Arn
      Runtime: python3.9
      Handler: index.lambda_handler
      Code:
        ZipFile: !Sub |
          def lambda_handler(event, context):
            return 'hello, from function 1.'

  ##################################################
  # 以下、URLと許可
  ##################################################
  TargetFunctionUrl:
    Type: AWS::Lambda::Url
    Properties:
      AuthType: NONE
      TargetFunctionArn: !GetAtt TargetFunction.Arn

  TargetFunctionUrlPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunctionUrl
      FunctionName: !GetAtt TargetFunction.Arn
      FunctionUrlAuthType: NONE
      Principal: "*"

Outputs:
  FunctionUrl:
    Value: !GetAtt TargetFunctionUrl.FunctionUrl
    Export:
      Name: TargetFunctionUrl

SAM

こちらも、昔のコードを流用します。

先ほどと同じものを追加するだけです。

template..yaml
AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31
Description: SAM Template for Lambda Function

Parameters:
  LambdaFunctionName:
    Type: String
    Default: "testfunction001"

Resources:
  FunctionRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub "for-lambdafunction-${LambdaFunctionName}"
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: '/service-role/'
      Policies:
        # CloudWatch
        - PolicyName: write-cloudwatchlogs
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action: 
                  - 'logs:CreateLogStream'
                  - 'logs:PutLogEvents'
                Resource: !Sub "arn:aws:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${LambdaFunctionName}:*"

  FunctionLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: !Sub /aws/lambda/${LambdaFunctionName}
      RetentionInDays: 3653

  TargetFunction:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: !Ref LambdaFunctionName
      Role: !GetAtt FunctionRole.Arn
      CodeUri: functions/
      Handler: app.lambda_handler
      Runtime: python3.9
      
  ##################################################
  # 以下、URLと許可
  ##################################################
  TargetFunctionUrl:
    Type: AWS::Lambda::Url
    Properties:
      AuthType: NONE
      TargetFunctionArn: !GetAtt TargetFunction.Arn

  TargetFunctionUrlPermission:
    Type: AWS::Lambda::Permission
    Properties:
      Action: lambda:InvokeFunctionUrl
      FunctionName: !GetAtt TargetFunction.Arn
      FunctionUrlAuthType: NONE
      Principal: "*"

Outputs:
  FunctionUrl:
    Value: !GetAtt TargetFunctionUrl.FunctionUrl
    Export:
      Name: TargetFunctionUrl

CDK

CDKで記述すると以下のようになります。CFnテンプレートと比べてとてもシンプルです。

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as path from 'path';

export class UsecdkStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const TargetFunction = new lambda.Function(this, 'TargetFunction',{
      runtime: lambda.Runtime.PYTHON_3_9,
      handler: 'app.lambda_handler',
      code: lambda.Code.fromAsset(path.join(__dirname,'../functions/'))
    });
    
    // Function URL
    const fnUrl = TargetFunction.addFunctionUrl({
      authType: lambda.FunctionUrlAuthType.NONE,
    });
    
    // URLをアウトプット
    new cdk.CfnOutput(this,'TargetFunctionUrl',{
      value: fnUrl.url,
    });
  }
}

先に記載したCFnテンプレートとSAMとは以下の点が異なりますが、Function URLの例には影響ないので除きました。

  • Lambda用のロールは作成しない
    • 自動でAWSLambdaBasicExecutionRoleがアタッチされます
  • Lambda用のロググループは作成しない
    • CFnテンプレート変換時に以下のプロパティで上書きされてしまったので定義しませんでした
      • 保持期間:1年
      • 削除ポリシー: RETAIN

使用するLambda関数はfunctionsフォルダ内に置きます。

functions/app.py
def lambda_handler(event, context):

    print('sample function')
    return {
        'statusCode': 200,
        'body': 'Hello from Lambda!'
    }

あとはコンパイルして変換してデプロイになります。方法は昔まとめた記事がありますのでそちらをご確認ください。

おわりに

今回、ちょっと使ってみたくて触った内容を記事にしました。
どなたかの助けになれば幸いです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?