I'm encountering a very frustrating issue with certain paths for my CF distribution.
On my origin server (non-AWS), I have set it up so all authenticated endpoints start with "/a/".
I have therefore configured CloudFront to forward all headers, thereby disabling cache. My CloudFront config for this behavior is as shown...
{
"TrustedSigners": {
"Enabled": false,
"Quantity": 0
},
"LambdaFunctionAssociations": {
"Quantity": 0
},
"TargetOriginId": "myorigin_id",
"ViewerProtocolPolicy": "redirect-to-https",
"ForwardedValues": {
"Headers": {
"Items": [
"*"
],
"Quantity": 1
},
"Cookies": {
"Forward": "all"
},
"QueryStringCacheKeys": {
"Quantity": 0
},
"QueryString": true
},
"MaxTTL": 31536000,
"PathPattern": "/a/*",
"SmoothStreaming": false,
"DefaultTTL": 86400,
"AllowedMethods": {
"Items": [
"HEAD",
"DELETE",
"POST",
"GET",
"OPTIONS",
"PUT",
"PATCH"
],
"CachedMethods": {
"Items": [
"HEAD",
"GET"
],
"Quantity": 2
},
"Quantity": 7
},
"MinTTL": 0,
"Compress": false
}
However all requests for any path starting with /a/ (i.e. /a/auth/login) fail at CloudFront. It gives me the standard error...
CloudFront wasn't able to connect to the origin.
The origin URL works perfectly. I've verified my SSL certificate. Everything appears to be correct.
What's more, if I check my server logs, I can see that for these paths, CloudFront never attempts to contact the origin server. There are no entries (successful or otherwise) for these paths for the CloudFront user-agent.
It doesn't appear to be due to any kind of origin timeout, as the error is returned immediately.
There must be an issue at the CloudFront end, but I can't figure out what I could have done wrong.
Incidentally, other behavior paths for the same origin work fine.
I figured out the problem.
IIS on my origin server had the website bound to a particular hostname. The problem is that with CloudFront fowarding "all" headers, this obviously includes the header "Host", which then meant the IIS binding was failing.
While a little counter-intuitive initially, this obviously makes perfect sense.
To fix the problem I simply needed to add an additional site binding to IIS for the CloudFront cname.
Related
We are working on an Open Source Chrome extension: Digital Assistant Client
We are trying to read and modify the "content security policy" header with chrome extension in manifest 3. We are using the declarativeNetRequest api for modification with append operation to allow our domains for fetching and posting data. In manifest v2 it is easy to read the header values by using
chrome.webRequest.onHeadersReceived.addListener( onHeadersReceived, onHeaderFilter, ['blocking', 'responseHeaders'] );
How can we acheive this in manifest 3 for reading the headers?
I have tried by defining the rules.json as given below
[ { "id": 1, "action": { "type": "modifyHeaders", "responseHeaders": [ { "header": "content-security-policy", "operation": "append", "value": "connect-src udan.nistapp.ai udantest.nistapp.ai" } ] }, "condition": { "resourceTypes": [ "csp_report", "font", "image", "main_frame", "media", "object", "other", "ping", "script", "stylesheet", "sub_frame", "webbundle", "websocket", "webtransport", "xmlhttprequest" ] } } ]
and in manifest as given below
.... permissions": [ .... "declarativeNetRequest", "declarativeNetRequestWithHostAccess", "declarativeNetRequestFeedback", ], "declarative_net_request": { "rule_resources": [{ "id": "csp_rules", "enabled": true, "path": "rules.json" }] }, ....
Problem:
When i try to append the value to the original, connect-src is getting overridden. So i want to read the header values such that i can modify the existing values. Is there a way for acheiving this?
The code you have looks good for modifying the CSP header. With that in mind, there are two common gotchas which you might be running in to:
Certain DNR rules that access or modify request/response data require host permissions. Make sure you have the host_permissions key set in the manifest with the hosts you wish to act on.
Modifications to headers made with DNR are not shown in Dev Tools (https://bugs.chromium.org/p/chromium/issues/detail?id=1247400). Doing a fetch request from the console and logging headers can help, or using the (development only) onRuleMatchedDebug API to see if your rule has been run.
I am trying to get the next page from API response, I have already tried using "AbsouteURL" which seems to "work" as it tries to call that URL (I can see that in the ADF output log).
The issue seems to be the response not having correct url in the response, it just says 0.0.0.0 instead of actual URL.
example:
"meta": {
"count": 500,
"pageCount": 10,
"totalCount": 50000,
"next": "http://0.0.0.0:3000/myData/myDataId?page=2&limit=25",
"previous": null,
"self": "http://0.0.0.0:3000/myData/myDataId?page=1&limit=25",
"first": "http://0.0.0.0:3000/myData/myDataId?page=1&limit=25",
"last": "http://0.0.0.0:3000/myData/myDataId?page=400&limit=25"
},
Is is possible to replace "0.0.0.0" with actual host name i.e. 'myWebApplication' when passing using "AbsouteURL" property?
I Have attached 2 images.
First Image is the very fist time when I load the website where the service-worker is registered. There are 2 arrow mark that shows 302 found and sets the cookies of session information.
This is the second time (refer the below image) , After I sign out and sign in again using google i am getting the below image as a response. You can see from the image there are no cookies set and it is actually from service worker.
This is my ngsw-config.json , from the docs Reference I have made it as "navigationRequestStrategy": "freshness", But still it doesnt work.
{
"$schema": "./node_modules/#angular/service-worker/config/schema.json",
"index": "/index.html",
"navigationUrls": [
"! /**/*callback*"
],
"navigationRequestStrategy": "freshness",
"assetGroups": [
{
"name": "app",
"installMode": "prefetch",
"resources": {
"files": [
"/favicon.ico",
"/manifest.webmanifest",
"/*.css",
"/*.js"
]
}
},
{
"name": "assets",
"installMode": "lazy",
"updateMode": "prefetch",
"resources": {
"files": [
"/assets/**",
"/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)"
]
}
}
]
}
So the service worker was caching the api response and returned from the cache. To bypass the service worker for certain apis. Either add salt or use ngsw-bypass in the queryparams.
Bypass Service Worker Caching in APIs
My first question would be, what's the best way to do this? It looks to me like the only way to do it without interrupting traffic would be through the AWS CLI, but if there's an easier way I'm all ears! If the CLI is the way to do it, I'm running into issues with the following command:
aws route53 change-resource-record-sets --hosted-zone-id XXXXXXXXXXXX --change-batch file://update-record.json
The update-record.json contains the following:
{
"Comment": "Swaps the Policy Record for a simple routing policy",
"Changes": [
{
"Action": "UPSERT",
"ResourceRecordSet": {
"Name": "www.example.com",
"Type": "A",
"AliasTarget": {
"HostedZoneId": "XXXXXXXXXXXX",
"DNSName": "xxxxxxxxxxxxx.cloudfront.net",
"EvaluateTargetHealth": false
}
}
}
]
}
The error I'm getting is:
An error occurred (InvalidChangeBatch) when calling the ChangeResourceRecordSets operation: [Tried to create an alias that targets xxxxxxxxxxxxx.cloudfront.net., type A in zone XXXXXXXXXXXX, but the alias target name does not lie within the target zone, Tried to create an alias that targets xxxxxxxxxxxxx.cloudfront.net., type A in zone XXXXXXXXXXXX, but that target was not found]
The Hosted Zone ID for the record in the account is accurate, as is the distribution DNS name. The record name, www.example.com, also exists in the account. The distribution has an alternate domain name (CNAME) of www.example.com.
I've also tried doing the change as a delete and create, rather than an upsert:
{
"Comment": "Swaps the Policy Record for a simple routing policy",
"Changes": [
{
"Action": "DELETE",
"ResourceRecordSet": {
"Name": "www.example.com.",
"Type": "A",
"TrafficPolicyInstanceId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
},
{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "www.example.com.",
"Type": "A",
"AliasTarget": {
"HostedZoneId": "XXXXXXXXXXXX",
"DNSName": "xxxxxxxxxxxxx.cloudfront.net",
"EvaluateTargetHealth": false
}
}
}
]
}
Doing this in two steps yields the same error message.
Each domain and subdomain in Route 53 is considered a "Hosted Zone", and as such has a "Hosted Zone ID". However, while the change-resource-record-sets documentation is extensive, it's not very clear about Alias records that point to a CloudFront distribution. I had to dig deeper, and look into the documentation around AliasTarget specifically. There, the documentation states:
Specify Z2FDTNDATAQYW2. This is always the hosted zone ID when you create an alias record that routes traffic to a CloudFront distribution.
This means that even though I was trying to create an Alias record in the hosted zone with an id of XXXXXXXXXXXX, the ID to use for any Alias record pointing to any CloudFront distribution is Z2FDTNDATAQYW2. Changing the update-record.json to the following works:
{
"Comment": "Swaps the Policy Record for a simple routing policy",
"Changes": [
{
"Action": "DELETE",
"ResourceRecordSet": {
"Name": "www.example.com.",
"Type": "A",
"TrafficPolicyInstanceId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
},
{
"Action": "CREATE",
"ResourceRecordSet": {
"Name": "www.example.com.",
"Type": "A",
"AliasTarget": {
"HostedZoneId": "Z2FDTNDATAQYW2",
"DNSName": "xxxxxxxxxxxxx.cloudfront.net",
"EvaluateTargetHealth": false
}
}
}
]
}
Doing this as a change-resource-record-set prevents interruption in traffic, as:
Change batches are considered transactional changes. Route 53 validates the changes in the request and then either makes all or none of the changes in the change batch request. This ensures that DNS routing isn't adversely affected by partial changes to the resource record sets in a hosted zone.
I have an Azure Function App with a function at the URL http://localhost:7072/api/create-room along with other functions. This particular function is a HTTPTrigger with allowed anonymous access and accepts the GET verb:
[HttpTrigger(AuthorizationLevel.Anonymous, "get")]
Along with that, I have a separate function app that hosts only a proxies.json file and serves only as a functions proxy. My proxies function is running on port 7071 locally.
My proxies file currently looks like this:
{
"$schema": "http://json.schemastore.org/proxies",
"proxies": {
"chatNegotiate": {
"matchCondition": {
"route": "/api/chat/negotiate",
"methods": [
"POST"
]
},
"backendUri": "%chat_api%/api/BeginNegotiate"
},
"chatMessages": {
"matchCondition": {
"route": "/api/chat/messages",
"methods": [
"POST"
]
},
"backendUri": "%chat_api%/api/PostMessage"
},
"createRoom": {
"matchCondition": {
"route": "/api/create-room",
"methods": [
"GET"
]
},
"backendUri": "%session_api%/api/CreateRoom"
}
}
}
When both of these function apps are deployed to Azure, everything works like a dream. I can make requests, they're forwarded on, requests come back. It's all glorious.
However, when I run these functions locally, the request is never forwarded on from the proxy, with the proxy returning a 404. I can hit the function on the other function app running locally on 7072 directly and all is well there, but not at all when I got via the proxy.
The proxy itself returns:
[30/05/2020 18:24:30] Host lock lease acquired by instance ID '0000000000000000000000002D5B6BEA'.
[30/05/2020 18:24:34] Executing HTTP request: {
[30/05/2020 18:24:34] "requestId": "9004b8e2-f208-4a98-8b48-6f85bca41281",
[30/05/2020 18:24:34] "method": "GET",
[30/05/2020 18:24:34] "uri": "/api/create-room"
[30/05/2020 18:24:34] }
[30/05/2020 18:24:34] Executed HTTP request: {
[30/05/2020 18:24:34] "requestId": "9004b8e2-f208-4a98-8b48-6f85bca41281",
[30/05/2020 18:24:34] "method": "GET",
[30/05/2020 18:24:34] "uri": "/api/create-room",
[30/05/2020 18:24:34] "identities": [],
[30/05/2020 18:24:34] "status": 404,
[30/05/2020 18:24:34] "duration": 15
[30/05/2020 18:24:34] }
From examples I've looked at such as https://chsakell.com/2019/02/03/azure-functions-proxies-in-action/, this should be working fine.
Any suggestions? Thanks in advance for any help you can provide!
I've solved this after all.
proxies.json isn't set to copy to the output directory by default.
You need to ensure that it's set to copy always.
In Visual Studio:
Right click proxies.json > click properties > Set Copy to output directory to Copy Always.
In Visual Studio Code (and other editors):
Open ProjectName.csproj and add an entry to always copy proxies.json to output directory.
<ItemGroup>
<None Update="proxies.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
This solved the problem with the 404 on my local instance of the function app proxy. In local.settings.json add this to Values:
"AZURE_FUNCTION_PROXY_DISABLE_LOCAL_CALL": true,
Credit: https://chsakell.com/2019/02/03/azure-functions-proxies-in-action/