Skip to content

Commit 78d7b6f

Browse files
committed
feat(llmo): close LLMO-5566 architectural gaps — org-scoped externalId, CF templates, setupType, rescan endpoint
- gateEdgeOptimizeWizard now derives externalId = toSafeAwsName(imsOrgId) server-side; FE no longer sends externalId - getEdgeOptimizeBootstrapUrl accepts setupType ('log-only'|'log-and-oae') and selects the matching CF template key - Add customer-bootstrap-role.yaml and customer-bootstrap-role-log-only.yaml CloudFormation templates - Add POST /sites/:siteId/llmo/cdn-log-rescan (rescanCdnLogDelivery) for idempotent re-enabling of log delivery - Remove 14 stale 'externalId missing' tests; add 9 tests for rescanCdnLogDelivery Introduced by: #2680
1 parent 296f489 commit 78d7b6f

7 files changed

Lines changed: 670 additions & 270 deletions

File tree

src/controllers/llmo/llmo.js

Lines changed: 244 additions & 129 deletions
Large diffs are not rendered by default.

src/routes/facs-capabilities.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ const routeFacsCapabilities = {
163163
'POST /sites/:siteId/llmo/edge-optimize/verify',
164164
'POST /sites/:siteId/llmo/edge-optimize/deploy',
165165
'POST /sites/:siteId/llmo/cdn-log-delivery',
166+
'POST /sites/:siteId/llmo/cdn-log-rescan',
166167
// Admin-only writes
167168
'POST /sites', // hasAdminAccess
168169
'DELETE /sites/:siteId', // restricted (always 403)

src/routes/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,7 @@ export default function getRouteHandlers(
521521
'POST /sites/:siteId/llmo/edge-optimize/verify': llmoController.verifyEdgeOptimizeRouting,
522522
'POST /sites/:siteId/llmo/edge-optimize/deploy': llmoController.deployEdgeOptimize,
523523
'POST /sites/:siteId/llmo/cdn-log-delivery': llmoController.enableCdnLogDelivery,
524+
'POST /sites/:siteId/llmo/cdn-log-rescan': llmoController.rescanCdnLogDelivery,
524525
'GET /sites/:siteId/llmo/strategy': llmoController.getStrategy,
525526
'PUT /sites/:siteId/llmo/strategy': llmoController.saveStrategy,
526527
'GET /sites/:siteId/llmo/edge-optimize-status': llmoController.checkEdgeOptimizeStatus,

src/routes/required-capabilities.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ export const INTERNAL_ROUTES = [
145145
'POST /sites/:siteId/llmo/edge-optimize/verify',
146146
'POST /sites/:siteId/llmo/edge-optimize/deploy',
147147
'POST /sites/:siteId/llmo/cdn-log-delivery',
148+
'POST /sites/:siteId/llmo/cdn-log-rescan',
148149
'PUT /sites/:siteId/llmo/opportunities-reviewed',
149150

150151
// LLMO Cloudflare onboarding - LLMO-admin self-service, gated by isLLMOAdministrator();
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
AWSTemplateFormatVersion: '2010-09-09'
2+
Description: >
3+
Adobe LLMO EdgeOptimize connector role — log-only setup (CDN log delivery only, no
4+
Lambda@Edge). Deploy this stack in the customer AWS account to grant Adobe SpaceCat
5+
permission to read CloudFront distribution configs and enable CloudWatch Logs Delivery
6+
for CDN access-log forwarding to Adobe. Use this template when the customer only wants
7+
log forwarding without the EdgeOptimize routing feature.
8+
9+
Setup type: log-only (logs only, no Origin@Edge routing)
10+
11+
Parameters:
12+
TrustedPrincipalArn:
13+
Type: String
14+
Description: ARN of the Adobe SpaceCat IAM principal allowed to assume this role.
15+
AllowedPattern: 'arn:aws:iam::[0-9]{12}:.*'
16+
ExternalId:
17+
Type: String
18+
Description: >
19+
Org-scoped external ID derived from the customer IMS org. Must match the value
20+
SpaceCat presents during AssumeRole (confused-deputy prevention).
21+
MinLength: 1
22+
RoleName:
23+
Type: String
24+
Default: AdobeLLMOptimizerCloudFrontConnectorRole
25+
Description: Name for the IAM role created in this account.
26+
27+
Resources:
28+
ConnectorRole:
29+
Type: AWS::IAM::Role
30+
Properties:
31+
RoleName: !Ref RoleName
32+
AssumeRolePolicyDocument:
33+
Version: '2012-10-17'
34+
Statement:
35+
- Effect: Allow
36+
Principal:
37+
AWS: !Ref TrustedPrincipalArn
38+
Action: sts:AssumeRole
39+
Condition:
40+
StringEquals:
41+
sts:ExternalId: !Ref ExternalId
42+
Description: >
43+
Grants Adobe SpaceCat cross-account read access to CloudFront distributions and
44+
CloudWatch Logs Delivery permission for CDN log forwarding. Does not include
45+
Lambda@Edge or CloudFront write permissions.
46+
Policies:
47+
- PolicyName: EdgeOptimizeLogOnlyPolicy
48+
PolicyDocument:
49+
Version: '2012-10-17'
50+
Statement:
51+
# CloudFront read access — used for distribution discovery and delivery-source wiring
52+
- Sid: CloudFrontRead
53+
Effect: Allow
54+
Action:
55+
- cloudfront:ListDistributions
56+
- cloudfront:GetDistribution
57+
- cloudfront:GetDistributionConfig
58+
Resource: '*'
59+
# CloudWatch Logs Delivery — create delivery source + link to Adobe destination
60+
- Sid: LogsDeliveryWrite
61+
Effect: Allow
62+
Action:
63+
- logs:PutDeliverySource
64+
- logs:CreateDelivery
65+
- logs:GetDeliverySource
66+
- logs:DescribeDeliveries
67+
Resource: '*'
68+
69+
Outputs:
70+
RoleArn:
71+
Description: ARN of the connector IAM role
72+
Value: !GetAtt ConnectorRole.Arn
73+
RoleName:
74+
Description: Name of the connector IAM role
75+
Value: !Ref ConnectorRole
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
AWSTemplateFormatVersion: '2010-09-09'
2+
Description: >
3+
Adobe LLMO EdgeOptimize connector role — full setup (CDN log delivery + Lambda@Edge
4+
origin-request routing). Deploy this stack in the customer AWS account to grant Adobe
5+
SpaceCat permission to read CloudFront distribution configs, create Lambda@Edge functions,
6+
and enable CloudWatch Logs Delivery for CDN access-log forwarding to Adobe.
7+
8+
Setup type: log-and-oae (logs + Origin@Edge routing)
9+
10+
Parameters:
11+
TrustedPrincipalArn:
12+
Type: String
13+
Description: ARN of the Adobe SpaceCat IAM principal allowed to assume this role.
14+
AllowedPattern: 'arn:aws:iam::[0-9]{12}:.*'
15+
ExternalId:
16+
Type: String
17+
Description: >
18+
Org-scoped external ID derived from the customer IMS org. Must match the value
19+
SpaceCat presents during AssumeRole (confused-deputy prevention).
20+
MinLength: 1
21+
RoleName:
22+
Type: String
23+
Default: AdobeLLMOptimizerCloudFrontConnectorRole
24+
Description: Name for the IAM role created in this account.
25+
26+
Resources:
27+
ConnectorRole:
28+
Type: AWS::IAM::Role
29+
Properties:
30+
RoleName: !Ref RoleName
31+
AssumeRolePolicyDocument:
32+
Version: '2012-10-17'
33+
Statement:
34+
- Effect: Allow
35+
Principal:
36+
AWS: !Ref TrustedPrincipalArn
37+
Action: sts:AssumeRole
38+
Condition:
39+
StringEquals:
40+
sts:ExternalId: !Ref ExternalId
41+
Description: >
42+
Grants Adobe SpaceCat cross-account access to CloudFront distributions and
43+
CloudWatch Logs Delivery for CDN log forwarding and Lambda@Edge routing.
44+
Policies:
45+
- PolicyName: EdgeOptimizeLogAndOAEPolicy
46+
PolicyDocument:
47+
Version: '2012-10-17'
48+
Statement:
49+
# CloudFront read access — used for distribution discovery and config inspection
50+
- Sid: CloudFrontRead
51+
Effect: Allow
52+
Action:
53+
- cloudfront:ListDistributions
54+
- cloudfront:GetDistribution
55+
- cloudfront:GetDistributionConfig
56+
Resource: '*'
57+
# CloudFront write access — used to add the Edge Optimize origin and routing function
58+
- Sid: CloudFrontWrite
59+
Effect: Allow
60+
Action:
61+
- cloudfront:UpdateDistribution
62+
- cloudfront:CreateFunction
63+
- cloudfront:UpdateFunction
64+
- cloudfront:PublishFunction
65+
- cloudfront:DescribeFunction
66+
- cloudfront:GetFunction
67+
- cloudfront:CreateCachePolicy
68+
- cloudfront:GetCachePolicy
69+
- cloudfront:ListCachePolicies
70+
Resource: '*'
71+
# Lambda@Edge — create and version the origin-request handler
72+
- Sid: LambdaEdgeWrite
73+
Effect: Allow
74+
Action:
75+
- lambda:CreateFunction
76+
- lambda:UpdateFunctionCode
77+
- lambda:UpdateFunctionConfiguration
78+
- lambda:GetFunction
79+
- lambda:PublishVersion
80+
- lambda:ListVersionsByFunction
81+
- lambda:AddPermission
82+
- lambda:GetPolicy
83+
Resource: !Sub 'arn:aws:lambda:us-east-1:${AWS::AccountId}:function:edgeoptimize-origin'
84+
# IAM PassRole — needed to attach the Lambda execution role
85+
- Sid: LambdaExecRolePass
86+
Effect: Allow
87+
Action: iam:PassRole
88+
Resource: !Sub 'arn:aws:iam::${AWS::AccountId}:role/edgeoptimize-lambda-exec'
89+
# IAM CreateRole — create the Lambda execution role if absent
90+
- Sid: LambdaExecRoleCreate
91+
Effect: Allow
92+
Action:
93+
- iam:CreateRole
94+
- iam:PutRolePolicy
95+
- iam:AttachRolePolicy
96+
- iam:GetRole
97+
Resource: !Sub 'arn:aws:iam::${AWS::AccountId}:role/edgeoptimize-lambda-exec'
98+
# CloudWatch Logs Delivery — create delivery source + link to Adobe destination
99+
- Sid: LogsDeliveryWrite
100+
Effect: Allow
101+
Action:
102+
- logs:PutDeliverySource
103+
- logs:CreateDelivery
104+
- logs:GetDeliverySource
105+
- logs:DescribeDeliveries
106+
Resource: '*'
107+
108+
Outputs:
109+
RoleArn:
110+
Description: ARN of the connector IAM role
111+
Value: !GetAtt ConnectorRole.Arn
112+
RoleName:
113+
Description: Name of the connector IAM role
114+
Value: !Ref ConnectorRole

0 commit comments

Comments
 (0)