ALB 触发器 Lambda 函数缺少权限 CDK
ALB Trigger Lamda function missing permission CDK
目前我在从 ALB 调用 Lamda 函数作为触发函数时遇到了问题。我收到错误消息,
elasticloadbalancing principal does not have permission to
invoke arn:aws:lambda:us-east-2:ACN:function
API: elasticloadbalancingv2:RegisterTargets elasticloadbalancing principal
does not have permission to invoke arn:aws:lambda:us-east-...function:Ddns
from target group arn:aws:elasticloadbalancing:us-east-2:...targetgroup/DdnsL
export class DdnsLamdaApiGateWayCdkStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const vpc = Vpc.fromLookup(this, 'global-vpc', {
vpcId: 'vpc-a0b8bec8',
});
const sg = ec2.SecurityGroup.fromSecurityGroupId(this, 'SG', 'sg-0740900526b94fd8f')
const fn = new lambda.Function(this, "API", {
handler: 'index.handler',
runtime: Runtime.NODEJS_12_X,
role: Role.fromRoleArn(this, 'lambda-role', 'arn:aws:iam::.....:role/service-role/LamdaR'),
code: Code.fromInline("test"),
});
fn.addToRolePolicy( new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: [
"lambda:InvokeFunction"
],
resources: [
"*"
]
}));
const lb = new elbv2.ApplicationLoadBalancer(this, "LoadBalancer", {
vpc,
internetFacing: false,
securityGroup: sg
});
const listener = lb.addListener("Listener", {
port: 80,
});
listener.addTargets('Targets', {
targets: [new LambdaALBTarget(fn)]
});
}
}
class LambdaALBTarget implements elbv2.IApplicationLoadBalancerTarget {
private fn: lambda.IFunction;
constructor(fn: lambda.IFunction) {
this.fn = fn;
}
attachToApplicationTargetGroup(
targetGroup: elbv2.ApplicationTargetGroup
): elbv2.LoadBalancerTargetProps {
return {
targetType: "lambda" as elbv2.TargetType,
targetJson: {
id: this.fn.functionArn
}
};
}
}
我假设 -> 我缺少此特定权限:
LambdaFunctionPermission:
Type: AWS::Lambda::Permission
Properties:
Action: lambda:InvokeFunction
FunctionName: !GetAtt LambdaTargetFunction.Arn
Principal: elasticloadbalancing.amazonaws.com
SourceArn: !Ref TargetGroup
但我不知道如何在给定的源代码中包含此权限。有没有人遇到同样的问题并知道如何解决?
我找到了一个解决方法,在部署堆栈时自动设置权限,而不是创建 class LambdaALBTarget,然后调用方法 attachToApplicationTargetGroup,只需将(新 LambdaTarget)添加到侦听器 ->当您将目标添加到负载均衡器时,attachToApplicationTargetGroup&attachToNetworkTargetGroup 会自动调用
listener.addTargets('Targets', {
targets: [new LambdaTarget(fn)]
});
...
这里是创建调用函数权限的部分(template.json)
"APIInvokeServicePrincipalelasticloadbalancingamazonawscom68C82386": {
"Type": "AWS::Lambda::Permission",
"Properties": {
"Action": "lambda:InvokeFunction",
"FunctionName": {
"Fn::GetAtt": [
"API62EA1CFF",
"Arn"
]
},
"Principal": "elasticloadbalancing.amazonaws.com"
},
"Metadata": {
"aws:cdk:path": "DdnsLamdaApiGateWayCdkStack/API/InvokeServicePrincipal(elasticloadbalancing.amazonaws.com)"
}
这是完成的源代码
export class DdnsLamdaApiGateWayCdkStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const vpc = Vpc.fromLookup(this, 'global-vpc', {
vpcId: '....',
});
const code = fs.readFileSync('./code.js','utf8');
const dnsRegistrationRole = new Role(this, 'DnsRegRole', {
roleName: 'Lamda-DnsRegRole',
managedPolicies: [
ManagedPolicy.fromAwsManagedPolicyName('AmazonVPCFullAccess'),
ManagedPolicy.fromAwsManagedPolicyName('AmazonRoute53AutoNamingRegistrantAccess'),
ManagedPolicy.fromAwsManagedPolicyName('AWSLambdaBasicExecutionRole '),
],
inlinePolicies: {
Route53ListHostedZone: new PolicyDocument({
statements: [
new PolicyStatement({
actions: ['route53:ListResourceRecordSets'],
resources: ['arn:aws:route53:::hostedzone/*'],
}),
],
}),
},
assumedBy: new ServicePrincipal('lambda.amazonaws.com'),
});
const dnsRegistrationLambda = new lambda.Function(this, "API", {
handler: 'index.handler',
runtime: Runtime.NODEJS_12_X,
role: dnsRegistrationRole,
code: Code.fromInline(code),
memorySize: 256,
});
const loadBalancerSecurityGroup = new ec2.SecurityGroup(this, "loadBalancer-security-group", {
vpc: vpc,
allowAllOutbound: true,
description: 'loadBalancerSecurityGroup'
});
loadBalancerSecurityGroup.addIngressRule(ec2.Peer.anyIpv4(),ec2.Port.tcp(80),"HTTP");
loadBalancerSecurityGroup.addIngressRule(ec2.Peer.anyIpv4(),ec2.Port.tcp(443),"HTTPS")
const lb = new elbv2.ApplicationLoadBalancer(this, "LoadBalancer", {
vpc,
internetFacing: true,
securityGroup: loadBalancerSecurityGroup
});
const listener = lb.addListener("Listener", {
port: 80,
});
listener.addTargets('Targets', {
targets: [new LambdaTarget(dnsRegistrationLambda)]
});
}
}
基本上我已经用 ALB&Lamda 构建了一个无服务器动态 DNS 系统
目前我在从 ALB 调用 Lamda 函数作为触发函数时遇到了问题。我收到错误消息,
elasticloadbalancing principal does not have permission to
invoke arn:aws:lambda:us-east-2:ACN:function
API: elasticloadbalancingv2:RegisterTargets elasticloadbalancing principal
does not have permission to invoke arn:aws:lambda:us-east-...function:Ddns
from target group arn:aws:elasticloadbalancing:us-east-2:...targetgroup/DdnsL
export class DdnsLamdaApiGateWayCdkStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const vpc = Vpc.fromLookup(this, 'global-vpc', {
vpcId: 'vpc-a0b8bec8',
});
const sg = ec2.SecurityGroup.fromSecurityGroupId(this, 'SG', 'sg-0740900526b94fd8f')
const fn = new lambda.Function(this, "API", {
handler: 'index.handler',
runtime: Runtime.NODEJS_12_X,
role: Role.fromRoleArn(this, 'lambda-role', 'arn:aws:iam::.....:role/service-role/LamdaR'),
code: Code.fromInline("test"),
});
fn.addToRolePolicy( new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: [
"lambda:InvokeFunction"
],
resources: [
"*"
]
}));
const lb = new elbv2.ApplicationLoadBalancer(this, "LoadBalancer", {
vpc,
internetFacing: false,
securityGroup: sg
});
const listener = lb.addListener("Listener", {
port: 80,
});
listener.addTargets('Targets', {
targets: [new LambdaALBTarget(fn)]
});
}
}
class LambdaALBTarget implements elbv2.IApplicationLoadBalancerTarget {
private fn: lambda.IFunction;
constructor(fn: lambda.IFunction) {
this.fn = fn;
}
attachToApplicationTargetGroup(
targetGroup: elbv2.ApplicationTargetGroup
): elbv2.LoadBalancerTargetProps {
return {
targetType: "lambda" as elbv2.TargetType,
targetJson: {
id: this.fn.functionArn
}
};
}
}
我假设 -> 我缺少此特定权限:
LambdaFunctionPermission:
Type: AWS::Lambda::Permission
Properties:
Action: lambda:InvokeFunction
FunctionName: !GetAtt LambdaTargetFunction.Arn
Principal: elasticloadbalancing.amazonaws.com
SourceArn: !Ref TargetGroup
但我不知道如何在给定的源代码中包含此权限。有没有人遇到同样的问题并知道如何解决?
我找到了一个解决方法,在部署堆栈时自动设置权限,而不是创建 class LambdaALBTarget,然后调用方法 attachToApplicationTargetGroup,只需将(新 LambdaTarget)添加到侦听器 ->当您将目标添加到负载均衡器时,attachToApplicationTargetGroup&attachToNetworkTargetGroup 会自动调用
listener.addTargets('Targets', {
targets: [new LambdaTarget(fn)]
});
...
这里是创建调用函数权限的部分(template.json)
"APIInvokeServicePrincipalelasticloadbalancingamazonawscom68C82386": {
"Type": "AWS::Lambda::Permission",
"Properties": {
"Action": "lambda:InvokeFunction",
"FunctionName": {
"Fn::GetAtt": [
"API62EA1CFF",
"Arn"
]
},
"Principal": "elasticloadbalancing.amazonaws.com"
},
"Metadata": {
"aws:cdk:path": "DdnsLamdaApiGateWayCdkStack/API/InvokeServicePrincipal(elasticloadbalancing.amazonaws.com)"
}
这是完成的源代码
export class DdnsLamdaApiGateWayCdkStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const vpc = Vpc.fromLookup(this, 'global-vpc', {
vpcId: '....',
});
const code = fs.readFileSync('./code.js','utf8');
const dnsRegistrationRole = new Role(this, 'DnsRegRole', {
roleName: 'Lamda-DnsRegRole',
managedPolicies: [
ManagedPolicy.fromAwsManagedPolicyName('AmazonVPCFullAccess'),
ManagedPolicy.fromAwsManagedPolicyName('AmazonRoute53AutoNamingRegistrantAccess'),
ManagedPolicy.fromAwsManagedPolicyName('AWSLambdaBasicExecutionRole '),
],
inlinePolicies: {
Route53ListHostedZone: new PolicyDocument({
statements: [
new PolicyStatement({
actions: ['route53:ListResourceRecordSets'],
resources: ['arn:aws:route53:::hostedzone/*'],
}),
],
}),
},
assumedBy: new ServicePrincipal('lambda.amazonaws.com'),
});
const dnsRegistrationLambda = new lambda.Function(this, "API", {
handler: 'index.handler',
runtime: Runtime.NODEJS_12_X,
role: dnsRegistrationRole,
code: Code.fromInline(code),
memorySize: 256,
});
const loadBalancerSecurityGroup = new ec2.SecurityGroup(this, "loadBalancer-security-group", {
vpc: vpc,
allowAllOutbound: true,
description: 'loadBalancerSecurityGroup'
});
loadBalancerSecurityGroup.addIngressRule(ec2.Peer.anyIpv4(),ec2.Port.tcp(80),"HTTP");
loadBalancerSecurityGroup.addIngressRule(ec2.Peer.anyIpv4(),ec2.Port.tcp(443),"HTTPS")
const lb = new elbv2.ApplicationLoadBalancer(this, "LoadBalancer", {
vpc,
internetFacing: true,
securityGroup: loadBalancerSecurityGroup
});
const listener = lb.addListener("Listener", {
port: 80,
});
listener.addTargets('Targets', {
targets: [new LambdaTarget(dnsRegistrationLambda)]
});
}
}
基本上我已经用 ALB&Lamda 构建了一个无服务器动态 DNS 系统