thin-edge.io
thin-edge.io copied to clipboard
C8y tenant validation broken while using custom domains
Describe the bug
When the c8y-mapper receives a configuration update request with the URL of the artefact to be downloaded, it checks if the incoming URL belongs to the same tenant domain that the mapper is configured with, using the http_proxy::C8yEndPoint::maybe_tenant_url
function. But, this function relies on common domain suffixes for this check so that aliases like xyz.c8y.io
and t123.c8y.io
pass the check as they both share the common c8y.io
domain suffix.
But, while using custom domains feature of C8y, the custom domain URL and the URL received in the incoming request may not have a common suffix. For example, a customer might be using a custom domain your.custom.domain
to connect to C8y, but the URLs in incoming requests would contain the real tenant URL behind the custom domain, in the form t123456.cumulocity.com
. Since they don't share a common suffix, the mapper will wrongly flag that URL as an external URL and try to download it without any authentication, resulting in a failure.
The current check is broken even in cases where abc.com
and xyz.com
will be qualified as part of the same domain, just because they have the matching .com
suffix, which is clearly wrong.
To Reproduce
To reproduce the first case, you need to have a C8y instance with a custom domain name that does not have a common suffix with the real tenant URL (If using the custom domain feature is not feasible, you can also simulate this behaviour by creating a local DNS entry on the tedge device with the custom domain URL pointing to the real tenant URL). With such a setup, configuration updates won't work as the mapper will fail to download the updated config artefacts.
For the second case, the following unit test would suffice, which fails with the existing code:
#[test]
fn url_is_my_tenant_not_too_broad() {
let c8y = C8yEndPoint::new("abc.com", "test_device");
assert!(c8y.maybe_tenant_url("http://xyz.com").is_none());
}
Expected behavior
Instead of doing a simple suffix match of the URLs, thin-edge should retrieve the real tenant URL behind the provided custom domain URL and use that for any further matching. The real URL can be retrieved by querying the loginOptions
endpoint (e.g: https://your.custom.domain/tenant/loginOptions
) and extracting the value of the self
key from the JSON response. A sample response would be as follows:
{
"self": "https://t123456.cumulocity.com/tenant/loginOptions/",
"loginOptions": []
}
This resolution needs to be done only once, and the result can be cached so that it is not repeated on every incoming URL validation. Ideally, this value can be retrieved while doing tedge connect c8y
and the result be cached on disk so that the mapper can access it for eternity.
We can also optionally provide a configuration setting that the user can set to define all the aliases of his tenant, so that incoming URL validation is done against them all.
Additional Context
Once this issue is resolved, re-enable the http_proxy::tests::url_is_my_tenant_check_not_too_broad
test.