-
Notifications
You must be signed in to change notification settings - Fork 9.8k
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
etcdmain, pkg: Support peer and client TLS auth based on SAN fields. #10614
etcdmain, pkg: Support peer and client TLS auth based on SAN fields. #10614
Conversation
292aa9e
to
62a316e
Compare
cc @wenjiaswe |
@@ -270,6 +270,11 @@ The security flags help to [build a secure etcd cluster][security]. | |||
+ default: "" | |||
+ env variable: ETCD_CLIENT_CRL_FILE | |||
|
|||
### --client-cert-allowed-name |
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.
allowed-san?
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.
When checking whether a given hostname is valid for a TLS certificate, it's typical to not mandate which particular field the name comes from. The implementation of (*x509.Certificate).VerifyHostname()
uses SAN if any are set, and falls back to CN.
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.
OK. The implementation checks CN first, then checks parsed SAN, right? Can we make this clear?
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 is hard to infer this behavior from the flag and current help message.
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 believe the verification logic is something like this:
func checkName(name string) bool {
if len(SAN) == 0 {
return validHostname(CN) && matches(CN, name)
}
for _, sanEntry := range SAN {
if matches(sanEntry, name) {
return true
}
}
return false
}
The full behavior is described by RFC 6125 section 6.4, which is too long to describe here.
sorry for the long delay. this pr looks good to me. but can we change allowed-name to allowed-san or something more specific? |
@xiang90 If I understood right, x509's logic is, if a SSL Certificate has a Subject Alternative Name (SAN) field, then SSL clients are supposed to ignore the Common Name value and seek a match in the SAN list. As in RFC 6125, Appendix B.2.:
I think in this PR, only one of If that's the case, maybe we could use --peer-cert-allowed-hostname instead of --peer-cert-allowed-name to match (*x509.Certificate).VerifyHostname() function name? |
@wenjiaswe Yep, that all matches my understanding. I'd be fine with renaming the new flags to |
Stray debugging prints removed, sorry about that. |
e543a09
to
95db995
Compare
The test failure in |
=== RUN TestBalancerUnderBlackholeKeepAliveWatch This is a known flaky test, do not worry about it. |
The semaphoreci tests timed out after 20m. Can you rebase to master? It was adjusted to 30m. |
Etcd currently supports validating peers based on their TLS certificate's CN field. The current best practice for creation and validation of TLS certs is to use the Subject Alternative Name (SAN) fields instead, so that a certificate might be issued with a unique CN and its logical identities in the SANs. This commit extends the peer validation logic to use Go's `(*"crypto/x509".Certificate).ValidateHostname` function for name validation, which allows SANs to be used for peer access control. In addition, it allows name validation to be enabled on clients as well. This is used when running Etcd behind an authenticating proxy, or as an internal component in a larger system (like a Kubernetes master).
95db995
to
fc8c021
Compare
LGTM if all failures are known. |
702e16c
to
c50dc81
Compare
The semaphore test is consistently failing with a timeout in the new test. Please don't merge until I can debug it. |
683068f
to
59072f2
Compare
59072f2
to
95f3138
Compare
Codecov Report
@@ Coverage Diff @@
## master #10614 +/- ##
==========================================
- Coverage 63.35% 62.31% -1.04%
==========================================
Files 398 398
Lines 37496 37507 +11
==========================================
- Hits 23754 23371 -383
- Misses 12144 12555 +411
+ Partials 1598 1581 -17
Continue to review full report at Codecov.
|
SemaphoreCI is green now. I've discovered an interesting behavior in the Go TLS library: the error message returned from a failed handshake is not deterministic. When both sides of a TLS handshake distrust the other, the error races between The test for CN tends toward the second error, and the new test tends toward the first. |
Gentle ping |
Thanks! |
Etcd currently supports validating peers based on their TLS certificate's
CN field. The current best practice for creation and validation of TLS
certs is to use the Subject Alternative Name (SAN) fields instead, so that
a certificate might be issued with a unique CN and its logical
identities in the SANs.
This commit extends the peer validation logic to use Go's
(*"crypto/x509".Certificate).ValidateHostname
function for namevalidation, which allows SANs to be used for peer access control.
In addition, it allows name validation to be enabled on clients as well.
This is used when running Etcd behind an authenticating proxy, or as
an internal component in a larger system (like a Kubernetes master).
(See issue #8262 and PR #8616 for additional context)