-
Notifications
You must be signed in to change notification settings - Fork 78
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Product's fulfillment URL is updated via Catalog API. Templates requi…
…res onw ProductId instead of the ProductCode.
- Loading branch information
Oscar Carrasquero
committed
Sep 10, 2024
1 parent
f183310
commit 304b097
Showing
1 changed file
with
166 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -50,7 +50,8 @@ Parameters: | |
Description: "This is the AWS region of the SNS Entitlement and Subscription topics for your product." | ||
AllowedValues: | ||
- us-east-1 | ||
ProductCode: | ||
|
||
ProductId: | ||
Type: String | ||
AllowedPattern: ".*" | ||
|
||
|
@@ -290,7 +291,7 @@ Resources: | |
MySQSEvent: | ||
Type: SNS | ||
Properties: | ||
Topic: !Sub 'arn:aws:sns:${SNSRegion}:${SNSAccountID}:aws-mp-entitlement-notification-${ProductCode}' | ||
Topic: !Sub 'arn:aws:sns:${SNSRegion}:${SNSAccountID}:aws-mp-entitlement-notification-${GetProductCode.ProductCode}' | ||
Region: !Sub '${SNSRegion}' | ||
SqsSubscription: | ||
BatchSize: 1 | ||
|
@@ -321,7 +322,7 @@ Resources: | |
Type: SNS | ||
Properties: | ||
#Topic: !Ref SubscriptionSNSTopic | ||
Topic: !Sub 'arn:aws:sns:${SNSRegion}:${SNSAccountID}:aws-mp-subscription-notification-${ProductCode}' | ||
Topic: !Sub 'arn:aws:sns:${SNSRegion}:${SNSAccountID}:aws-mp-subscription-notification-${GetProductCode.ProductCode}' | ||
Region: !Sub '${SNSRegion}' | ||
SqsSubscription: true | ||
|
||
|
@@ -425,7 +426,7 @@ Resources: | |
Runtime: nodejs18.x | ||
Environment: | ||
Variables: | ||
ProductCode: !Ref ProductCode | ||
ProductCode: !GetAtt GetProductCode.ProductCode | ||
AWSMarketplaceMeteringRecordsTableName: !Ref AWSMarketplaceMeteringRecordsTableName | ||
Policies: | ||
- DynamoDBWritePolicy: | ||
|
@@ -1011,7 +1012,167 @@ Resources: | |
- !Ref AWS::StackId | ||
RetentionInDays: 7 | ||
|
||
GetProductCode: | ||
Type: Custom::Lambda | ||
Properties: | ||
ServiceToken: !GetAtt GetProductCodeCustomResource.Arn | ||
ProductId: !Ref ProductId | ||
|
||
GetProductCodeCustomResource: | ||
Type: AWS::Lambda::Function | ||
Properties: | ||
Role: !GetAtt CAPILambdasExecutionRole.Arn | ||
Runtime: nodejs18.x | ||
Handler: index.handler | ||
Code: | ||
ZipFile: | | ||
const { MarketplaceCatalogClient, DescribeEntityCommand } = require("@aws-sdk/client-marketplace-catalog"); | ||
const response = require('cfn-response'); | ||
exports.handler = async (event, context) => { | ||
context.callbackWaitsForEmptyEventLoop = true; | ||
console.log("REQUEST RECEIVED:\n" + JSON.stringify(event)); | ||
const client = new MarketplaceCatalogClient({ region: 'us-east-1' }); | ||
const productId = event.ResourceProperties.ProductId; // Assuming the product ID is passed as an event parameter | ||
try { | ||
if (event.RequestType === 'Create' || event.RequestType === 'Update') { | ||
// Fetch the product details from AWS Marketplace | ||
const command = new DescribeEntityCommand({ | ||
Catalog: 'AWSMarketplace', | ||
EntityId: productId, | ||
EntityType: 'Product' | ||
}); | ||
const resp = await client.send(command); | ||
// Extract the product code from the response | ||
const productCode = resp.DetailsDocument.Description.ProductCode; | ||
const responseData = { | ||
ProductCode: productCode | ||
}; | ||
await response.send(event, context, 'SUCCESS', responseData); | ||
} else if (event.RequestType === 'Delete') { | ||
// No action needed for delete | ||
await response.send(event, context, 'SUCCESS', {}); | ||
} else { | ||
await response.send(event, context, 'FAILED', { error: 'Invalid request type' }); | ||
} | ||
} catch (error) { | ||
console.error('Error:', error); | ||
await response.send(event, context, 'FAILED', { error: 'Failed to fetch product code' }); | ||
} | ||
}; | ||
CAPILambdasExecutionRole: | ||
Type: AWS::IAM::Role | ||
Properties: | ||
AssumeRolePolicyDocument: | ||
Version: '2012-10-17' | ||
Statement: | ||
- Effect: Allow | ||
Principal: | ||
Service: | ||
- lambda.amazonaws.com | ||
Action: | ||
- 'sts:AssumeRole' | ||
ManagedPolicyArns: | ||
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole | ||
- arn:aws:iam::aws:policy/AWSMarketplaceSellerFullAccess | ||
|
||
UpdateFulfillmentURL: | ||
Type: Custom::Lambda | ||
Properties: | ||
ServiceToken: !GetAtt UpdateFulfillmentURLCustomResource.Arn | ||
ProductId: !Ref ProductId | ||
# FulfillmentUrl: 'https://cachicamo.org' | ||
FulfillmentUrl: !If [ | ||
CreateWeb, | ||
!Sub "https://${CloudfrontDistribution.DomainName}/redirectmarketplacetoken", | ||
!Sub "https://${ServerlessApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/redirectmarketplacetoken" | ||
] | ||
|
||
UpdateFulfillmentURLCustomResource: | ||
Type: AWS::Lambda::Function | ||
Properties: | ||
Role: !GetAtt CAPILambdasExecutionRole.Arn | ||
Runtime: nodejs18.x | ||
Handler: index.handler | ||
Code: | ||
ZipFile: | | ||
const { MarketplaceCatalogClient, DescribeEntityCommand, StartChangeSetCommand } = require("@aws-sdk/client-marketplace-catalog"); | ||
const response = require('cfn-response'); | ||
exports.handler = async (event, context) => { | ||
console.log("REQUEST RECEIVED:\n" + JSON.stringify(event)); | ||
const client = new MarketplaceCatalogClient({ region: 'us-east-1' }); | ||
const productId = event.ResourceProperties.ProductId; | ||
const fulfillmentUrl = event.ResourceProperties.FulfillmentUrl; | ||
try { | ||
if (event.RequestType === 'Create' || event.RequestType === 'Update') { | ||
// Fetch the fulfillment url id to be able to update the fulfillment url | ||
let command = new DescribeEntityCommand({ | ||
Catalog: 'AWSMarketplace', | ||
EntityId: productId, | ||
EntityType: 'Product' | ||
}); | ||
let resp = await client.send(command); | ||
console.debug("DescribeEntityCommand:\n" + JSON.stringify(resp)); | ||
const fulfillmentUrlID = resp.DetailsDocument.Versions[0].DeliveryOptions[0].Id | ||
console.debug("FullfilmentId:\n" + fulfillmentUrlID); | ||
const details = { | ||
DeliveryOptions : [{ | ||
Id: fulfillmentUrlID, | ||
Details: { | ||
SaaSUrlDeliveryOptionDetails: { | ||
FulfillmentUrl: fulfillmentUrl | ||
} | ||
} | ||
}] | ||
}; | ||
console.debug("details:\n" + JSON.stringify(details)); | ||
const startChangeSetInput = { | ||
Catalog: 'AWSMarketplace', | ||
ChangeSet: [ | ||
{ | ||
ChangeType: 'UpdateDeliveryOptions', | ||
Entity: { | ||
Identifier: productId, | ||
Type: '[email protected]' | ||
}, | ||
Details: JSON.stringify(details) | ||
} | ||
] | ||
}; | ||
console.debug("startChangeSetInput:\n" + JSON.stringify(startChangeSetInput)); | ||
command = new StartChangeSetCommand(startChangeSetInput); | ||
resp = await client.send(command); | ||
console.debug("StartChangeSetResp: \n" + JSON.stringify(resp)); | ||
const responseData = { | ||
StartChangeSetResp: JSON.stringify(resp) | ||
}; | ||
await response.send(event, context, 'SUCCESS', responseData); | ||
} else if (event.RequestType === 'Delete') { | ||
// No action needed for delete | ||
await response.send(event, context, 'SUCCESS', {}); | ||
} else { | ||
await response.send(event, context, 'FAILED', { error: 'Invalid request type' }); | ||
} | ||
} catch (error) { | ||
console.error('Error:', error); | ||
await response.send(event, context, 'FAILED', { error: 'Failed to update fulfillment url' }); | ||
} | ||
}; | ||
Outputs: | ||
|
||
CrossAccountRole: | ||
Description: This is the cross account role ARN. | ||
Value: | ||
|
@@ -1037,6 +1198,7 @@ Outputs: | |
!Sub "https://${CloudfrontDistribution.DomainName}/index.html", | ||
"N/A" | ||
] | ||
|
||
MarketplaceFulfillmentURL: | ||
Description: This is the Marketplace fulfillment URL. | ||
Value: | ||
|