-
Notifications
You must be signed in to change notification settings - Fork 36
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Validate domain of Srv endpoints #489
Validate domain of Srv endpoints #489
Conversation
1ddedad
to
c35748b
Compare
c35748b
to
ec6a431
Compare
|
||
public static async Task<string> GetValidDomain(Uri originEndpoint, string srvHostName) | ||
{ | ||
if (string.IsNullOrEmpty(srvHostName)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That seems like argument exception. Why would empty or null be passed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.
is a valid target host in SRV DNS, if we can't trust the SRV DNS lookup result, we probably can get such a host name, and after trimming the tailing '.', we get an empty host name.
src/Microsoft.Extensions.Configuration.AzureAppConfiguration/DomainVerifier.cs
Show resolved
Hide resolved
src/Microsoft.Extensions.Configuration.AzureAppConfiguration/DomainVerifier.cs
Show resolved
Hide resolved
} | ||
} | ||
|
||
// Get the Common Name (CN) from the Subject Name if Subject Alternative Name is not available |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of our certs use SAN right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They should.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
then we can remove this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a way recommended by a RFC doc, but given we ensure we use SAN, we can remove this.
src/Microsoft.Extensions.Configuration.AzureAppConfiguration/DomainVerifier.cs
Outdated
Show resolved
Hide resolved
src/Microsoft.Extensions.Configuration.AzureAppConfiguration/DomainVerifier.cs
Outdated
Show resolved
Hide resolved
private const string CommonName = "CN="; | ||
private const string MultiDomainWildcard = "*."; | ||
|
||
public static async Task<string> GetValidDomain(Uri originEndpoint, string srvHostName) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be able to return multiple valid domains if there are multiple matches, for future proofing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make sense, updated
|
||
private async Task<bool> IsValidEndpoint(string hostName) | ||
{ | ||
if (string.IsNullOrWhiteSpace(hostName)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why would we have null or whitespace here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Explained in another comment
return false; | ||
} | ||
|
||
if (string.IsNullOrEmpty(_validDomain)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was expecting valid domains to be an enumerable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated
src/Microsoft.Extensions.Configuration.AzureAppConfiguration/DomainVerifier.cs
Outdated
Show resolved
Hide resolved
// Initiate the connection, so it will download the server certificate | ||
await sslStream.AuthenticateAsClientAsync(endpoint).ConfigureAwait(false); | ||
|
||
var serverCertificate = sslStream.RemoteCertificate; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will throw for untrusted cert right? Trying to figure out the code path of untrusted endpoint and untrusted endpoint with untrusted cert.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think not, this doesn't verify whether it's a trusted cert, it won't verify the certificate chain, the expiration time, the issuer or the root cert is trusted or not, etc. And seems doing such verification is overkill here because we just aim to verify the domain of srv endpoint, not really need to check the legality of that certificate. We just leverage the cert to ensure the acquired SRV endpoints are in the same domain as the original endpoint would be fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No way ! We shouldn't be using any info from a certificate we haven't validated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In that case, someone controlling a bad endpoint could mint a certificate with whatever they want.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then we should validate the certificate, what kind of validation should be done against the certificate? This is what we can get which can help to do the validation
https://learn.microsoft.com/en-us/dotnet/api/system.net.security.sslpolicyerrors?view=net-7.0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we make an anonymous http call to the endpoint? I think http call has built in validation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Confirmed, it does throw for untrusted cert as expected.
src/Microsoft.Extensions.Configuration.AzureAppConfiguration/DomainVerifier.cs
Outdated
Show resolved
Hide resolved
62d66e4
to
b4c41e0
Compare
@@ -36,7 +38,8 @@ internal class ConfigurationClientManager : IConfigurationClientManager | |||
private readonly bool _replicaDiscoveryEnabled; | |||
|
|||
private IList<ConfigurationClientWrapper> _dynamicClients; | |||
private Lazy<SrvLookupClient> _srvLookupClient; | |||
private SrvLookupClient _srvLookupClient; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
private SrvLookupClient _srvLookupClient; | |
private readonly SrvLookupClient _srvLookupClient; |
return validDomains; | ||
} | ||
|
||
cert = new X509Certificate2(serverCertificate); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's disposable.
src/Microsoft.Extensions.Configuration.AzureAppConfiguration/DomainVerifier.cs
Show resolved
Hide resolved
9d7f7c2
to
523733e
Compare
return validDomains; | ||
} | ||
|
||
using (cert) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a bit unfortunate the using
is separated from the insantiation of the disposable object.
Could you use a private method to avoid separating the two?
using (var cert = new X509Certificate2(serverCertificate))
{
return GetValidDomains(cert);
}
* Validate domain of Srv endpoints * Resolve comments * Resolve comments * Create object in using
* Validate domain of Srv endpoints * Resolve comments * Resolve comments * Create object in using
* Automatic http failover base on Srv Dns * update failover condition * Logging messages for auto failover * Not use generic method * Remove useless constructor * Failover to TCP when response is truncated * Error handling of TCP failover * Resolve comments and add thrid party notice * Fix the tests * Fix the tess * Fix the test * Update to use DnsClient.NET * Remove unecessary code * Resolve conflict * Stop once it has been auto failovered * Update GetAvaliableClient method * Resolve comments * Resolve comments * Internalize getting dynamic client in ConfigurationClientManager * Fix format * Fix format * Resolve comments * Resolve comments * Resolve comments * Resolve comments * Resolve comments * Resolve comments * Resolve comments * Not await RefreshFallbackClients when startup * Revert non-await RefreshFallbackClients * Validate domain of Srv endpoints (#489) * Validate domain of Srv endpoints * Resolve comments * Resolve comments * Create object in using * Add the origin host to the srv lookup result * Validate endpoint by domain name (#499) * Validate endpoint by domain name * Resolve comments * Remove *-test * Fix formatResolve conflict * Use await using for IAsyncDisposible * Replace IAsyncEumerable with ValueTask<IEnumerable> * Resolve comments * Remove cancallation token * Resolve comments
* Automatic http failover base on Srv Dns * update failover condition * Logging messages for auto failover * Not use generic method * Remove useless constructor * Failover to TCP when response is truncated * Error handling of TCP failover * Resolve comments and add thrid party notice * Fix the tests * Fix the tess * Fix the test * Update to use DnsClient.NET * Remove unecessary code * Resolve conflict * Stop once it has been auto failovered * Update GetAvaliableClient method * Resolve comments * Resolve comments * Internalize getting dynamic client in ConfigurationClientManager * Fix format * Fix format * Resolve comments * Resolve comments * Resolve comments * Resolve comments * Resolve comments * Resolve comments * Resolve comments * Not await RefreshFallbackClients when startup * Revert non-await RefreshFallbackClients * Validate domain of Srv endpoints (#489) * Validate domain of Srv endpoints * Resolve comments * Resolve comments * Create object in using * Add the origin host to the srv lookup result * Validate endpoint by domain name (#499) * Validate endpoint by domain name * Resolve comments * Remove *-test * Fix formatResolve conflict * Use await using for IAsyncDisposible * Replace IAsyncEumerable with ValueTask<IEnumerable> * Resolve comments * Remove cancallation token * Resolve comments
* Automatic http failover base on Srv Dns (#442) * Automatic http failover base on Srv Dns * update failover condition * Logging messages for auto failover * Not use generic method * Remove useless constructor * Failover to TCP when response is truncated * Error handling of TCP failover * Resolve comments and add thrid party notice * Fix the tests * Fix the tess * Fix the test * Update to use DnsClient.NET * Remove unecessary code * Resolve conflict * Stop once it has been auto failovered * Update GetAvaliableClient method * Resolve comments * Resolve comments * Internalize getting dynamic client in ConfigurationClientManager * Fix format * Fix format * Resolve comments * Resolve comments * Resolve comments * Resolve comments * Resolve comments * Resolve comments * Resolve comments * Not await RefreshFallbackClients when startup * Revert non-await RefreshFallbackClients * Validate domain of Srv endpoints (#489) * Validate domain of Srv endpoints * Resolve comments * Resolve comments * Create object in using * Add the origin host to the srv lookup result * Validate endpoint by domain name (#499) * Validate endpoint by domain name * Resolve comments * Remove *-test * Fix formatResolve conflict * Use await using for IAsyncDisposible * Replace IAsyncEumerable with ValueTask<IEnumerable> * Resolve comments * Remove cancallation token * Resolve comments * Refactor and move backoff logic to AzureAppConfigurationProvider (#508) * move backoff logic to provider, can't access backoffendtime from manager for dynamic clients * add condition before calling getclients in refreshasync, add refreshclients method * fix logic to check if backoff ended for client * fix indents * check client backoff before refresh, fix tests in progress * remove tolist * comment changes, fix refresh tests * reduce minimum backoff when testing * fix tests, fix typo with failover logic * update comments in tests * resolve PR comments * resolve small comments * fix tests backoff duration * fix tests backoff duration * fix error from merging main branch in * add back fix for attempts backoff calculation --------- Co-authored-by: Richard chen <99175581+RichardChen820@users.noreply.github.com>
Validate domain of Srv endpoints @jimmyca15