-
Notifications
You must be signed in to change notification settings - Fork 5.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
server, sessionctx: support token-based authentication #36152
Conversation
[REVIEW NOTIFICATION] This pull request has been approved by:
To complete the pull request process, please ask the reviewers in the list to review by filling The full list of commands accepted by this bot can be found here. Reviewer can indicate their review by submitting an approval review. |
Code Coverage Details: https://codecov.io/github/pingcap/tidb/commit/03cb1c70653da5de71a196b509a84b0087afe437 |
executor/show.go
Outdated
// The token may be leaked without TLS, so we enforce a TLS connection. | ||
if e.ctx.GetSessionVars().TLSConnectionState == nil { | ||
//return ErrCannotMigrateSession.GenWithStackByArgs("the token must be queried in a TLS connection") | ||
return errors.New("the token must be queried in a TLS connection") |
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 we could use ErrSecureTransportRequired
for this error?
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.
Yes, but only if we require secure transport, not if we require TLS.
secure transport is either TLS or a UNIX socket.
I think allowing a UNIX socket or TLS is the right option 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.
The error message of ErrSecureTransportRequired
is Connections using insecure transport are prohibited while --require_secure_transport=ON.
, but the --require_secure_transport
is OFF
when it comes 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.
Got it, thanks!
Please make the first letter upper-cased: "The token must be queried in a TLS connection"
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.
Yes, but only if we require secure transport, not if we require TLS.
secure transport is either TLS or a UNIX socket.
I think allowing a UNIX socket or TLS is the right option here.
To judge whether it's a Unix socket, I made use of SessionVars.ConnectionInfo
, which is only used for audit logs before. Thus, every connection has a ConnectionInfo
now, which occupies a little more memory. The commit: 40735d3
return nil | ||
}}, | ||
{Scope: ScopeGlobal, Name: TiDBAuthSigningKey, Value: "", Type: TypeStr, SetGlobal: func(s *SessionVars, val string) error { | ||
sessionstates.SetKeyPath(val) |
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 have one concern: every tidb may not be deployed identically and may have different filesystems, i.e. different paths for the 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.
At least for now, we could accept the identical cert path for all instances. TiDB instances with different paths like this would be hard to maintain and those paths are generally configured as command-line arguments.
BTW, this concern reminds me to confirm that: if we have multiple TiDB servers deployed on the same node, are they supposed to use the same certs and keys? @djshow832
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 MySQL paths are often relative to the data directory, which allows deployments on different paths.
Maybe there should be a CertDir
for this as well as other SSL/TLS related files?
It is also possible to store this in either a table in TiDB or on PD/TiKV and use that to distribute this. The benefit for this is that scaling out is easy. The drawback is that doing this in a secure way is more difficult.
Could/should we use something like AWS KMS for 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.
I talked about this with the PM. He suggests making it a global variable.
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.
At least for now, we could accept the identical cert path for all instances. TiDB instances with different paths like this would be hard to maintain and those paths are generally configured as command-line arguments.
BTW, this concern reminds me to confirm that: if we have multiple TiDB servers deployed on the same node, are they supposed to use the same certs and keys? @djshow832
They could use the same certs, as long as they can read them concurrently. The rationale is that the certs are supposed to be the same.
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 MySQL paths are often relative to the data directory, which allows deployments on different paths. Maybe there should be a
CertDir
for this as well as other SSL/TLS related files?
I looked up the doc of SSL-related system variables in MySQL: https://dev.mysql.com/doc/refman/8.0/en/using-encrypted-connections.html#using-encrypted-connections-server-side-runtime-configuration. I saw some examples from somewhere else and found that ssl_ca
, ssl_cert
, and ssl_key
are not relative paths. Is that so?
A CertDir
is a good idea, although it adds one more variable. The most important thing of updating the configuration of other TLS related files is backward compatibility. I think it's feasible.
I surveyed another DBMS as a reference: it has a CertsDir
configuration. The file names under this directory should be organized as client.<username>.crt
, client-tenant.<tenant-id>.crt
, etc.
Could/should we use something like AWS KMS for this?
I'm not familiar with KMS. I'll take a look. I'll appreciate much if you can summarize how to use it.
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.
The description said something about validating the CN. If/how is the CN validated? is this going to be the hostname of the client? if so, then probably using the SubjectAlternativeName is what should be done instead.
I haven't actually run the code yet and I don't have a full understanding about how this is going to work yet. However I also don't see any major issues with this, at least not yet, which is good.
executor/show.go
Outdated
// The token may be leaked without TLS, so we enforce a TLS connection. | ||
if e.ctx.GetSessionVars().TLSConnectionState == nil { | ||
//return ErrCannotMigrateSession.GenWithStackByArgs("the token must be queried in a TLS connection") | ||
return errors.New("the token must be queried in a TLS connection") |
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.
Yes, but only if we require secure transport, not if we require TLS.
secure transport is either TLS or a UNIX socket.
I think allowing a UNIX socket or TLS is the right option here.
@@ -167,6 +167,7 @@ const ( | |||
AuthNativePassword = "mysql_native_password" // #nosec G101 | |||
AuthCachingSha2Password = "caching_sha2_password" // #nosec G101 | |||
AuthSocket = "auth_socket" | |||
AuthTiDBSessionToken = "tidb_session_token" |
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 like the tidb_
prefix here. That helps to avoids name collisions from future MySQL authentication methods.
return nil | ||
}}, | ||
{Scope: ScopeGlobal, Name: TiDBAuthSigningKey, Value: "", Type: TypeStr, SetGlobal: func(s *SessionVars, val string) error { | ||
sessionstates.SetKeyPath(val) |
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 MySQL paths are often relative to the data directory, which allows deployments on different paths.
Maybe there should be a CertDir
for this as well as other SSL/TLS related files?
It is also possible to store this in either a table in TiDB or on PD/TiKV and use that to distribute this. The benefit for this is that scaling out is easy. The drawback is that doing this in a secure way is more difficult.
Could/should we use something like AWS KMS for this?
And for |
As far as I know, it is safely skipped, for now. |
I think it's fine to add it to the statement history and it will, because the result of the query is not recorded. The audit log will also log it. |
You can check this: https://docs.pingcap.com/tidb/v5.0/enable-tls-between-components#verify-component-callers-identity. I can configure the common name of the proxy as
I'm just notifying you that I'm adding a new auth-plugin, since this module is what you're concerned about. If you like, you can give me some advice, that will be great. @dveeden |
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.
LGTM
/merge |
This pull request has been accepted and is ready to merge. Commit hash: 40735d3
|
/run-unit-test |
/run-all-tests |
/run-check_dev_2 |
/run-mysql-test |
1 similar comment
/run-mysql-test |
TiDB MergeCI notify🔴 Bad News! New failing [1] after this pr merged.
|
What problem does this PR solve?
Issue Number: close #35913
Problem Summary:
Support authentication using a session token. The token serves as the password. This is used for session manager, which migrates sessions.
What is changed and how it works?
tidb_session_token
. If the plugin istidb_session_token
, then it will bypass the normal authentication process and only validate the session token.show session_states
statement. It requires a TLS connection because the token is confidential.tidb_auth_signing_cert
andtidb_auth_signing_key
, which are used to configure the path of the signing certificate.Other considerations:
cluster-verify-cn
is not documented, so I assume it's not commonly used.tidb_session_token
, the token is sent already. So it may require another switch-plugin request to pass the token, which is more complicated. For now, we can only turn on therequire-secure-transport
.Check List
Tests
Side effects
Documentation
Release note
Please refer to Release Notes Language Style Guide to write a quality release note.