У меня есть шаблон AWS CloudFormation, написанный на yaml, который успешно создает все необходимые мне ресурсы и настраивает шлюз API для успешного вызова лямбда-файла, за исключением того, что у шлюза API нет разрешения на автоматический вызов лямбда-функции.
В настоящее время мне нужно войти в шлюз API и дать разрешение вручную. Перед этим я получаю ошибку с кодом 500, а потом получаю код 200 и результат, который хочу.
Добавить разрешение на лямбда-функцию
Внизу моего шаблона я попытался сделать разрешение на основе нескольких других сообщений о переполнении стека, которые я видел по этой теме, но я не смог заставить их работать после нескольких часов попыток разных ответов и форматов. Я помещаю полный шаблон ниже.
AWSTemplateFormatVersion: 2010-09-09
Resources:
LambdaRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: 'Allow'
Principal:
Service:
- 'lambda.amazonaws.com'
- 'comprehend.amazonaws.com'
- 'apigateway.amazonaws.com'
Action:
- 'sts:AssumeRole'
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/ComprehendFullAccess'
- 'arn:aws:iam::aws:policy/service-role/ComprehendDataAccessRolePolicy'
- 'arn:aws:iam::aws:policy/AmazonS3FullAccess'
RoleName: LambdaRole
SentimentFunction:
Type: AWS::Lambda::Function
DependsOn:
- LambdaRole
Properties:
Code:
ZipFile: |
import boto3
client = boto3.client('comprehend')
def lambda_handler(event, context):
result = {
'Sentiment': client.detect_sentiment(Text = event['inputTranscript'], LanguageCode='en')['Sentiment'],
'SentimentScore': client.detect_sentiment(Text = event['inputTranscript'], LanguageCode='en')['SentimentScore']
}
return result
FunctionName: 'SentimentFunction'
Handler: index.lambda_handler
Role: !GetAtt LambdaRole.Arn
Runtime: 'python3.9'
SentimentSchedule:
Type: AWS::Events::Rule
Properties:
Description: "Schedule to trigger SentimentFunction every minute"
ScheduleExpression: "cron(* * * * ? *)"
Targets:
- Arn: !GetAtt SentimentFunction.Arn
Id: "SentimentFunction"
SentimentAPI:
Type: AWS::ApiGateway::RestApi
Properties:
EndpointConfiguration:
Types:
- REGIONAL
Name: SentimentAPI
RestApiDeployment:
Type: AWS::ApiGateway::Deployment
DependsOn:
- SentimentAPI
- SentimentAnalysis
Properties:
RestApiId: !Ref SentimentAPI
StageName: dev
SentimentGatewayResource:
Type: AWS::ApiGateway::Resource
DependsOn:
- SentimentAPI
Properties:
ParentId: !GetAtt SentimentAPI.RootResourceId
PathPart: analysis
RestApiId: !Ref SentimentAPI
SentimentAnalysis:
Type: AWS::ApiGateway::Method
DependsOn:
- SentimentGatewayResource
- SentimentAPI
- SentimentFunction
Properties:
ApiKeyRequired: false
AuthorizationType: NONE
HttpMethod: GET
Integration:
IntegrationHttpMethod: GET
IntegrationResponses:
- StatusCode: '200'
PassthroughBehavior: WHEN_NO_TEMPLATES
RequestTemplates:
application/json : '{"inputTranscript": "I want something"}'
Type: AWS
Uri:
!Join
- ''
- - 'arn:'
- !Ref AWS::Partition
- ':apigateway:'
- !Ref AWS::Region
- :lambda:path/2015-03-31/functions/
- !GetAtt SentimentFunction.Arn
- /invocations
MethodResponses:
- ResponseModels:
application/json : Empty
StatusCode: '200'
ResourceId: !Ref SentimentGatewayResource
RestApiId: !Ref SentimentAPI
# vvvvvvvv This doesn't work vvvvvvvv
GWAuth:
Type: AWS::ApiGateway::Authorizer
Properties:
AuthorizerUri: !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${SentimentFunction.Arn}/invocations"
RestApiId: !Ref SentimentAPI
Type: "REQUEST"
IdentitySource: method.request.header.authorization
Name: custom_auth
GWAuthPermission:
Type: AWS::Lambda::Permission
Properties:
Action: lambda:InvokeFunction
FunctionName: !GetAtt SentimentFunction.Arn
Principal: "apigateway.amazonaws.com"
SourceArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${SentimentAPI}/authorizers/${GWAuth}"
Я очень новичок в AWS, поэтому я уверен, что мой шаблон изначально плохо сформирован. Эта ошибка мешала мне добиться большего прогресса. Любая помощь очень ценится!
Сбой лямбда-вызова до предоставления разрешений вручную
Лямбда-вызов работает после предоставления разрешений вручную
У меня есть настройка API для лямбда, которая использует свойство events
в лямбде:
RetrieverLambda:
Type: AWS::Serverless::Function
Properties:
Environment:
Variables:
STAGE:
Ref: Stage
ACCOUNT:
Ref: AWS::AccountId
REGION:
Ref: AWS::Region
CodeUri:
Bucket: {'Fn::If': ['UseBatsKey', 'BATS::SAM::CodeS3Bucket', {"Fn::ImportValue": {Ref: 'DeploymentBucketImportName'}}]}
Key: BATS::SAM::CodeS3Key
Events:
APIG:
Properties:
Method: ANY
Path: /
RestApiId: {Ref: LambdaAPIDefinition}
Type: Api
proxy:
Type: Api
Properties:
Path: /{proxy+}
Method: ANY
RestApiId: {Ref: LambdaAPIDefinition}
Handler: ...
.....
И шлюз Api определяется так же, как вы это сделали:
LambdaAPIDefinition:
Type: 'AWS::Serverless::Api'
Properties:
StageName: {Ref: Stage}
EndpointConfiguration: REGIONAL
Auth:
DefaultAuthorizer: AWS_IAM
InvokeRole: NONE # removal of this will cause deployment failure with the error
#'Caller provided credentials not allowed when resource policy is set'
ResourcePolicy:
CustomStatements:
- Effect: 'Allow'
Action: 'execute-api:Invoke'
Resource: ['execute-api:/*/*/*']
Principal:
AWS:
- !Sub "arn:aws:iam::${AWS::AccountId}:user/ApiUser"
В приведенном выше примере я использую пользователя IAM
вместо роли. Но я не думаю, что это имеет значение здесь.
Я думаю, добавление триггера события в вашу конструкцию Lambda должно это исправить.