mirror of
https://github.com/dolthub/dolt.git
synced 2026-04-21 02:57:46 -05:00
Merge pull request #3867 from dolthub/taylor/jwtauth
Sql server jwt auth
This commit is contained in:
Generated
+209
@@ -5455,6 +5455,215 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
= LICENSE 6681c42f6974591d2056518a26201323fa7d42bdc4d64bfc12c332b3 =
|
||||
================================================================================
|
||||
|
||||
================================================================================
|
||||
= github.com/pquerna/cachecontrol licensed under: =
|
||||
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
= LICENSE 75cd5500580317e758b5e984e017524dc961140e4889f7d427f85e41 =
|
||||
================================================================================
|
||||
|
||||
================================================================================
|
||||
= github.com/prometheus/client_golang licensed under: =
|
||||
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
// Copyright 2022 Dolthub, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package engine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/dolthub/go-mysql-server/sql/mysql_db"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/dolthub/dolt/go/libraries/utils/jwtauth"
|
||||
)
|
||||
|
||||
type JwksConfig struct {
|
||||
Name string `yaml:"name"`
|
||||
LocationUrl string `yaml:"location_url"`
|
||||
Claims map[string]string `yaml:"claims"`
|
||||
FieldsToLog []string `yaml:"fields_to_log"`
|
||||
}
|
||||
|
||||
// authenticateDoltJWTPlugin is used to authenticate plaintext user plugins
|
||||
type authenticateDoltJWTPlugin struct {
|
||||
jwksConfig []JwksConfig
|
||||
}
|
||||
|
||||
func NewAuthenticateDoltJWTPlugin(jwksConfig []JwksConfig) mysql_db.PlaintextAuthPlugin {
|
||||
return &authenticateDoltJWTPlugin{jwksConfig: jwksConfig}
|
||||
}
|
||||
|
||||
func (p *authenticateDoltJWTPlugin) Authenticate(db *mysql_db.MySQLDb, user string, userEntry *mysql_db.User, pass string) (bool, error) {
|
||||
return validateJWT(p.jwksConfig, user, userEntry.Identity, pass, time.Now())
|
||||
}
|
||||
|
||||
func validateJWT(config []JwksConfig, username, identity, token string, reqTime time.Time) (bool, error) {
|
||||
if len(config) == 0 {
|
||||
return false, fmt.Errorf("ValidateJWT: JWKS server config not found")
|
||||
}
|
||||
|
||||
expectedClaimsMap := parseUserIdentity(identity)
|
||||
sub, ok := expectedClaimsMap["sub"]
|
||||
if ok && sub != username {
|
||||
return false, fmt.Errorf("ValidateJWT: Subjects do not match")
|
||||
}
|
||||
|
||||
jwksConfig, err := getMatchingJwksConfig(config, expectedClaimsMap["jwks"])
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
pr, err := getJWTProvider(expectedClaimsMap, jwksConfig.LocationUrl)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
vd := jwtauth.NewJWTValidator(pr)
|
||||
claims, err := vd.ValidateJWT(token, reqTime)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
logString := "Authenticating with JWT: "
|
||||
for _, field := range jwksConfig.FieldsToLog {
|
||||
logString += fmt.Sprintf("%s: %s,", field, getClaimFromKey(claims, field))
|
||||
}
|
||||
logrus.Info(logString)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func getJWTProvider(expectedClaimsMap map[string]string, url string) (jwtauth.JWTProvider, error) {
|
||||
pr := jwtauth.JWTProvider{URL: url}
|
||||
for name, claim := range expectedClaimsMap {
|
||||
switch name {
|
||||
case "iss":
|
||||
pr.Issuer = claim
|
||||
case "aud":
|
||||
pr.Audience = claim
|
||||
case "sub":
|
||||
pr.Subject = claim
|
||||
case "jwks":
|
||||
continue
|
||||
default:
|
||||
return pr, fmt.Errorf("ValidateJWT: Unexpected expected claim found in user identity")
|
||||
}
|
||||
}
|
||||
return pr, nil
|
||||
}
|
||||
|
||||
func getClaimFromKey(claims *jwtauth.Claims, field string) string {
|
||||
switch field {
|
||||
case "id":
|
||||
return claims.ID
|
||||
case "iss":
|
||||
return claims.Issuer
|
||||
case "sub":
|
||||
return claims.Subject
|
||||
case "on_behalf_of":
|
||||
return claims.OnBehalfOf
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func getMatchingJwksConfig(config []JwksConfig, name string) (*JwksConfig, error) {
|
||||
for _, item := range config {
|
||||
if item.Name == name {
|
||||
return &item, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("ValidateJWT: Matching JWKS config not found")
|
||||
}
|
||||
|
||||
func parseUserIdentity(identity string) map[string]string {
|
||||
idMap := make(map[string]string)
|
||||
items := strings.Split(identity, ",")
|
||||
for _, item := range items {
|
||||
tup := strings.Split(item, "=")
|
||||
idMap[tup[0]] = tup[1]
|
||||
}
|
||||
return idMap
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
// Copyright 2022 Dolthub, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package engine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var jwksName = "jwksname"
|
||||
var sub = "test_user"
|
||||
var iss = "dolthub.com"
|
||||
var aud = "my_resource"
|
||||
var onBehalfOf = "my_user"
|
||||
var jwt = "eyJhbGciOiJSUzI1NiIsImtpZCI6ImUwNjA2Y2QwLTkwNWQtNGFiYS05MjBjLTZlNTE0YTFjYmIyNiIsInR5cCI6IkpXVCJ9.eyJhdWQiOlsibXlfcmVzb3VyY2UiXSwiZXhwIjoxNjU4Mjc1OTAzLCJpYXQiOjE2NTgyNzU4NzMsImlzcyI6ImRvbHRodWIuY29tIiwianRpIjoiN2ViZTg3YmMtOTkzMi00ZTljLTk5N2EtNjQzMDk0NTBkMWVjIiwib25fYmVoYWxmX29mIjoibXlfdXNlciIsInN1YiI6InRlc3RfdXNlciJ9.u2cUGUkQ2hk4AaxtNQB-6Jcdf5LtehFA7XX2FG8LGgTf6KfwE3cuuGaBIU8Jz9ktD9g8TjAbfAfbrNaFNYnKG6SnDUHp0t7VbfLdgfNDQqSyH0nOK2UF8ffxqa46PRxeMwTSJv8prE07rcmiZNL9Ie4vSGYLncJfMzo_RdE-A-PH7z-ZyZ_TxOMhkgMFq2Af5Px3zFuAKq-Y-PrQNopSuzjPJc0DQ93Q7EcIHfU6Fx6gOVTkzHxnOFcg3Nj-4HhqBSvBa_BdMYEzHJKx3F_9rrCCPqEGUFnxXAqFFmnZUQuQKpN2yW_zhviCVqrvbP7vOCIXmxi8YXLiGiV-4KlxHA"
|
||||
|
||||
func TestJWTAuth(t *testing.T) {
|
||||
jwksConfig := []JwksConfig{
|
||||
{
|
||||
Name: jwksName,
|
||||
LocationUrl: fmt.Sprintf("file:///testdata/test_jwks.json"),
|
||||
Claims: map[string]string{
|
||||
"alg": "RS256",
|
||||
"aud": aud,
|
||||
"iss": iss,
|
||||
"sub": sub,
|
||||
},
|
||||
FieldsToLog: []string{"id", "on_behalf_of"},
|
||||
},
|
||||
}
|
||||
|
||||
// Success
|
||||
tokenCreated := time.Date(2022, 07, 20, 0, 12, 0, 0, time.UTC) // Update time if creating new token
|
||||
authed, err := validateJWT(jwksConfig, sub, fmt.Sprintf("jwks=%s,sub=%s,iss=%s,aud=%s", jwksName, sub, iss, aud), jwt, tokenCreated)
|
||||
require.NoError(t, err)
|
||||
require.True(t, authed)
|
||||
|
||||
// Token expired
|
||||
now := time.Now()
|
||||
authed, err = validateJWT(jwksConfig, sub, fmt.Sprintf("jwks=%s,sub=%s,iss=%s,aud=%s", jwksName, sub, iss, aud), jwt, now)
|
||||
require.Error(t, err)
|
||||
require.False(t, authed)
|
||||
|
||||
// Expected sub does not match
|
||||
authed, err = validateJWT(jwksConfig, sub, fmt.Sprintf("jwks=%s,sub=%s,iss=%s,aud=%s", jwksName, "wrong-sub", iss, aud), jwt, tokenCreated)
|
||||
require.Error(t, err)
|
||||
require.False(t, authed)
|
||||
|
||||
// Jwks config doesn't exist
|
||||
authed, err = validateJWT([]JwksConfig{}, sub, fmt.Sprintf("jwks=%s,sub=%s,iss=%s,aud=%s", jwksName, sub, iss, aud), jwt, tokenCreated)
|
||||
require.Error(t, err)
|
||||
require.False(t, authed)
|
||||
|
||||
// No token
|
||||
authed, err = validateJWT(jwksConfig, sub, fmt.Sprintf("jwks=%s,sub=%s,iss=%s,aud=%s", jwksName, sub, iss, aud), "", tokenCreated)
|
||||
require.Error(t, err)
|
||||
require.False(t, authed)
|
||||
|
||||
// Unknown claim in identity string
|
||||
authed, err = validateJWT(jwksConfig, sub, fmt.Sprintf("jwks=%s,sub=%s,iss=%s,unknown=%s", jwksName, sub, iss, aud), "", tokenCreated)
|
||||
require.Error(t, err)
|
||||
require.False(t, authed)
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
"github.com/dolthub/go-mysql-server/sql"
|
||||
"github.com/dolthub/go-mysql-server/sql/analyzer"
|
||||
"github.com/dolthub/go-mysql-server/sql/information_schema"
|
||||
"github.com/dolthub/go-mysql-server/sql/mysql_db"
|
||||
"github.com/dolthub/vitess/go/vt/sqlparser"
|
||||
|
||||
"github.com/dolthub/dolt/go/cmd/dolt/cli"
|
||||
@@ -54,6 +55,7 @@ type SqlEngineConfig struct {
|
||||
ServerPass string
|
||||
Autocommit bool
|
||||
Bulk bool
|
||||
JwksConfig []JwksConfig
|
||||
}
|
||||
|
||||
// NewSqlEngine returns a SqlEngine
|
||||
@@ -106,6 +108,10 @@ func NewSqlEngine(
|
||||
// Set up engine
|
||||
engine := gms.New(analyzer.NewBuilder(pro).WithParallelism(parallelism).Build(), &gms.Config{IsReadOnly: config.IsReadOnly, TemporaryUsers: tempUsers}).WithBackgroundThreads(bThreads)
|
||||
engine.Analyzer.Catalog.MySQLDb.SetPersister(persister)
|
||||
engine.Analyzer.Catalog.MySQLDb.SetPlugins(map[string]mysql_db.PlaintextAuthPlugin{
|
||||
"authentication_dolt_jwt": NewAuthenticateDoltJWTPlugin(config.JwksConfig),
|
||||
})
|
||||
|
||||
// Load MySQL Db information
|
||||
if err = engine.Analyzer.Catalog.MySQLDb.LoadData(sql.NewEmptyContext(), data); err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
{"keys":[{"use":"sig","kty":"RSA","kid":"e0606cd0-905d-4aba-920c-6e514a1cbb26","alg":"RS256","n":"3uhDGQLrA8ZJIPAixKoxzCMzWRHb5_UWNihyccCWUicUnCOuTr5caoP4pTVdvK8SudQDQJFXBcO8i3Y5zIHTafTjYZ_ofe07_E9Pz9hFI8pvfXLfL0PWaSO5Y2XGyCgC2ibLqAEc71VYIqruyVuaYqv4gqG__gmBcR3C4gULOjYkBTNs7jMT2XaqlPE0dWDWSfLC-Zz-Czxkp52fOxUVAYb1tZcuActo6DLwnYGf5cpJMU76BhEegEkJzvJqDr9DdS996cjl2vxhPtCtS2rx7z4fCk5gCnCefztu_JjageY5Lk9IG03xzW3A2TUAXm-t_KJbRKa4-DghWEfBr8zv1w","e":"AQAB"}]}
|
||||
@@ -139,6 +139,7 @@ func Serve(
|
||||
ServerUser: serverConfig.User(),
|
||||
ServerPass: serverConfig.Password(),
|
||||
Autocommit: serverConfig.AutoCommit(),
|
||||
JwksConfig: serverConfig.JwksConfig(),
|
||||
}
|
||||
sqlEngine, err := engine.NewSqlEngine(
|
||||
ctx,
|
||||
|
||||
@@ -164,6 +164,7 @@ func TestServerGoodParams(t *testing.T) {
|
||||
DefaultServerConfig().withLogLevel(LogLevel_Info).WithPort(15408),
|
||||
DefaultServerConfig().withReadOnly(true).WithPort(15409),
|
||||
DefaultServerConfig().withUser("testusernamE").withPassword("hunter2").withTimeout(4).WithPort(15410),
|
||||
DefaultServerConfig().withAllowCleartextPasswords(true),
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
@@ -174,7 +175,7 @@ func TestServerGoodParams(t *testing.T) {
|
||||
}(test, sc)
|
||||
err := sc.WaitForStart()
|
||||
require.NoError(t, err)
|
||||
conn, err := dbr.Open("mysql", ConnectionString(test), nil)
|
||||
conn, err := dbr.Open("mysql", ConnectionString(test, "dbname"), nil)
|
||||
require.NoError(t, err)
|
||||
err = conn.Close()
|
||||
require.NoError(t, err)
|
||||
@@ -198,7 +199,7 @@ func TestServerSelect(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
const dbName = "dolt"
|
||||
conn, err := dbr.Open("mysql", ConnectionString(serverConfig)+dbName, nil)
|
||||
conn, err := dbr.Open("mysql", ConnectionString(serverConfig, dbName), nil)
|
||||
require.NoError(t, err)
|
||||
defer conn.Close()
|
||||
sess := conn.NewSession(nil)
|
||||
@@ -274,7 +275,7 @@ func TestServerSetDefaultBranch(t *testing.T) {
|
||||
|
||||
const dbName = "dolt"
|
||||
|
||||
conn, err := dbr.Open("mysql", ConnectionString(serverConfig)+dbName, nil)
|
||||
conn, err := dbr.Open("mysql", ConnectionString(serverConfig, dbName), nil)
|
||||
require.NoError(t, err)
|
||||
sess := conn.NewSession(nil)
|
||||
|
||||
@@ -316,7 +317,7 @@ func TestServerSetDefaultBranch(t *testing.T) {
|
||||
}
|
||||
conn.Close()
|
||||
|
||||
conn, err = dbr.Open("mysql", ConnectionString(serverConfig)+dbName, nil)
|
||||
conn, err = dbr.Open("mysql", ConnectionString(serverConfig, dbName), nil)
|
||||
require.NoError(t, err)
|
||||
defer conn.Close()
|
||||
|
||||
@@ -353,7 +354,7 @@ func TestServerSetDefaultBranch(t *testing.T) {
|
||||
}
|
||||
conn.Close()
|
||||
|
||||
conn, err = dbr.Open("mysql", ConnectionString(serverConfig)+dbName, nil)
|
||||
conn, err = dbr.Open("mysql", ConnectionString(serverConfig, dbName), nil)
|
||||
require.NoError(t, err)
|
||||
defer conn.Close()
|
||||
|
||||
@@ -431,7 +432,7 @@ func TestReadReplica(t *testing.T) {
|
||||
multiSetup.PushToRemote(sourceDbName, "remote1", "main")
|
||||
|
||||
t.Run("read replica pulls multiple branches", func(t *testing.T) {
|
||||
conn, err := dbr.Open("mysql", ConnectionString(serverConfig)+readReplicaDbName, nil)
|
||||
conn, err := dbr.Open("mysql", ConnectionString(serverConfig, readReplicaDbName), nil)
|
||||
defer conn.Close()
|
||||
require.NoError(t, err)
|
||||
sess := conn.NewSession(nil)
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"net"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/dolthub/dolt/go/cmd/dolt/commands/engine"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/env"
|
||||
)
|
||||
|
||||
@@ -36,22 +37,23 @@ const (
|
||||
)
|
||||
|
||||
const (
|
||||
defaultHost = "localhost"
|
||||
defaultPort = 3306
|
||||
defaultUser = "root"
|
||||
defaultPass = ""
|
||||
defaultTimeout = 8 * 60 * 60 * 1000 // 8 hours, same as MySQL
|
||||
defaultReadOnly = false
|
||||
defaultLogLevel = LogLevel_Info
|
||||
defaultAutoCommit = true
|
||||
defaultMaxConnections = 100
|
||||
defaultQueryParallelism = 2
|
||||
defaultPersistenceBahavior = loadPerisistentGlobals
|
||||
defaultDataDir = "."
|
||||
defaultCfgDir = ".doltcfg"
|
||||
defaultPrivilegeFilePath = "privileges.db"
|
||||
defaultMetricsHost = ""
|
||||
defaultMetricsPort = -1
|
||||
defaultHost = "localhost"
|
||||
defaultPort = 3306
|
||||
defaultUser = "root"
|
||||
defaultPass = ""
|
||||
defaultTimeout = 8 * 60 * 60 * 1000 // 8 hours, same as MySQL
|
||||
defaultReadOnly = false
|
||||
defaultLogLevel = LogLevel_Info
|
||||
defaultAutoCommit = true
|
||||
defaultMaxConnections = 100
|
||||
defaultQueryParallelism = 2
|
||||
defaultPersistenceBahavior = loadPerisistentGlobals
|
||||
defaultDataDir = "."
|
||||
defaultCfgDir = ".doltcfg"
|
||||
defaultPrivilegeFilePath = "privileges.db"
|
||||
defaultMetricsHost = ""
|
||||
defaultMetricsPort = -1
|
||||
defaultAllowCleartextPasswords = false
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -132,27 +134,32 @@ type ServerConfig interface {
|
||||
PrivilegeFilePath() string
|
||||
// UserVars is an array containing user specific session variables
|
||||
UserVars() []UserSessionVars
|
||||
// JwksConfig is an array containing jwks config
|
||||
JwksConfig() []engine.JwksConfig
|
||||
// AllowCleartextPasswords is true if the server should accept cleartext passwords.
|
||||
AllowCleartextPasswords() bool
|
||||
}
|
||||
|
||||
type commandLineServerConfig struct {
|
||||
host string
|
||||
port int
|
||||
user string
|
||||
password string
|
||||
timeout uint64
|
||||
readOnly bool
|
||||
logLevel LogLevel
|
||||
dbNamesAndPaths []env.EnvNameAndPath
|
||||
dataDir string
|
||||
cfgDir string
|
||||
autoCommit bool
|
||||
maxConnections uint64
|
||||
queryParallelism int
|
||||
tlsKey string
|
||||
tlsCert string
|
||||
requireSecureTransport bool
|
||||
persistenceBehavior string
|
||||
privilegeFilePath string
|
||||
host string
|
||||
port int
|
||||
user string
|
||||
password string
|
||||
timeout uint64
|
||||
readOnly bool
|
||||
logLevel LogLevel
|
||||
dbNamesAndPaths []env.EnvNameAndPath
|
||||
dataDir string
|
||||
cfgDir string
|
||||
autoCommit bool
|
||||
maxConnections uint64
|
||||
queryParallelism int
|
||||
tlsKey string
|
||||
tlsCert string
|
||||
requireSecureTransport bool
|
||||
persistenceBehavior string
|
||||
privilegeFilePath string
|
||||
allowCleartextPasswords bool
|
||||
}
|
||||
|
||||
var _ ServerConfig = (*commandLineServerConfig)(nil)
|
||||
@@ -253,6 +260,14 @@ func (cfg *commandLineServerConfig) UserVars() []UserSessionVars {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cfg *commandLineServerConfig) JwksConfig() []engine.JwksConfig {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cfg *commandLineServerConfig) AllowCleartextPasswords() bool {
|
||||
return cfg.allowCleartextPasswords
|
||||
}
|
||||
|
||||
// DatabaseNamesAndPaths returns an array of env.EnvNameAndPathObjects corresponding to the databases to be loaded in
|
||||
// a multiple db configuration. If nil is returned the server will look for a database in the current directory and
|
||||
// give it a name automatically.
|
||||
@@ -348,23 +363,29 @@ func (cfg *commandLineServerConfig) withPrivilegeFilePath(privFilePath string) *
|
||||
return cfg
|
||||
}
|
||||
|
||||
func (cfg *commandLineServerConfig) withAllowCleartextPasswords(allow bool) *commandLineServerConfig {
|
||||
cfg.allowCleartextPasswords = allow
|
||||
return cfg
|
||||
}
|
||||
|
||||
// DefaultServerConfig creates a `*ServerConfig` that has all of the options set to their default values.
|
||||
func DefaultServerConfig() *commandLineServerConfig {
|
||||
return &commandLineServerConfig{
|
||||
host: defaultHost,
|
||||
port: defaultPort,
|
||||
user: defaultUser,
|
||||
password: defaultPass,
|
||||
timeout: defaultTimeout,
|
||||
readOnly: defaultReadOnly,
|
||||
logLevel: defaultLogLevel,
|
||||
autoCommit: defaultAutoCommit,
|
||||
maxConnections: defaultMaxConnections,
|
||||
queryParallelism: defaultQueryParallelism,
|
||||
persistenceBehavior: defaultPersistenceBahavior,
|
||||
dataDir: defaultDataDir,
|
||||
cfgDir: filepath.Join(defaultDataDir, defaultCfgDir),
|
||||
privilegeFilePath: filepath.Join(defaultDataDir, defaultCfgDir, defaultPrivilegeFilePath),
|
||||
host: defaultHost,
|
||||
port: defaultPort,
|
||||
user: defaultUser,
|
||||
password: defaultPass,
|
||||
timeout: defaultTimeout,
|
||||
readOnly: defaultReadOnly,
|
||||
logLevel: defaultLogLevel,
|
||||
autoCommit: defaultAutoCommit,
|
||||
maxConnections: defaultMaxConnections,
|
||||
queryParallelism: defaultQueryParallelism,
|
||||
persistenceBehavior: defaultPersistenceBahavior,
|
||||
dataDir: defaultDataDir,
|
||||
cfgDir: filepath.Join(defaultDataDir, defaultCfgDir),
|
||||
privilegeFilePath: filepath.Join(defaultDataDir, defaultCfgDir, defaultPrivilegeFilePath),
|
||||
allowCleartextPasswords: defaultAllowCleartextPasswords,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -392,8 +413,12 @@ func ValidateConfig(config ServerConfig) error {
|
||||
}
|
||||
|
||||
// ConnectionString returns a Data Source Name (DSN) to be used by go clients for connecting to a running server.
|
||||
func ConnectionString(config ServerConfig) string {
|
||||
return fmt.Sprintf("%v:%v@tcp(%v:%v)/", config.User(), config.Password(), config.Host(), config.Port())
|
||||
func ConnectionString(config ServerConfig, database string) string {
|
||||
str := fmt.Sprintf("%v:%v@tcp(%v:%v)/%v", config.User(), config.Password(), config.Host(), config.Port(), database)
|
||||
if config.AllowCleartextPasswords() {
|
||||
str += "?allowCleartextPasswords=1"
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
// ConfigInfo returns a summary of some of the config which contains some of the more important information
|
||||
|
||||
@@ -137,7 +137,7 @@ func (cmd SqlClientCmd) Exec(ctx context.Context, commandStr string, args []stri
|
||||
}
|
||||
}
|
||||
|
||||
conn, err := dbr.Open("mysql", ConnectionString(serverConfig), nil)
|
||||
conn, err := dbr.Open("mysql", ConnectionString(serverConfig, ""), nil)
|
||||
if err != nil {
|
||||
cli.PrintErrln(err.Error())
|
||||
serverController.StopServer()
|
||||
|
||||
@@ -34,18 +34,19 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
hostFlag = "host"
|
||||
portFlag = "port"
|
||||
userFlag = "user"
|
||||
passwordFlag = "password"
|
||||
timeoutFlag = "timeout"
|
||||
readonlyFlag = "readonly"
|
||||
logLevelFlag = "loglevel"
|
||||
noAutoCommitFlag = "no-auto-commit"
|
||||
configFileFlag = "config"
|
||||
queryParallelismFlag = "query-parallelism"
|
||||
maxConnectionsFlag = "max-connections"
|
||||
persistenceBehaviorFlag = "persistence-behavior"
|
||||
hostFlag = "host"
|
||||
portFlag = "port"
|
||||
userFlag = "user"
|
||||
passwordFlag = "password"
|
||||
timeoutFlag = "timeout"
|
||||
readonlyFlag = "readonly"
|
||||
logLevelFlag = "loglevel"
|
||||
noAutoCommitFlag = "no-auto-commit"
|
||||
configFileFlag = "config"
|
||||
queryParallelismFlag = "query-parallelism"
|
||||
maxConnectionsFlag = "max-connections"
|
||||
persistenceBehaviorFlag = "persistence-behavior"
|
||||
allowCleartextPasswordsFlag = "allow-cleartext-passwords"
|
||||
)
|
||||
|
||||
func indentLines(s string) string {
|
||||
@@ -145,6 +146,7 @@ func (cmd SqlServerCmd) ArgParser() *argparser.ArgParser {
|
||||
ap.SupportsInt(maxConnectionsFlag, "", "max-connections", fmt.Sprintf("Set the number of connections handled by the server (default `%d`)", serverConfig.MaxConnections()))
|
||||
ap.SupportsString(persistenceBehaviorFlag, "", "persistence-behavior", fmt.Sprintf("Indicate whether to `load` or `ignore` persisted global variables (default `%s`)", serverConfig.PersistenceBehavior()))
|
||||
ap.SupportsString(commands.PrivsFilePathFlag, "", "privilege file", "Path to a file to load and store users and grants. Defaults to $doltcfg-dir/privileges.db")
|
||||
ap.SupportsString(allowCleartextPasswordsFlag, "", "allow-cleartext-passwords", "Allows use of cleartext passwords. Defaults to false.")
|
||||
return ap
|
||||
}
|
||||
|
||||
@@ -402,6 +404,7 @@ func getCommandLineServerConfig(dEnv *env.DoltEnv, apr *argparser.ArgParseResult
|
||||
}
|
||||
|
||||
serverConfig.autoCommit = !apr.Contains(noAutoCommitFlag)
|
||||
serverConfig.allowCleartextPasswords = apr.Contains(allowCleartextPasswordsFlag)
|
||||
|
||||
return serverConfig, nil
|
||||
}
|
||||
|
||||
+25
-17
@@ -1,19 +1,27 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIBNDCB56ADAgECAhEAhVdohjG405MnAoq13fHhEDAFBgMrZXAwGDEWMBQGA1UE
|
||||
ChMNRG9sdEh1YiwgSW5jLjAeFw0yMTA4MjcyMjI4MzdaFw0yMTA4MjgwMDI4Mzda
|
||||
MBgxFjAUBgNVBAoTDURvbHRIdWIsIEluYy4wKjAFBgMrZXADIQC/Zq8Ls6UODL79
|
||||
YzRbfgy9oahzE87ivh8FgM+lKPkBtaNGMEQwDgYDVR0PAQH/BAQDAgeAMBMGA1Ud
|
||||
JQQMMAoGCCsGAQUFBwMBMAwGA1UdEwEB/wQCMAAwDwYDVR0RBAgwBocEfwAAATAF
|
||||
BgMrZXADQQAoT9OOXUnXkw+la93z+1unL867fVNnONbNWkH/slRs/cHXIE2MQy6+
|
||||
bKq/GWJjmcE+IldXLsGefzDrV49RrucM
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIBVzCCAQmgAwIBAgIRAI0WiAW7LLS1/nv1+9T/y0swBQYDK2VwMBgxFjAUBgNV
|
||||
BAoTDURvbHRIdWIsIEluYy4wHhcNMjEwODI3MjIyODM3WhcNMjEwODI4MDAyODM3
|
||||
WjAYMRYwFAYDVQQKEw1Eb2x0SHViLCBJbmMuMCowBQYDK2VwAyEAHb23NjQMfMsj
|
||||
riWIJVCXmqWTFCuAa0ETYI/3kL7QhxqjaDBmMA4GA1UdDwEB/wQEAwIHgDATBgNV
|
||||
HSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRBKiEB
|
||||
oxoqqO7cTCUUCeFVzdC4iDAPBgNVHREECDAGhwR/AAABMAUGAytlcANBAEV94bXU
|
||||
ELMAUs+uhcp1Px4/1oHu//x56qwRWVpoeQ1AxF8hJ7ImZao2NQ1xQkbJ5KSZzPWU
|
||||
od969YFcalxnkQU=
|
||||
MIIErDCCApQCCQCnSokQKR3M/zANBgkqhkiG9w0BAQUFADAYMRYwFAYDVQQKDA1E
|
||||
b2x0SHViLCBJbmMuMB4XDTIyMDcyMTIwMDgzMloXDTI2MDcxOTIwMDgzMlowGDEW
|
||||
MBQGA1UECgwNRG9sdEh1YiwgSW5jLjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC
|
||||
AgoCggIBAMPmzHy0CmW5Xc27rbRYpJG/QKMXVAz+k2v+AkTQkUzBWKv0z8WhePB/
|
||||
tDNVfVYuYQ2sBiHTaar9nn2Lokon+YkPjyMis2aMETHVuqx0DmJb9YcxniA8M27o
|
||||
ZlfDrJtQO5UzIp9q2zhsFWj30Qdm6YUOhZ3rTnvYOMUYG/cIYLWXyQCg1oPqRVRr
|
||||
GldzLP2GdigdrS6QQjA9AdK+Zi3dP2m2vssG4gJ+lkAWOHe7wvv2RJl/alsvWXmw
|
||||
pur7Q9Z7M+tQmqGDxlyDtkDDecyqvEkxPH7mnKV1jahJjzUFHND1r44JlCN0eTmD
|
||||
Q3+RldBNZCZSJWQ42yOIK+mTSp4QUvZL9wnJ1/lMb/v7atDlF/MSLeN6SDyAPod7
|
||||
Oci8PR+nGhaOKacngrogM6SFQ1kF4tlY5Scrpg61IAcf6uxF3eSBP0qEaFvfLXZV
|
||||
mc136E4g2G1haLt7y2prckCHLXEnxurXU4xlU/SH4cy4jB/zLZJs46tM7J9ZtCjg
|
||||
QScZeNBA91kKAvHr36f/+suU3MNPAP2fmMCziH2uxh6SxTP8yzsUoV9PCTeaSnXX
|
||||
rTMB077j0TOB2qsYhLF3XsLMz+B2Jo0b7ydT7c7rMS9yYvyKPA9JSE44nUrZWj3B
|
||||
7ity1moIfrzwbH3AK3D5I9iUbBV0+JpuIZFPoqTIb15TUXJSusYHAgMBAAEwDQYJ
|
||||
KoZIhvcNAQEFBQADggIBABGrQEUFJk5StmyFUGvaw/57H+K1ZT62rusFBq1NacMb
|
||||
61dMh9xJyDMgLiUllQ8q5CS3bjYt2J2KajpU/58ugF/Ct9aoxA4vFDtfHECllYaH
|
||||
zvoiK0Dkrf901xxNVeCbHDmXbvzJ0N/xTkP80kbT4o+aBOw6fxQVEBGAGg4EEz1D
|
||||
k7v3/lEsZ2TkCPua1p9kXHaG8+wwE0hAWsaUYgXHTpzz0gUBJ69bOIlBpLKqO9It
|
||||
HStkPD7wtYnN54pmOM68EAyXAxUC7yZ9PqncX0X04hH0VlmQGfdXFJDR89mSS6B4
|
||||
P1qsi1XtnKC/hHuJlrY02uMXn7u1cVCf5uWfFm6Xs8rLL+q28gV6Tr2aXqgY0Cjl
|
||||
tNtUEIP23/irWN48c5/rKOTiUIHJy2m6UofwMQO91jgKFxIyUmkgPQmos2LLNjtk
|
||||
VFaPRigAaArwvombUmvfXJl6KoyH/je4H4+Gs+rRQURXU/PD1cioHgsOYNXSmYAj
|
||||
AQJv/xp9QBmpzb1ExJOKeWjnUWGu0Wdv4TCTXJNvfdQqOVkT6k6ty1urgr9fNOxY
|
||||
PDbHZTI6rXMtT57G108k2gAkaCE6O2R2Dm+vfW7auauqF3lNiZU9Y8IEGU2ybmE3
|
||||
s2j+THPWmhuepbZKO5daQH0zlma31QgoyhGSoZ6QUWKEjufEvfx4HwGqMP6BEmaP
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
+50
-1
@@ -1,3 +1,52 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
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
|
||||
LWLCd/YowgxkNl5j6a5QMFoZvjLi5A==
|
||||
-----END PRIVATE KEY-----
|
||||
|
||||
+25
-8
@@ -1,10 +1,27 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIBVzCCAQmgAwIBAgIRAI0WiAW7LLS1/nv1+9T/y0swBQYDK2VwMBgxFjAUBgNV
|
||||
BAoTDURvbHRIdWIsIEluYy4wHhcNMjEwODI3MjIyODM3WhcNMjEwODI4MDAyODM3
|
||||
WjAYMRYwFAYDVQQKEw1Eb2x0SHViLCBJbmMuMCowBQYDK2VwAyEAHb23NjQMfMsj
|
||||
riWIJVCXmqWTFCuAa0ETYI/3kL7QhxqjaDBmMA4GA1UdDwEB/wQEAwIHgDATBgNV
|
||||
HSUEDDAKBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRBKiEB
|
||||
oxoqqO7cTCUUCeFVzdC4iDAPBgNVHREECDAGhwR/AAABMAUGAytlcANBAEV94bXU
|
||||
ELMAUs+uhcp1Px4/1oHu//x56qwRWVpoeQ1AxF8hJ7ImZao2NQ1xQkbJ5KSZzPWU
|
||||
od969YFcalxnkQU=
|
||||
MIIErDCCApQCCQCP9IKGyBYVUDANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQKDA1E
|
||||
b2x0SHViLCBJbmMuMB4XDTIyMDcyMTE5NTUyN1oXDTI2MDcyMDE5NTUyN1owGDEW
|
||||
MBQGA1UECgwNRG9sdEh1YiwgSW5jLjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC
|
||||
AgoCggIBAMRNMquL4n2bAMQmoedUFcT/zI42ThW5o9qxh9U8MhsDqKBet7JL7ruh
|
||||
3FRj/yaU+3ax2lGgapcTnSJHWHPUX6MzUpqkwrLzKxqMrKQYnU2F96n3GOflllsB
|
||||
8ISKBy0TIipLWKupndc893qk+j6HUQ9OrtFHwroZ6/Tg32h4LcJvhkwILb8EHZpI
|
||||
fSSzi637msnXWqln1WYmX+v4ARUVVSwl5kkPGZ4PxMDQRX3ioqy2d27GbHYSo01K
|
||||
tSScQvnFJeddu09l7hNTSFixRz+XU+F+jYna8xUtqHMawEpfGw8Gsu8sMV9PUfUx
|
||||
6WrMb1tcyWEDvHwH6RUlhNa085eCRFznHLDZNxrgBwrslII9d9xW/JaRq43d4M0q
|
||||
e7F+BazB3rImMo2QHFvtvq55N7mvp+LprMjoEneBboiz1I6M0rq7Sn58FxazgQvz
|
||||
mCZmNYIrznx+S1mlJjxtC7xgDPZn5Z/68TsmT26j5UNLou7i/yb7XFdMVY6kAnoZ
|
||||
BAf4+rAUEDV85OLz0kWZSJj+DdlPOl/gIhTgrgJev2Cc7THUTnuk+nGETG49DITS
|
||||
ySWYLsMYFHweSTm3rG6sMyN7mdbRrUSM1bqbARm46mt89+0HGsFX1QLe3v4yda67
|
||||
ic93J5mkfNPZ96K9Hth3SBbZt43DvB56ZqsFQlzBZeQ3hkk7ooulAgMBAAEwDQYJ
|
||||
KoZIhvcNAQELBQADggIBAJgopHEYmETWhH06T72EpgLr3xqckCP9QZ6/UBN8eDt0
|
||||
rRqMCfM5H33qpe2wojjKwFDkR8XpwF/80VflfFBt9hc1c1fuKmyQSES9gUw10uSL
|
||||
Z54MCPOa+c8+hslkmJR8Na0QyWN5unnozVHf4XIChsgL1/FblXcOgQLPZygzMNM2
|
||||
IjdT9XpEHiZTDZDp1NmM7rkRkcpgF2J8G2dcRjo/OGpnhH7wHgxm7hS6yWLW8xPP
|
||||
8M2/8LPYA7H6HMGYeyrYuDPeVzfaHrECTft+4cjHLu/jYnVLukMMSuI9v5FjtxtX
|
||||
PYtxnLv8hnbParjSnzK8cOlGdfJDRPMUw9/tvZ4bTeyTtJQYgl/jtdaU4mbdWlge
|
||||
XMzkZGH3kKpsV2rPZXKJuqRq3vzfr51cQhEcnbJ5H8BsDUQADS3ind37guqoKhuZ
|
||||
6vFUBTKLeYK5VZ4J18ztXhEynAf7kdROKP6XbE53qtH8qQujmOMWliSFQFdidYsj
|
||||
eItzGQ4M/ZqI84UnPRL3WPdfPkWqa0x1k6PHFRcFJPp8nhl3O5V4ZdyVC3pKhzUJ
|
||||
Y8sMit5RH1K8ZTYUVtEKwMX9wRMEkbfE4u/P+yItKw7QgYRdKerlDfCGZP8JY9+k
|
||||
wqYmF56EVGQFaJdJ1ublVEHQkAVHOBowzccwWOV/OPi1sL+cf4RxAaY7gJpuNEIk
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
+50
-1
@@ -1,3 +1,52 @@
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
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
|
||||
+MjyTS/rmN7YbJRkCrgg/4kGlldmYg==
|
||||
-----END PRIVATE KEY-----
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
"github.com/dolthub/dolt/go/cmd/dolt/commands/engine"
|
||||
"github.com/dolthub/dolt/go/libraries/doltcore/env"
|
||||
)
|
||||
|
||||
@@ -95,6 +96,8 @@ type ListenerYAMLConfig struct {
|
||||
TLSCert *string `yaml:"tls_cert"`
|
||||
// RequireSecureTransport can enable a mode where non-TLS connections are turned away.
|
||||
RequireSecureTransport *bool `yaml:"require_secure_transport"`
|
||||
// AllowCleartextPasswords enables use of cleartext passwords.
|
||||
AllowCleartextPasswords *bool `yaml:"allow_cleartext_passwords"`
|
||||
}
|
||||
|
||||
// PerformanceYAMLConfig contains configuration parameters for performance tweaking
|
||||
@@ -113,13 +116,6 @@ type UserSessionVars struct {
|
||||
Vars map[string]string `yaml:"vars"`
|
||||
}
|
||||
|
||||
type JwksYAMLConfig struct {
|
||||
Name string `yaml:"name"`
|
||||
LocationUrl string `yaml:"location_url"`
|
||||
Claims map[string]string `yaml:"claims"`
|
||||
FieldsToLog []string `yaml:"fields_to_log"`
|
||||
}
|
||||
|
||||
// YAMLConfig is a ServerConfig implementation which is read from a yaml file
|
||||
type YAMLConfig struct {
|
||||
LogLevelStr *string `yaml:"log_level"`
|
||||
@@ -133,7 +129,7 @@ type YAMLConfig struct {
|
||||
MetricsConfig MetricsYAMLConfig `yaml:"metrics"`
|
||||
PrivilegeFile *string `yaml:"privilege_file"`
|
||||
Vars []UserSessionVars `yaml:"user_session_vars"`
|
||||
Jwks []JwksYAMLConfig `yaml:"jwks"`
|
||||
Jwks []engine.JwksConfig `yaml:"jwks"`
|
||||
}
|
||||
|
||||
var _ ServerConfig = YAMLConfig{}
|
||||
@@ -163,6 +159,7 @@ func serverConfigAsYAMLConfig(cfg ServerConfig) YAMLConfig {
|
||||
nillableStrPtr(cfg.TLSKey()),
|
||||
nillableStrPtr(cfg.TLSCert()),
|
||||
nillableBoolPtr(cfg.RequireSecureTransport()),
|
||||
nillableBoolPtr(cfg.AllowCleartextPasswords()),
|
||||
},
|
||||
DatabaseConfig: nil,
|
||||
}
|
||||
@@ -348,13 +345,20 @@ func (cfg YAMLConfig) UserVars() []UserSessionVars {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cfg YAMLConfig) JwksConfig() []JwksYAMLConfig {
|
||||
func (cfg YAMLConfig) JwksConfig() []engine.JwksConfig {
|
||||
if cfg.Jwks != nil {
|
||||
return cfg.Jwks
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cfg YAMLConfig) AllowCleartextPasswords() bool {
|
||||
if cfg.ListenerConfig.AllowCleartextPasswords == nil {
|
||||
return defaultAllowCleartextPasswords
|
||||
}
|
||||
return *cfg.ListenerConfig.AllowCleartextPasswords
|
||||
}
|
||||
|
||||
// QueryParallelism returns the parallelism that should be used by the go-mysql-server analyzer
|
||||
func (cfg YAMLConfig) QueryParallelism() int {
|
||||
if cfg.PerformanceConfig.QueryParallelism == nil {
|
||||
|
||||
@@ -18,9 +18,10 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
"github.com/dolthub/dolt/go/cmd/dolt/commands/engine"
|
||||
)
|
||||
|
||||
func TestUnmarshall(t *testing.T) {
|
||||
@@ -125,7 +126,7 @@ jwks:
|
||||
},
|
||||
},
|
||||
}
|
||||
expected.Jwks = []JwksYAMLConfig{
|
||||
expected.Jwks = []engine.JwksConfig{
|
||||
{
|
||||
Name: "jwks_name",
|
||||
LocationUrl: "https://website.com",
|
||||
@@ -198,10 +199,12 @@ func TestYAMLConfigDefaults(t *testing.T) {
|
||||
assert.Equal(t, "", cfg.TLSKey())
|
||||
assert.Equal(t, "", cfg.TLSCert())
|
||||
assert.Equal(t, false, cfg.RequireSecureTransport())
|
||||
assert.Equal(t, false, cfg.AllowCleartextPasswords())
|
||||
assert.Equal(t, false, cfg.DisableClientMultiStatements())
|
||||
assert.Equal(t, defaultMetricsHost, cfg.MetricsHost())
|
||||
assert.Equal(t, defaultMetricsPort, cfg.MetricsPort())
|
||||
assert.Nil(t, cfg.MetricsConfig.Labels)
|
||||
assert.Equal(t, defaultAllowCleartextPasswords, cfg.AllowCleartextPasswords())
|
||||
|
||||
c, err := LoadTLSConfig(cfg)
|
||||
assert.NoError(t, err)
|
||||
@@ -234,7 +237,7 @@ listener:
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, c)
|
||||
assert.Len(t, c.Certificates, 1)
|
||||
assert.Len(t, c.Certificates[0].Certificate, 2)
|
||||
assert.Len(t, c.Certificates[0].Certificate, 1)
|
||||
|
||||
cfg = YAMLConfig{}
|
||||
err = yaml.Unmarshal([]byte(`
|
||||
|
||||
@@ -52,7 +52,7 @@ require (
|
||||
google.golang.org/api v0.32.0
|
||||
google.golang.org/grpc v1.37.0
|
||||
google.golang.org/protobuf v1.27.1
|
||||
gopkg.in/square/go-jose.v2 v2.5.1
|
||||
gopkg.in/square/go-jose.v2 v2.6.0
|
||||
gopkg.in/src-d/go-errors.v1 v1.0.0
|
||||
gopkg.in/yaml.v2 v2.3.0
|
||||
)
|
||||
@@ -112,6 +112,7 @@ require (
|
||||
github.com/pierrec/lz4/v4 v4.1.6 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||
github.com/pquerna/cachecontrol v0.1.0
|
||||
github.com/prometheus/client_model v0.2.0 // indirect
|
||||
github.com/prometheus/common v0.26.0 // indirect
|
||||
github.com/prometheus/procfs v0.6.0 // indirect
|
||||
@@ -139,4 +140,8 @@ replace (
|
||||
github.com/oliveagle/jsonpath => github.com/dolthub/jsonpath v0.0.0-20210609232853-d49537a30474
|
||||
)
|
||||
|
||||
// replace github.com/dolthub/vitess => /Users/taylor/go/src/github.com/dolthub/vitess
|
||||
|
||||
// replace github.com/dolthub/go-mysql-server => /Users/taylor/go/src/github.com/dolthub/go-mysql-server
|
||||
|
||||
go 1.18
|
||||
|
||||
@@ -596,6 +596,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/pquerna/cachecontrol v0.1.0 h1:yJMy84ti9h/+OEWa752kBTKv4XC30OtVVHYv/8cTqKc=
|
||||
github.com/pquerna/cachecontrol v0.1.0/go.mod h1:NrUG3Z7Rdu85UNR3vm7SOsl1nFIeSiQnrHV5K9mBcUI=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
|
||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||
@@ -1199,8 +1201,8 @@ gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mN
|
||||
gopkg.in/jcmturner/gokrb5.v7 v7.3.0/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM=
|
||||
gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w=
|
||||
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI=
|
||||
gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
gopkg.in/src-d/go-errors.v1 v1.0.0 h1:cooGdZnCjYbeS1zb1s6pVAAimTdKceRrpn7aKOnNIfc=
|
||||
gopkg.in/src-d/go-errors.v1 v1.0.0/go.mod h1:q1cBlomlw2FnDBDNGlnh6X0jPihy+QxZfMMNxPCbdYg=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
|
||||
@@ -331,7 +331,7 @@ func startServer(t *testing.T) (*sqlserver.ServerController, sqlserver.ServerCon
|
||||
|
||||
func newConnection(t *testing.T, serverConfig sqlserver.ServerConfig) (*dbr.Connection, *dbr.Session) {
|
||||
const dbName = "dolt"
|
||||
conn, err := dbr.Open("mysql", sqlserver.ConnectionString(serverConfig)+dbName, nil)
|
||||
conn, err := dbr.Open("mysql", sqlserver.ConnectionString(serverConfig, dbName), nil)
|
||||
require.NoError(t, err)
|
||||
sess := conn.NewSession(nil)
|
||||
return conn, sess
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
// Copyright 2022 Dolthub, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package jwtauth
|
||||
|
||||
import (
|
||||
"gopkg.in/square/go-jose.v2/jwt"
|
||||
)
|
||||
|
||||
type Claims struct {
|
||||
jwt.Claims
|
||||
OnBehalfOf string `json:"on_behalf_of"`
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
Creates files with a jwks and a jwt that can be validating using the jwks. Used in bats.
|
||||
@@ -0,0 +1,127 @@
|
||||
// Copyright 2022 Dolthub, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"gopkg.in/square/go-jose.v2"
|
||||
"gopkg.in/square/go-jose.v2/jwt"
|
||||
)
|
||||
|
||||
var sub = "test_user"
|
||||
var iss = "dolthub.com"
|
||||
var aud = "my_resource"
|
||||
var onBehalfOf = "my_user"
|
||||
|
||||
func main() {
|
||||
privKey, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
pubKey := privKey.Public()
|
||||
|
||||
kid, err := uuid.NewRandom()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
err = writeJWKSToFile(pubKey, kid.String())
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
jwt, err := generateJWT(privKey, kid.String())
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile("token.jwt", []byte(jwt), 0644)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
func writeJWKSToFile(pubKey crypto.PublicKey, kid string) error {
|
||||
jwk := jose.JSONWebKey{
|
||||
KeyID: kid,
|
||||
Key: pubKey,
|
||||
Use: "sig",
|
||||
Algorithm: "RS256",
|
||||
}
|
||||
jwks := jose.JSONWebKeySet{Keys: []jose.JSONWebKey{jwk}}
|
||||
|
||||
jwksjson, err := json.Marshal(jwks)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = ioutil.WriteFile("test_jwks.json", jwksjson, 0644)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func generateJWT(privKey *rsa.PrivateKey, kid string) (string, error) {
|
||||
id, err := uuid.NewRandom()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
claims := jwt.Claims{
|
||||
ID: id.String(),
|
||||
Audience: []string{aud},
|
||||
Issuer: iss,
|
||||
Subject: sub,
|
||||
IssuedAt: jwt.NewNumericDate(now),
|
||||
Expiry: jwt.NewNumericDate(now.Add(30 * time.Second)),
|
||||
}
|
||||
privClaims := struct {
|
||||
OnBehalfOf string `json:"on_behalf_of"`
|
||||
}{
|
||||
onBehalfOf,
|
||||
}
|
||||
|
||||
sig := jose.SigningKey{Algorithm: jose.RS256, Key: privKey}
|
||||
opts := (&jose.SignerOptions{ExtraHeaders: map[jose.HeaderKey]interface{}{
|
||||
"kid": kid,
|
||||
}}).WithType("JWT")
|
||||
|
||||
signer, err := jose.NewSigner(sig, opts)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
jwtBuilder := jwt.Signed(signer)
|
||||
jwtBuilder = jwtBuilder.Claims(claims)
|
||||
jwtBuilder = jwtBuilder.Claims(privClaims)
|
||||
|
||||
com, err := jwtBuilder.CompactSerialize()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return com, nil
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
// Copyright 2022 Dolthub, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package jwtauth
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
jose "gopkg.in/square/go-jose.v2"
|
||||
"gopkg.in/square/go-jose.v2/json"
|
||||
|
||||
"github.com/pquerna/cachecontrol"
|
||||
)
|
||||
|
||||
type cachedJWKS struct {
|
||||
value *jose.JSONWebKeySet
|
||||
expires time.Time
|
||||
mutex *sync.Mutex
|
||||
}
|
||||
|
||||
func newCachedJWKS() *cachedJWKS {
|
||||
return &cachedJWKS{value: nil, expires: time.Now(), mutex: &sync.Mutex{}}
|
||||
}
|
||||
|
||||
type fetchedJWKS struct {
|
||||
URL string
|
||||
cache *cachedJWKS
|
||||
}
|
||||
|
||||
func newJWKS(provider JWTProvider) *fetchedJWKS {
|
||||
return &fetchedJWKS{URL: provider.URL, cache: newCachedJWKS()}
|
||||
}
|
||||
|
||||
func (f *fetchedJWKS) needsRefresh() bool {
|
||||
return f.cache.value == nil || time.Now().After(f.cache.expires)
|
||||
}
|
||||
|
||||
func (f *fetchedJWKS) GetJWKS() (*jose.JSONWebKeySet, error) {
|
||||
f.cache.mutex.Lock()
|
||||
defer f.cache.mutex.Unlock()
|
||||
if f.needsRefresh() {
|
||||
tr := &http.Transport{}
|
||||
pwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Allows use of file:// for jwks location url for tests
|
||||
tr.RegisterProtocol("file", http.NewFileTransport(http.Dir(pwd)))
|
||||
client := &http.Client{Transport: tr}
|
||||
|
||||
request, err := http.NewRequest("GET", f.URL, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
response, err := client.Do(request)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if response.StatusCode/100 != 2 {
|
||||
return nil, errors.New("FetchedJWKS: Non-2xx status code from JWKS fetch")
|
||||
} else {
|
||||
defer response.Body.Close()
|
||||
contents, err := ioutil.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
jwks := jose.JSONWebKeySet{}
|
||||
err = json.Unmarshal(contents, &jwks)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
f.cache.value = &jwks
|
||||
_, _, err = cachecontrol.CachableResponse(request, response, cachecontrol.Options{})
|
||||
}
|
||||
}
|
||||
return f.cache.value, nil
|
||||
}
|
||||
|
||||
func (f *fetchedJWKS) GetKey(kid string) ([]jose.JSONWebKey, error) {
|
||||
jwks, err := f.GetJWKS()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return jwks.Key(kid), nil
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright 2022 Dolthub, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package jwtauth
|
||||
|
||||
type JWTProvider struct {
|
||||
URL string
|
||||
Issuer string
|
||||
Audience string
|
||||
Subject string
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
// Copyright 2022 Dolthub, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package jwtauth
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
jose "gopkg.in/square/go-jose.v2"
|
||||
"gopkg.in/square/go-jose.v2/jwt"
|
||||
)
|
||||
|
||||
type KeyProvider interface {
|
||||
GetKey(kid string) ([]jose.JSONWebKey, error)
|
||||
}
|
||||
|
||||
var ErrKeyNotFound = errors.New("Key not found")
|
||||
|
||||
func ValidateJWT(unparsed string, reqTime time.Time, keyProvider KeyProvider, expectedClaims jwt.Expected) (*Claims, error) {
|
||||
parsed, err := jwt.ParseSigned(unparsed)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(parsed.Headers) != 1 {
|
||||
return nil, fmt.Errorf("ValidateJWT: Unexpected JWT headers length %v.", len(parsed.Headers))
|
||||
}
|
||||
|
||||
if parsed.Headers[0].Algorithm != "RS512" &&
|
||||
parsed.Headers[0].Algorithm != "RS256" &&
|
||||
parsed.Headers[0].Algorithm != "EdDSA" {
|
||||
return nil, fmt.Errorf("ValidateJWT: Currently only support RS256, RS512 and EdDSA signatures. Unexpected algorithm: %v", parsed.Headers[0].Algorithm)
|
||||
}
|
||||
|
||||
keyID := parsed.Headers[0].KeyID
|
||||
|
||||
keys, err := keyProvider.GetKey(keyID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var claims Claims
|
||||
claimsError := fmt.Errorf("ValidateJWT: KeyID: %v. Err: %w", keyID, ErrKeyNotFound)
|
||||
for _, key := range keys {
|
||||
claimsError = parsed.Claims(key.Key, &claims)
|
||||
if claimsError == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
if claimsError != nil {
|
||||
return nil, claimsError
|
||||
}
|
||||
|
||||
if err := claims.Validate(expectedClaims.WithTime(reqTime)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &claims, nil
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// Copyright 2022 Dolthub, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package jwtauth
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gopkg.in/square/go-jose.v2/jwt"
|
||||
)
|
||||
|
||||
type JWTValidator interface {
|
||||
ValidateJWT(unparsed string, reqTime time.Time) (*Claims, error)
|
||||
}
|
||||
|
||||
type fetchingJWTValidator struct {
|
||||
jwks *fetchedJWKS
|
||||
expected jwt.Expected
|
||||
}
|
||||
|
||||
func NewJWTValidator(provider JWTProvider) JWTValidator {
|
||||
expected := jwt.Expected{Issuer: provider.Issuer, Audience: jwt.Audience{provider.Audience}}
|
||||
return &fetchingJWTValidator{jwks: newJWKS(provider), expected: expected}
|
||||
}
|
||||
|
||||
func (v *fetchingJWTValidator) ValidateJWT(unparsed string, reqTime time.Time) (*Claims, error) {
|
||||
return ValidateJWT(unparsed, reqTime, v.jwks, v.expected)
|
||||
}
|
||||
@@ -198,7 +198,7 @@ func executeServerQueries(ctx context.Context, b *testing.B, dEnv *env.DoltEnv,
|
||||
}
|
||||
|
||||
func executeQuery(cfg srv.ServerConfig, q query) error {
|
||||
cs := srv.ConnectionString(cfg) + database
|
||||
cs := srv.ConnectionString(cfg, database)
|
||||
conn, err := dbr.Open("mysql", cs, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -210,7 +210,7 @@ func executeServerQueries(ctx context.Context, b *testing.B, dEnv *env.DoltEnv,
|
||||
}
|
||||
|
||||
func executeQuery(cfg srv.ServerConfig, q query) error {
|
||||
cs := srv.ConnectionString(cfg) + database
|
||||
cs := srv.ConnectionString(cfg, database)
|
||||
conn, err := dbr.Open("mysql", cs, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
#!/usr/bin/env bats
|
||||
load $BATS_TEST_DIRNAME/helper/common.bash
|
||||
load $BATS_TEST_DIRNAME/helper/query-server-common.bash
|
||||
|
||||
make_repo() {
|
||||
mkdir "$1"
|
||||
cd "$1"
|
||||
dolt init
|
||||
cd ..
|
||||
}
|
||||
|
||||
setup() {
|
||||
skiponwindows "Missing dependencies"
|
||||
setup_no_dolt_init
|
||||
make_repo repo1
|
||||
(cd "$BATS_TEST_DIRNAME"/../../go/libraries/utils/jwtauth/gen_keys && go run .)
|
||||
}
|
||||
|
||||
teardown() {
|
||||
stop_sql_server
|
||||
teardown_common
|
||||
rm -rf "$BATS_TEST_DIRNAME/../../go/libraries/utils/jwtauth/gen_keys/token.jwt"
|
||||
rm -rf "$BATS_TEST_DIRNAME/../../go/libraries/utils/jwtauth/gen_keys/test_jwks.json"
|
||||
}
|
||||
|
||||
|
||||
@test "sql-jwt-auth: jwt auth from config" {
|
||||
cd repo1
|
||||
cp "$BATS_TEST_DIRNAME"/../../go/cmd/dolt/commands/sqlserver/testdata/chain_key.pem .
|
||||
cp "$BATS_TEST_DIRNAME"/../../go/cmd/dolt/commands/sqlserver/testdata/chain_cert.pem .
|
||||
cp "$BATS_TEST_DIRNAME"/../../go/libraries/utils/jwtauth/gen_keys/test_jwks.json .
|
||||
let PORT="$$ % (65536-1024) + 1024"
|
||||
TOKEN="`cat $BATS_TEST_DIRNAME/../../go/libraries/utils/jwtauth/gen_keys/token.jwt`"
|
||||
|
||||
cat >config.yml <<EOF
|
||||
log_level: debug
|
||||
user:
|
||||
name: dolt
|
||||
listener:
|
||||
host: "0.0.0.0"
|
||||
port: $PORT
|
||||
tls_cert: chain_cert.pem
|
||||
tls_key: chain_key.pem
|
||||
require_secure_transport: true
|
||||
privilege_file: privs.json
|
||||
jwks:
|
||||
- name: jwksname
|
||||
location_url: file:///test_jwks.json
|
||||
claims:
|
||||
alg: RS256
|
||||
aud: my_resource
|
||||
sub: test_jwt_user
|
||||
iss: dolthub.com
|
||||
fields_to_log: [on_behalf_of,id]
|
||||
EOF
|
||||
|
||||
dolt sql --privilege-file=privs.json -q "CREATE USER dolt@'127.0.0.1'"
|
||||
dolt sql --privilege-file=privs.json -q "GRANT ALL ON *.* TO dolt@'127.0.0.1' WITH GRANT OPTION"
|
||||
dolt sql --privilege-file=privs.json -q "CREATE USER test_jwt_user@'127.0.0.1' IDENTIFIED WITH authentication_dolt_jwt AS 'jwks=jwksname,sub=test_jwt_user,iss=dolthub.com,aud=my_resource'"
|
||||
dolt sql --privilege-file=privs.json -q "GRANT ALL ON *.* TO test_jwt_user@'127.0.0.1' WITH GRANT OPTION"
|
||||
|
||||
dolt sql-server --config ./config.yml &
|
||||
SERVER_PID=$!
|
||||
|
||||
|
||||
# We do things manually here because we need TLS support.
|
||||
python3 -c '
|
||||
import mysql.connector
|
||||
import sys
|
||||
import time
|
||||
import os
|
||||
i=0
|
||||
|
||||
os.environ["LIBMYSQL_ENABLE_CLEARTEXT_PLUGIN"] = "1"
|
||||
args = sys.argv[sys.argv.index("--") + 1:]
|
||||
password = args[0]
|
||||
|
||||
while True:
|
||||
try:
|
||||
with mysql.connector.connect(
|
||||
host="127.0.0.1",
|
||||
user="test_jwt_user",
|
||||
password=password,
|
||||
port='"$PORT"',
|
||||
database="repo1",
|
||||
connection_timeout=1
|
||||
) as c:
|
||||
cursor = c.cursor()
|
||||
cursor.execute("show tables")
|
||||
for (t) in cursor:
|
||||
print(t)
|
||||
sys.exit(0)
|
||||
except mysql.connector.Error as err:
|
||||
if err.errno != 2003:
|
||||
raise err
|
||||
else:
|
||||
i += 1
|
||||
time.sleep(1)
|
||||
if i == 10:
|
||||
raise err
|
||||
' -- "$TOKEN"
|
||||
}
|
||||
Reference in New Issue
Block a user