Swagger: disabling security on one particular path - rest

I have a Swagger file that starts with the following
{
"swagger": "2.0",
"basePath": "/api",
"schemes": [
"https"
],
"securityDefinitions": {
"internalApiKey": {
"type": "apiKey",
"name": "AAuthorization",
"in": "header"
}
},
"security" : [
{ "internalApiKey": [ ] }
],
This prolog applies the security setting to every path that follows in the file. Eg.
"paths": {
"/foo": {
"get": {
Is there some way I can disable security on just ONE particular Path or Method?

Sure. Simply add the "security" property to operation with an empty array [] as a value.
So something like
{
"tags": [
"pet"
],
"summary": "Updates a pet in the store with form data",
"description": "",
"operationId": "updatePetWithForm",
"consumes": [
"application/x-www-form-urlencoded"
],
"produces": [
"application/json",
"application/xml"
],
"parameters": [
{
"name": "petId",
"in": "path",
"description": "ID of pet that needs to be updated",
"required": true,
"type": "string"
}
],
"responses": {
"200": {
"description": "Pet updated."
}
},
"security": [
]
}
would nullify the security for this operation.

You can try
security:
- NONE: []
This worked for me.
Reference

Related

Update Azure FrontdoorPremium Web Application Firewall Policy by API

I'm trying to update an Frontdoor WAF policy by API following the article in the link below but I'm running into several issues.
-Article seems to be focused on Frontdoor Classic, not premium, so the json in the article doesn't work.
-Adding an empty tags value solves the tags error.
https://learn.microsoft.com/en-us/rest/api/frontdoorservice/webapplicationfirewall/policies/create-or-update?tabs=HTTP#skuname
Can't get anywhere with MS Support, hoping anyone here has experience with this.
HTTP Respons:
{
"errors": {
"sku": [
"Could not find member 'sku' on object of type 'WebApplicationFirewallPatchRequestModel'. Path 'sku', line 1, position 7070."
],
"tags": [
"Required property 'tags' not found in JSON. Path '', line 1, position 7104."
],
"location": [
"Could not find member 'location' on object of type 'WebApplicationFirewallPatchRequestModel'. Path 'location', line 1, position 12."
],
"properties": [
"Could not find member 'properties' on object of type 'WebApplicationFirewallPatchRequestModel'. Path 'properties', line 1, position 35."
]
},
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "00-1006d4208c3a8e569d9ec0ff3513ca31-cc06e3e858308547-01"
}
Json post (shortend):
{
"location": "global",
"properties": {
"customRules": {
"rules": [
{
"name": "AllowCDN",
"enabledState": "Enabled",
"priority": 110,
"ruleType": "MatchRule",
"rateLimitDurationInMinutes": 1,
"rateLimitThreshold": 100,
"matchConditions": [
{
"matchVariable": "RequestUri",
"selector": null,
"operator": "Contains",
"negateCondition": false,
"matchValue": [
"snip.azureedge.net",
"snip.azureedge.net"
],
"transforms": [
"Lowercase"
]
}
],
"action": "Allow"
}
]
},
"managedRules": {
"managedRuleSets": [
{
"ruleSetType": "Microsoft_DefaultRuleSet",
"ruleSetVersion": "2.1",
"ruleSetAction": "Block",
"ruleGroupOverrides": [],
"exclusions": []
},
{
"ruleSetType": "Microsoft_BotManagerRuleSet",
"ruleSetVersion": "1.0",
"ruleSetAction": null,
"ruleGroupOverrides": [
{
"ruleGroupName": "GoodBots",
"rules": [
{
"ruleId": "Bot200200",
"enabledState": "Enabled",
"action": "Block",
"exclusions": []
}
],
"exclusions": []
},
{
"ruleGroupName": "UnknownBots",
"rules": [
{
"ruleId": "Bot300200",
"enabledState": "Enabled",
"action": "Block",
"exclusions": []
},
{
"ruleId": "Bot300600",
"enabledState": "Enabled",
"action": "Block",
"exclusions": []
},
{
"ruleId": "Bot300700",
"enabledState": "Enabled",
"action": "Log",
"exclusions": []
},
{
"ruleId": "Bot300400",
"enabledState": "Enabled",
"action": "Log",
"exclusions": []
},
{
"ruleId": "Bot300300",
"enabledState": "Enabled",
"action": "Block",
"exclusions": []
}
],
"exclusions": []
}
],
"exclusions": []
}
]
},
"policySettings": {
"enabledState": "Enabled",
"mode": "Prevention",
"redirectUrl": null,
"customBlockResponseStatusCode": null,
"customBlockResponseBody": null,
"requestBodyCheck": "Enabled"
}
},
"sku": {
"name": "Premium_AzureFrontDoor"
}
}
Updating an existing Frontdoor Premium WAF policy doesn't work.
I was able to execute the Update REST API above though for my Azure Front Door Standard. The process I followed was to make the GET REST API Call first and then copy the response body and then make the updates required in the JSON and use this JSON as a request Body in the Update REST API. The reference JSON below worked for me.
{
"id": "/subscriptions/xxxxx/resourcegroups/xxxxx/providers/Microsoft.Network/frontdoorwebapplicationfirewallpolicies/xxxxx",
"type": "Microsoft.Network/frontdoorwebapplicationfirewallpolicies",
"name": "xxxxx",
"location": "Global",
"tags": {
"Reason": "Repro",
"CreatedDate": "12/29/2022 2:40:29 AM",
"CreatedBy": "xxxxx",
"OwningTeam": "xxxxx"
},
"sku": {
"name": "Standard_AzureFrontDoor"
},
"properties": {
"policySettings": {
"enabledState": "Enabled",
"mode": "Detection",
"redirectUrl": null,
"customBlockResponseStatusCode": 403,
"customBlockResponseBody": null,
"requestBodyCheck": "Disabled"
},
"customRules": {
"rules": [
{
"name": "testcustomrule",
"enabledState": "Enabled",
"priority": 100,
"ruleType": "MatchRule",
"rateLimitDurationInMinutes": 1,
"rateLimitThreshold": 100,
"matchConditions": [
{
"matchVariable": "SocketAddr",
"selector": null,
"operator": "GeoMatch",
"negateCondition": false,
"matchValue": [
"UY"
],
"transforms": []
}
],
"action": "Block"
},
{
"name": "testcustomrule2",
"enabledState": "Enabled",
"priority": 101,
"ruleType": "MatchRule",
"rateLimitDurationInMinutes": 1,
"rateLimitThreshold": 100,
"matchConditions": [
{
"matchVariable": "SocketAddr",
"selector": null,
"operator": "GeoMatch",
"negateCondition": false,
"matchValue": [
"AU"
],
"transforms": []
}
],
"action": "Block"
}
]
},
"managedRules": {
"managedRuleSets": []
},
"frontendEndpointLinks": [],
"securityPolicyLinks": [
{
"id": "/subscriptions/xxxxx/resourcegroups/xxxxx/providers/Microsoft.Cdn/profiles/xxxxx/securitypolicies/xxxxx"
}
],
"routingRuleLinks": [],
"resourceState": "Enabled",
"provisioningState": "Succeeded"
}
}

Powershell Invoke-RestMethod in LogicApps

For this line of code in Powershell I used an HTTP connector in Logic Apps using Joey Cai's advice.
$body_login = #{"method"="login";"username"="qq";"password"="qqq"} | ConvertTo-Json
Now, I have this line of code in Powershell. How do I do the equivalent in LogicApps?
$Conn = Invoke-RestMethod -Method Post $uri_login -Headers $header -Body $body_login
Do I use the same HTTP connector or do I need something else? It's the Invoke-RestMethod syntax that I'm unsure of in Logic Apps.
I will need the output in JSON format, so I can parse it.
Thanks for the first answer. I need to know what to put in the uri, header and body. Here is the rest of the code which I should have provided before.
$baseuri = "https://test"
$header = #{
"Accept" = "text/json"
"Content-Type" = "text/json"
}
$G_header = #{"Accept" = "text/json"}
Write-Output "Login ..."
$uri_login = $baseuri + "SPDEDJSONSERVICE.LOGIN"
$body_login = #{"method"="login";"username"="qqq";"password"="qqq"} | ConvertTo-Json
$Conn = Invoke-RestMethod -Method Post $uri_login -Headers $header -Body $body_login
$SessionID = $conn.sessionID</code>
How do I do the equivalent in LogicApps?
As I have provided before, use HTTP connector.
I will need the output in JSON format, so I can parse it.
You could use Compose to work with data in JSON format.
1.Add Headers/Body which you want into Compose.
2.Add Outputs into Parse JSON. Copy the HTTP response Headers/Body info, and click use sample payload to generate schema, then parse Headers in it.
3.Use Initialize variable to get info what you want such as Date.
The result:
With Azure Logic Apps and the built-in HTTP action, you can create automated tasks and workflows that regularly send requests to any HTTP or HTTPS endpoint.
Sign in to the Azure portal. Open your logic app in Logic App Designer.
Under the step where you want to add the HTTP action, select New step.
To add an action between steps, move your pointer over the arrow between steps. Select the plus sign (+) that appears, and then select Add an action.
Under Choose an action, in the search box, enter "http" as your filter. From the Actions list, select the HTTP action.
Select HTTP action
For your scenarion you can use Basic Authentication.
This seems to work, but I could not have done it without Joey
<code>
{
"definition": {
"$schema":
"https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-
01/workflowdefinition.json#",
"actions": {
"HTTP_2": {
"inputs": {
"body": {
"FORMAT": "payload",
"FROM": 0,
"GRIDID": "PROP",
"GRIDVIEW": "1",
"HITS": 100,
"ORDERBY": "PR_DATESOLD",
"PROFILE": [
{
"PR_NAME": "G*",
"PR_USER1": "GENERATED"
}
],
"sessionID": "#body('Parse_JSON3')['sessionID']"
},
"headers": {
"Accept": "text/json",
"Content-Type": "text/json"
},
"method": "POST",
"uri": "#variables('uri_DefGrid')"
},
"runAfter": {
"Parse_JSON3": [
"Succeeded"
]
},
"type": "Http"
},
"Initialize_Header": {
"inputs": {
"variables": [
{
"name": "Header",
"type": "string",
"value": "{\"Accept\":\"text/json\",\"Content-
Type\":\"text/json\"}"
}
]
},
"runAfter": {
"Initialize_body_login": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"Initialize_body_DefGrid": {
"inputs": {
"variables": [
{
"name": "body_DefGrid",
"type": "string",
"value": "json(#{body('HTTP_2')})"
}
]
},
"runAfter": {
"HTTP_2": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"Initialize_body_login": {
"inputs": {
"variables": [
{
"name": "body_login",
"type": "string",
"value": "json(#{triggerBody()})"
}
]
},
"runAfter": {},
"type": "InitializeVariable"
},
"Initialize_uri_DefGrid": {
"inputs": {
"variables": [
{
"name": "uri_DefGrid",
"type": "string",
"value": "https://test/SPDEDMHAPI.GRIDGET"
}
]
},
"runAfter": {
"Initialize_uri_login": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"Initialize_uri_login": {
"inputs": {
"variables": [
{
"name": "uri_login",
"type": "string",
"value": "https://test/SPDEDJSONSERVICE.LOGIN"
}
]
},
"runAfter": {
"Initialize_Header": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"Initialize_uri_logout": {
"inputs": {
"variables": [
{
"name": "uri_logout",
"type": "string",
"value": "https://test/SPDEDJSONSERVICE.LOGOUT"
}
]
},
"runAfter": {
"Initialize_body_DefGrid": [
"Succeeded"
]
},
"type": "InitializeVariable"
},
"Logout": {
"inputs": {
"body": {
"method": "logout",
"sessionID": "#body('Parse_JSON3')['sessionID']"
},
"headers": {
"Accept": "text/json",
"Content-Type": "text/json"
},
"method": "POST",
"uri": "#variables('uri_logout')"
},
"runAfter": {
"Initialize_uri_logout": [
"Succeeded"
]
},
"type": "Http"
},
"Parse_JSON3": {
"inputs": {
"content": "#triggerBody()",
"schema": {
"properties": {
"RLS_WHERE": {
"$id": "#/properties/RLS_WHERE",
"type": "string"
},
"contact": {
"type": "string"
},
"error": {
"type": "string"
},
"errorId": {
"type": "string"
},
"fullName": {
"type": "string"
},
"labellanguage": {
"type": "string"
},
"language": {
"type": "string"
},
"message": {
"type": "string"
},
"params": {
"properties": {
"WOPARTSOPT": {
"type": "string"
}
},
"required": [
"WOPARTSOPT"
],
"title": "The Params Schema",
"type": "object"
},
"role": {
"type": "string"
},
"sessionID": {
"type": "string"
},
"success": {
"type": "string"
},
"userEmail": {
"$id": "#/properties/userEmail",
"type": "string"
}
},
"required": [
"success",
"message",
"sessionID",
"language",
"labellanguage",
"error",
"errorId",
"fullName",
"role",
"contact",
"RLS_WHERE",
"userEmail",
"params"
],
"title": "The Root Schema",
"type": "object"
}
},
"runAfter": {
"Initialize_uri_DefGrid": [
"Succeeded"
]
},
"type": "ParseJson"
}
},
"contentVersion": "1.0.0.0",
"outputs": {},
"parameters": {},
"triggers": {
"HTTP": {
"inputs": {
"body": {
"method": "login",
"password": "qqq",
"username": "qqq"
},
"headers": {
"Accept": "text/json",
"Content-Type": "text/json"
},
"method": "POST",
"uri": "https://test/SPDEDJSONSERVICE.LOGIN"
},
"recurrence": {
"frequency": "Minute",
"interval": 4
},
"type": "Http"
}
}
},
"parameters": {}
}
</code>

Google Assistant : account linking and Actions sdk : fail to see sign in message

I want to enable account linking on an Google Assistant application using Actions Sdk.
I have already provided the information in the Account Linking section of the AoG Console :
The grant Type is Authorization code.
I use Auth0 as Oauth Server and i checked that the endpoints are functional.
When the application is invoked using the simulator, the server application send the following json response :
{
"expectUserResponse": true,
"finalResponse": null,
"expectedInputs": [{
"possibleIntents": [{
"intent": "actions.intent.SIGN_IN",
"inputValueData": null
}],
"inputPrompt": {
"richInitialPrompt": {
"items": [{
"simpleResponse": {
"textToSpeech": "Merci de vous authentifier",
"ssml": null,
"displayText": "Merci de vous authentifier"
}
}]
}
}
}],
"conversationToken": null,
"isInSandbox": false
}
I expected then to see the message like : it looks like your account … is not linked
Instead of that, the assistant immediately sends the following request to the server :
{
"user": {
"userId": "ABwppHGK6fClByrbLlS8WDM4xfY0qEck5i_kOGMhlJtuj64SjC-8qDqlH3xZ3BN7f9Yz1JDza-sc",
"locale": "fr-CA",
"lastSeen": "2018-04-23T14:12:02Z"
},
"conversation": {"conversationId": "1524493058716", "type": "NEW"},
"inputs": [{
"intent": "actions.intent.SIGN_IN",
"rawInputs": [{"inputType": "KEYBOARD"}],
"arguments": [{
"name": "SIGN_IN",
"extension": {
"#type": "type.googleapis.com/google.actions.v2.SignInValue",
"status": "ERROR"
}
}]
}],
"surface": {
"capabilities": [
{"name": "actions.capability.WEB_BROWSER"},
{"name": "actions.capability.MEDIA_RESPONSE_AUDIO"},
{"name": "actions.capability.SCREEN_OUTPUT"},
{"name": "actions.capability.AUDIO_OUTPUT"}
]
},
"isInSandbox": true,
"availableSurfaces": [
{
"capabilities": [
{"name": "actions.capability.SCREEN_OUTPUT"},
{"name": "actions.capability.AUDIO_OUTPUT"}
]
}
]
}
Did someone have the same problem ? Thanks
I have a working example, but it might be different of what you are doing because I ask the sign-in with dialogflow Integrations' tab for Google Assistant, and not explicitely with the SDK. The code is for the V2 of Dialogflow, I also have one for the V1 but it is now legacy.
This is my BONJOUR intent that is triggered when my app is launched:
const rp = require('request-promise');
app.intent('BONJOUR', (conv) => {
console.log("Debug: SAY_HELLO");
const accessToken = conv.user.access.token;
console.log("Access Token = "+accessToken);
//========Auth with OAuth website========
if (!accessToken) {
conv.ask(new SignIn());
} else {
let options = {
method: 'GET',
url: '[...]',//Oauth URL
headers:{
authorization: 'Bearer ' + accessToken,
}
};
// I use the RP lib as we need Promises for the V2 of Dialogflow.
return rp(options).then((body) => {
let data = JSON.parse(body);
console.log("auth data ="+JSON.stringify(data));
//You can access the auth data easily here
// For example if you want the name, it's in data.given_name, etc...
//Use conv.ask() to say something here
}).catch((error) => {
console.log("Error in auth request"+error);
})
}
});
Update:
This is my JSON mais the SignIn() is called, as I just tested it, it doesn't work (I created an intent that receives the actions_intent_SIGN_IN event from an example. And it never asks for sign In , I'm always in the else.)
Response {
"payload": {
"google": {
"expectUserResponse": true,
"richResponse": {
"items": [
{
"simpleResponse": {
"textToSpeech": "PLACEHOLDER"
}
}
]
},
"userStorage": "{\"data\":{}}",
"systemIntent": {
"intent": "actions.intent.SIGN_IN",
"data": {
"#type": "type.googleapis.com/google.actions.v2.SignInValueSpec"
}
}
}
},
"outputContexts": [
{
"name": [...],
"lifespanCount": 99,
"parameters": {
"data": "{}"
}
}
]
}
Then the request after that is:
Request {
"responseId": "5a711f0e-be66-4311-b776-2085e81e9bde",
"queryResult": {
"queryText": "actions_intent_SIGN_IN",
"parameters": {},
"allRequiredParamsPresent": true,
"fulfillmentMessages": [
{
"text": {
"text": [
""
]
}
}
],
"outputContexts": [
{
"name": "..."
},
{
"name": ".../actions_intent_sign_in",
"parameters": {
"SIGN_IN": {
"#type": "type.googleapis.com/google.actions.v2.SignInValue",
"status": "ERROR"
}
}
},
{
"name": "...",
"lifespanCount": 98,
"parameters": {
"data": "{}"
}
},
{
"name": "..."
},
{
"name": "..."
},
{
"name": "..."
},
{
"name": "..."
}
],
"intent": {
"name": "...",
"displayName": "Get Signin"
},
"intentDetectionConfidence": 1,
"diagnosticInfo": {},
"languageCode": "fr-fr"
},
"originalDetectIntentRequest": {
"source": "google",
"version": "2",
"payload": {
"isInSandbox": true,
"surface": {
"capabilities": [
{
"name": "actions.capability.WEB_BROWSER"
},
{
"name": "actions.capability.MEDIA_RESPONSE_AUDIO"
},
{
"name": "actions.capability.SCREEN_OUTPUT"
},
{
"name": "actions.capability.AUDIO_OUTPUT"
}
]
},
"inputs": [
{
"rawInputs": [
{
"inputType": "KEYBOARD"
}
],
"arguments": [
{
"extension": {
"#type": "type.googleapis.com/google.actions.v2.SignInValue",
"status": "ERROR"
},
"name": "SIGN_IN"
}
],
"intent": "actions.intent.SIGN_IN"
}
],
"user": {
"userStorage": "{\"data\":{}}",
"lastSeen": "2018-04-24T12:21:19Z",
"locale": "fr-FR",
"userId": "ABwppHHXrOc7N24RC5YS1dMvt7C-MbpzTb5TtzmufeIpGTCINVlReIMb8RKo4SGQMgBY7BUvO1qhn0B-"
},
"conversation": {
"conversationId": "1524572717282",
"type": "ACTIVE",
"conversationToken": "[\"_actions_on_google\"]"
},
"availableSurfaces": [
{
"capabilities": [
{
"name": "actions.capability.SCREEN_OUTPUT"
},
{
"name": "actions.capability.AUDIO_OUTPUT"
}
]
}
]
}
},
"session": "..."
}
I hope it can help you somehow.

Get Google Assistant Action to respond to "Quit" or "Cancel"

I've tried to follow the documentation about App Exit handling, but it doesn't seem to be working correctly. (See the screen shot of my Intent below).
When I do it this way, it seems to resort to my Default Fallback Intent, although it does indicate that the resolvedQuery is actions_intent_CANCEL, which should be correct. (See the JSON body below.)
Am I doing something wrong, or is the documentation wrong?
Intent trying to handle it:
JSON Body:
{
"originalRequest": {
"source": "google",
"version": "2",
"data": {
"isInSandbox": true,
"surface": {
"capabilities": [
{
"name": "actions.capability.AUDIO_OUTPUT"
},
{
"name": "actions.capability.SCREEN_OUTPUT"
}
]
},
"inputs": [
{
"rawInputs": [
{}
],
"intent": "actions.intent.CANCEL"
}
],
"user": {
"locale": "en-US",
"userId": "AETml1QP6omTPEXBfrOBdvNlwHxY"
},
"conversation": {
"conversationId": "1509314271837",
"type": "ACTIVE",
"conversationToken": "[]"
},
"availableSurfaces": [
{
"capabilities": [
{
"name": "actions.capability.AUDIO_OUTPUT"
},
{
"name": "actions.capability.SCREEN_OUTPUT"
}
]
}
]
}
},
"id": "bbd363aa-f555-4543-a748-294751194fa9",
"timestamp": "2017-10-29T21:58:00.691Z",
"lang": "en-us",
"result": {
"source": "agent",
"resolvedQuery": "actions_intent_CANCEL",
"speech": "",
"action": "input.unknown",
"actionIncomplete": false,
"parameters": {},
"contexts": [
{
"name": "actions_intent_cancel",
"parameters": {},
"lifespan": 0
},
{
"name": "actions_capability_screen_output",
"parameters": {},
"lifespan": 0
},
{
"name": "actions_capability_audio_output",
"parameters": {},
"lifespan": 0
}
],
"metadata": {
"intentId": "25f6e14b-a92c-479b-8943-76c4b6914579",
"webhookUsed": "true",
"webhookForSlotFillingUsed": "false",
"nluResponseTime": 2,
"intentName": "Default Fallback Intent"
},
"fulfillment": {
"speech": "I'm sorry. I didn't quite grasp what you just said.",
"messages": [
{
"type": 0,
"id": "535c3b80-f13d-4b61-8c1d-bb58fa3f5e44",
"speech": "I'm a bit confused by that last part."
}
]
},
"score": 1
},
"status": {
"code": 200,
"errorType": "success"
},
"sessionId": "1509314271837"
}
In addition to the steps in the documentation, I found that I had to tell the simulator to update to the most recent version!
Here is my video outlining the steps I took.
https://www.youtube.com/watch?v=ZvZDokjhUIY
Although this isn't what the documentation suggests, I've found a workaround that seems to be correct.
Since there doesn't seem to be any spoken input registered, it looks like it would make sense for a Fallback Intent. Since Fallback Intents other than the default one require a Context, and not just an Event, and it looks like the actions_intent_cancel context is created, it seems reasonable to use it.
A Fallback Intent for this might look something like this:

Using CloudFormation to configure CloudFront with an S3 origin

I am trying to use CloudFormation for the first time to configure a CloudFront distribution that uses an S3 bucket as its origin.
However I am receiving the error One or more of your origins do not exist when the template is run. I have assumed it is down to the origin DomainName being configured incorrectly, however have not been able to find a configuration that works.
I currently have the following template:
{
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"AssetBucket": {
"Type": "AWS::S3::Bucket",
"Properties": {
"BucketName": "cdn-assets",
"AccessControl": "PublicRead",
"CorsConfiguration": {
"CorsRules": [
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"GET"
],
"AllowedOrigins": [
"*"
],
"Id": "OpenCors",
"MaxAge": "3600"
}
]
}
}
},
"AssetCDN": {
"Type": "AWS::CloudFront::Distribution",
"Properties": {
"DistributionConfig": {
"Origins": [
{
"DomainName": {
"Fn::GetAtt": [
"AssetBucket",
"DomainName"
]
},
"Id": "AssetBucketOrigin",
"S3OriginConfig": {}
}
],
"Enabled": "true",
"DefaultCacheBehavior": {
"Compress": true,
"AllowedMethods": [
"GET",
"HEAD",
"OPTIONS"
],
"TargetOriginId": "origin-access-identity/cloudfront/AssetCDN",
"ForwardedValues": {
"QueryString": "false",
"Cookies": {
"Forward": "none"
}
},
"ViewerProtocolPolicy": "allow-all"
},
"PriceClass": "PriceClass_All",
"ViewerCertificate": {
"CloudFrontDefaultCertificate": "true"
}
}
},
"DependsOn": [
"AssetBucket"
]
}
}
}
I have not been able to find much advice on this, so hoping someone can point me in the right direction.
Your Cache Behavior's TargetOriginId property must match the value specified in the S3 Origin's Id property.
In your above example, TargetOriginId is origin-access-identity/cloudfront/AssetCDN while Id is AssetBucketOrigin, which is causing the error.
The real issue here is that Cloudfront have a dependency - S3 bucket. And so you should put this reference inside cloudfront object to let CFN know that first of all it should create S3 bucket. To do this you have to change your Origins.Id and DefaultCacheBehavior.TargetOriginId properties to Ref to your bucket config:
{
"AWSTemplateFormatVersion": "2010-09-09",
"Resources": {
"AssetBucket": {
"Type": "AWS::S3::Bucket",
"Properties": {
"BucketName": "cdn-assets",
"AccessControl": "PublicRead",
"CorsConfiguration": {
"CorsRules": [
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"GET"
],
"AllowedOrigins": [
"*"
],
"Id": "OpenCors",
"MaxAge": "3600"
}
]
}
}
},
"AssetCDN": {
"Type": "AWS::CloudFront::Distribution",
"Properties": {
"DistributionConfig": {
"Origins": [
{
"DomainName": {
"Fn::GetAtt": [
"AssetBucket",
"DomainName"
]
},
"Id": { "Ref": "AssetBucket" }, /// HERE!!!!
"S3OriginConfig": {}
}
],
"Enabled": "true",
"DefaultCacheBehavior": {
"Compress": true,
"AllowedMethods": [
"GET",
"HEAD",
"OPTIONS"
],
"TargetOriginId": { "Ref": "AssetBucket" }, /// HERE!!!!
"ForwardedValues": {
"QueryString": "false",
"Cookies": {
"Forward": "none"
}
},
"ViewerProtocolPolicy": "allow-all"
},
"PriceClass": "PriceClass_All",
"ViewerCertificate": {
"CloudFrontDefaultCertificate": "true"
}
}
},
"DependsOn": [
"AssetBucket"
]
}
}
}