mirror of
https://github.com/dolthub/dolt.git
synced 2026-04-29 19:39:52 -05:00
Feedback
This commit is contained in:
@@ -102,7 +102,10 @@ func clone(ctx context.Context, apr *argparser.ArgParseResults, dEnv *env.DoltEn
|
||||
return verr
|
||||
}
|
||||
|
||||
dEnv.UserPassConfig = getUserAndPassConfig(apr)
|
||||
dEnv.UserPassConfig, verr = getUserAndPassConfig(apr)
|
||||
if verr != nil {
|
||||
return verr
|
||||
}
|
||||
|
||||
userDirExists, _ := dEnv.FS.Exists(dir)
|
||||
|
||||
@@ -233,13 +236,16 @@ func validateAndParseDolthubUrl(urlStr string) (string, bool) {
|
||||
return "", false
|
||||
}
|
||||
|
||||
func getUserAndPassConfig(apr *argparser.ArgParseResults) *creds.DoltCredsForPass {
|
||||
func getUserAndPassConfig(apr *argparser.ArgParseResults) (*creds.DoltCredsForPass, errhand.VerboseError) {
|
||||
if !apr.Contains(cli.UserParam) {
|
||||
return nil
|
||||
return nil, nil
|
||||
}
|
||||
pass, found := os.LookupEnv("DOLT_REMOTE_PASSWORD")
|
||||
if !found {
|
||||
return nil, errhand.BuildDError("error: must set DOLT_REMOTE_PASSWORD environment variable to use --user param").Build()
|
||||
}
|
||||
pass := os.Getenv("DOLT_REMOTE_PASSWORD")
|
||||
return &creds.DoltCredsForPass{
|
||||
Username: apr.GetValueOrDefault(cli.UserParam, ""),
|
||||
Password: pass,
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -238,7 +238,8 @@ func Serve(
|
||||
ReadOnly: true,
|
||||
HttpListenAddr: listenaddr,
|
||||
GrpcListenAddr: listenaddr,
|
||||
}, &remotesrv.UserAuth{User: serverConfig.User(), Password: serverConfig.Password()})
|
||||
})
|
||||
args = sqle.WithUserPasswordAuth(args, remotesrv.UserAuth{User: serverConfig.User(), Password: serverConfig.Password()})
|
||||
args.TLSConfig = serverConf.TLSConfig
|
||||
remoteSrv, err = remotesrv.NewServer(args)
|
||||
if err != nil {
|
||||
|
||||
@@ -60,11 +60,6 @@ type DoltCreds struct {
|
||||
KeyID []byte
|
||||
}
|
||||
|
||||
type DoltCredsForPass struct {
|
||||
Username string
|
||||
Password string
|
||||
}
|
||||
|
||||
func PubKeyStrToKIDStr(pub string) (string, error) {
|
||||
data, err := B32CredsEncoding.DecodeString(pub)
|
||||
|
||||
@@ -126,20 +121,15 @@ func (dc DoltCreds) Sign(data []byte) []byte {
|
||||
}
|
||||
|
||||
type RPCCreds struct {
|
||||
PrivKey ed25519.PrivateKey
|
||||
KeyID string
|
||||
Audience string
|
||||
Issuer string
|
||||
Subject string
|
||||
RequireTLS bool
|
||||
UserPassContents string
|
||||
PrivKey ed25519.PrivateKey
|
||||
KeyID string
|
||||
Audience string
|
||||
Issuer string
|
||||
Subject string
|
||||
RequireTLS bool
|
||||
}
|
||||
|
||||
func (c *RPCCreds) toBearerToken() (string, error) {
|
||||
if len(c.UserPassContents) > 0 {
|
||||
return "", fmt.Errorf("cannot create bearer token with user/pass credentials")
|
||||
}
|
||||
|
||||
key := jose.SigningKey{Algorithm: jose.EdDSA, Key: c.PrivKey}
|
||||
opts := &jose.SignerOptions{ExtraHeaders: map[jose.HeaderKey]interface{}{
|
||||
JWTKIDHeader: c.KeyID,
|
||||
@@ -163,11 +153,6 @@ func (c *RPCCreds) toBearerToken() (string, error) {
|
||||
}
|
||||
|
||||
func (c *RPCCreds) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
|
||||
if len(c.UserPassContents) > 0 {
|
||||
return map[string]string{
|
||||
"authorization": "Basic " + c.UserPassContents,
|
||||
}, nil
|
||||
}
|
||||
t, err := c.toBearerToken()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -195,13 +180,34 @@ func (dc DoltCreds) RPCCreds(audience string) *RPCCreds {
|
||||
}
|
||||
}
|
||||
|
||||
func (dcp DoltCredsForPass) ToBase64Str() string {
|
||||
return base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", dcp.Username, dcp.Password)))
|
||||
type DoltCredsForPass struct {
|
||||
Username string
|
||||
Password string
|
||||
}
|
||||
|
||||
func (dc DoltCredsForPass) RPCCreds() *RPCCreds {
|
||||
return &RPCCreds{
|
||||
type RPCCredsForPass struct {
|
||||
RequireTLS bool
|
||||
UserPassContents string
|
||||
}
|
||||
|
||||
func (dcp DoltCredsForPass) ToBase64Str() string {
|
||||
bStr := []byte(fmt.Sprintf("%s:%s", dcp.Username, dcp.Password))
|
||||
return base64.StdEncoding.EncodeToString(bStr)
|
||||
}
|
||||
|
||||
func (dc DoltCredsForPass) RPCCreds() *RPCCredsForPass {
|
||||
return &RPCCredsForPass{
|
||||
RequireTLS: false,
|
||||
UserPassContents: dc.ToBase64Str(),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *RPCCredsForPass) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
|
||||
return map[string]string{
|
||||
"authorization": "Basic " + c.UserPassContents,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *RPCCredsForPass) RequireTransportSecurity() bool {
|
||||
return c.RequireTLS
|
||||
}
|
||||
|
||||
@@ -33,12 +33,12 @@ type UserAuth struct {
|
||||
Password string
|
||||
}
|
||||
|
||||
type serverinterceptor struct {
|
||||
type ServerInterceptor struct {
|
||||
Lgr *logrus.Entry
|
||||
ExpectedUserAuth UserAuth
|
||||
}
|
||||
|
||||
func (si *serverinterceptor) Stream() grpc.StreamServerInterceptor {
|
||||
func (si *ServerInterceptor) Stream() grpc.StreamServerInterceptor {
|
||||
return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
|
||||
if err := si.authenticate(ss.Context()); err != nil {
|
||||
return err
|
||||
@@ -48,7 +48,7 @@ func (si *serverinterceptor) Stream() grpc.StreamServerInterceptor {
|
||||
}
|
||||
}
|
||||
|
||||
func (si *serverinterceptor) Unary() grpc.UnaryServerInterceptor {
|
||||
func (si *ServerInterceptor) Unary() grpc.UnaryServerInterceptor {
|
||||
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
|
||||
if err := si.authenticate(ctx); err != nil {
|
||||
return nil, err
|
||||
@@ -58,14 +58,14 @@ func (si *serverinterceptor) Unary() grpc.UnaryServerInterceptor {
|
||||
}
|
||||
}
|
||||
|
||||
func (si *serverinterceptor) Options() []grpc.ServerOption {
|
||||
func (si *ServerInterceptor) Options() []grpc.ServerOption {
|
||||
return []grpc.ServerOption{
|
||||
grpc.ChainUnaryInterceptor(si.Unary()),
|
||||
grpc.ChainStreamInterceptor(si.Stream()),
|
||||
}
|
||||
}
|
||||
|
||||
func (si *serverinterceptor) authenticate(ctx context.Context) error {
|
||||
func (si *ServerInterceptor) authenticate(ctx context.Context) error {
|
||||
if len(si.ExpectedUserAuth.User) == 0 && len(si.ExpectedUserAuth.Password) == 0 {
|
||||
return nil
|
||||
}
|
||||
@@ -86,7 +86,8 @@ func (si *serverinterceptor) authenticate(ctx context.Context) error {
|
||||
si.Lgr.Infof("incoming request authorization header failed to decode: %v", err)
|
||||
return status.Error(codes.Unauthenticated, "unauthenticated")
|
||||
}
|
||||
compare := subtle.ConstantTimeCompare(uDec, []byte(fmt.Sprintf("%s:%s", si.ExpectedUserAuth.User, si.ExpectedUserAuth.Password)))
|
||||
uExp := []byte(fmt.Sprintf("%s:%s", si.ExpectedUserAuth.User, si.ExpectedUserAuth.Password))
|
||||
compare := subtle.ConstantTimeCompare(uDec, uExp)
|
||||
if compare == 0 {
|
||||
|
||||
si.Lgr.Infof("incoming request authorization header failed to match")
|
||||
|
||||
@@ -61,8 +61,7 @@ type ServerArgs struct {
|
||||
ReadOnly bool
|
||||
Options []grpc.ServerOption
|
||||
|
||||
HttpInterceptor func(http.Handler) http.Handler
|
||||
ServerInterceptor serverinterceptor
|
||||
HttpInterceptor func(http.Handler) http.Handler
|
||||
|
||||
// If supplied, the listener(s) returned from Listeners() will be TLS
|
||||
// listeners. The scheme used in the URLs returned from the gRPC server
|
||||
|
||||
@@ -465,7 +465,7 @@ func (c *Controller) RemoteSrvServerArgs(ctx *sql.Context, args remotesrv.Server
|
||||
args.HttpListenAddr = listenaddr
|
||||
args.GrpcListenAddr = listenaddr
|
||||
args.Options = c.ServerOptions()
|
||||
args = sqle.RemoteSrvServerArgs(ctx, args, nil)
|
||||
args = sqle.RemoteSrvServerArgs(ctx, args)
|
||||
args.DBCache = remotesrvStoreCache{args.DBCache, c}
|
||||
|
||||
keyID := creds.PubKeyToKID(c.pub)
|
||||
|
||||
@@ -60,14 +60,18 @@ func (s remotesrvStore) Get(path, nbfVerStr string) (remotesrv.RemoteSrvStore, e
|
||||
return rss, nil
|
||||
}
|
||||
|
||||
func RemoteSrvServerArgs(ctx *sql.Context, args remotesrv.ServerArgs, userAuth *remotesrv.UserAuth) remotesrv.ServerArgs {
|
||||
func RemoteSrvServerArgs(ctx *sql.Context, args remotesrv.ServerArgs) remotesrv.ServerArgs {
|
||||
sess := dsess.DSessFromSess(ctx.Session)
|
||||
args.FS = sess.Provider().FileSystem()
|
||||
args.DBCache = remotesrvStore{ctx, args.ReadOnly}
|
||||
if userAuth != nil {
|
||||
args.ServerInterceptor.Lgr = args.Logger
|
||||
args.ServerInterceptor.ExpectedUserAuth = *userAuth
|
||||
args.Options = append(args.Options, args.ServerInterceptor.Options()...)
|
||||
}
|
||||
return args
|
||||
}
|
||||
|
||||
func WithUserPasswordAuth(args remotesrv.ServerArgs, userAuth remotesrv.UserAuth) remotesrv.ServerArgs {
|
||||
si := remotesrv.ServerInterceptor{
|
||||
Lgr: args.Logger,
|
||||
ExpectedUserAuth: userAuth,
|
||||
}
|
||||
args.Options = append(args.Options, si.Options()...)
|
||||
return args
|
||||
}
|
||||
|
||||
@@ -212,3 +212,30 @@ SQL
|
||||
[[ "$status" != 0 ]] || false
|
||||
[[ "$output" =~ "Unauthenticated" ]] || false
|
||||
}
|
||||
|
||||
@test "sql-server-remotesrv: dolt clone with incorrect authentication errors" {
|
||||
mkdir remote
|
||||
cd remote
|
||||
dolt init
|
||||
dolt sql --privilege-file=privs.json -q "CREATE USER user0 IDENTIFIED BY 'pass0'"
|
||||
dolt sql -q 'create table vals (i int);'
|
||||
dolt sql -q 'insert into vals (i) values (1), (2), (3), (4), (5);'
|
||||
dolt add vals
|
||||
dolt commit -m 'initial vals.'
|
||||
export DOLT_REMOTE_USER="user0"
|
||||
export PASSWORD="pass0"
|
||||
|
||||
dolt sql-server -u $DOLT_REMOTE_USER -p $PASSWORD --remotesapi-port 50051 &
|
||||
srv_pid=$!
|
||||
|
||||
cd ../
|
||||
|
||||
run dolt clone http://localhost:50051/remote repo1 -u $DOLT_REMOTE_USER
|
||||
[[ "$status" != 0 ]] || false
|
||||
[[ "$output" =~ "must set DOLT_REMOTE_PASSWORD environment variable" ]] || false
|
||||
|
||||
export DOLT_REMOTE_PASSWORD="wrong-password"
|
||||
run dolt clone http://localhost:50051/remote repo1 -u $DOLT_REMOTE_USER
|
||||
[[ "$status" != 0 ]] || false
|
||||
[[ "$output" =~ "Unauthenticated" ]] || false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user