fix: resolve error when using destinations with per-function IAM roles#13293
fix: resolve error when using destinations with per-function IAM roles#13293
Conversation
This commit fixes issue #13292 where using Lambda destinations with per-function IAM roles (provider.iam.role.mode: perFunction) caused a TypeError: Cannot read properties of undefined (reading 'Properties'). Root cause: - When per-function IAM mode is enabled, the shared IamRoleLambdaExecution role is not created - The compileFunctionEventInvokeConfig() method did not detect per-function mode and tried to add destination permissions to the non-existent shared role - Additionally, the per-function roles module did not add destination permissions (sqs:SendMessage, sns:Publish, lambda:InvokeFunction, events:PutEvents) for functions using destinations Changes: 1. functions.js: Updated hasAccessPoliciesHandledExternally check to detect per-function IAM mode (provider.iam.role.mode === 'perFunction') 2. roles-per-function-permissions.js: Added applyDestinationPermissions() function that adds the appropriate IAM permissions for Lambda destinations (onSuccess/onFailure) to each function's per-function role Fixes #13292
|
All contributors have signed the CLA ✍️ ✅ |
✅ Snyk checks have passed. No issues have been found so far.
💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse. |
📝 WalkthroughWalkthroughTreats provider IAM configured with Changes
Sequence Diagram(s)sequenceDiagram
participant Packager as "Package step"
participant Compiler as "AwsCompileFunctions"
participant IAM as "Provider IAM config"
participant Permissions as "roles-per-function-permissions"
participant DestService as "Destination service\n(Lambda/SQS/SNS/Events)"
Packager->>Compiler: compileFunctionEventInvokeConfig(function)
Compiler->>IAM: read provider.iam.role (mode)
IAM-->>Compiler: returns mode (e.g., 'perFunction')
alt mode === 'perFunction' or executionRole present
Compiler->>Permissions: applyPerFunctionPermissions(function)
Permissions->>Permissions: applyDestinationPermissions(onSuccess/onFailure)
Permissions->>DestService: emit policy statement (action, resource/ARN)
Compiler->>DestService: create EventInvokeConfig with destinations
else shared-role mode
Compiler->>Compiler: ensureTargetExecutionPermission(target)
Compiler->>DestService: create EventInvokeConfig with destinations
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (2 warnings)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/serverless/lib/plugins/aws/package/lib/roles-per-function-permissions.js (1)
516-595: Fail fast when destination permissions can’t be inferred.In per-function IAM mode,
ensureTargetExecutionPermissionis skipped; ifgetDestinationActionreturnsnull(typo/unsupported type), we now silently skip permissions, which can surface later as runtime delivery failures. Consider throwing (or usingthrowError) to keep behavior consistent with the shared-role path.🧩 Proposed fix
-function applyDestinationPermissions({ - functionObject, - policyStatements, - serverless, -}) { +function applyDestinationPermissions({ + functionObject, + policyStatements, + serverless, + throwError, +}) { const { destinations } = functionObject if (!destinations) return const processDestination = (destinationProperty) => { const action = getDestinationAction(destinationProperty) - if (!action) return + if (!action) { + if (typeof throwError === 'function') { + throwError(`Unsupported destination target`, functionObject) + } + return + } const resourceArn = getDestinationArn(destinationProperty, serverless) policyStatements.push({ Effect: 'Allow', Action: action, Resource: resourceArn, }) } @@ - applyDestinationPermissions({ functionObject, policyStatements, serverless }) + applyDestinationPermissions({ + functionObject, + policyStatements, + serverless, + throwError, + }) }
🤖 Fix all issues with AI agents
In
`@packages/serverless/test/unit/lib/plugins/aws/package/compile/functions.test.js`:
- Around line 661-664: The test currently uses await
expect(awsCompileFunctions.compileFunctions()).resolves.not.toThrow(), which is
invalid because toThrow expects a function; replace that assertion with a direct
await of the promise to ensure it resolves without throwing: change the
assertion to await awsCompileFunctions.compileFunctions(); (locate and update
the test that calls awsCompileFunctions.compileFunctions()).
packages/serverless/test/unit/lib/plugins/aws/package/compile/functions.test.js
Outdated
Show resolved
Hide resolved
This has been addressed |
This commit fixes issue #13292 where using Lambda destinations with per-function IAM roles (provider.iam.role.mode: perFunction) caused a TypeError: Cannot read properties of undefined (reading 'Properties').
Root cause:
Changes:
Fixes #13292
Summary by CodeRabbit
New Features
Tests
Chores
✏️ Tip: You can customize this high-level summary in your review settings.