diff --git a/cmd/drone-server/config/config.go b/cmd/drone-server/config/config.go index 94f52ad47..eae1f9fc5 100644 --- a/cmd/drone-server/config/config.go +++ b/cmd/drone-server/config/config.go @@ -275,10 +275,9 @@ type ( // Session provides the session configuration. Session struct { - Timeout time.Duration `envconfig:"DRONE_COOKIE_TIMEOUT" default:"720h"` - Secret string `envconfig:"DRONE_COOKIE_SECRET"` - Secure bool `envconfig:"DRONE_COOKIE_SECURE"` - MappingFile string `envconfig:"DRONE_LEGACY_TOKEN_MAPPING_FILE"` + Timeout time.Duration `envconfig:"DRONE_COOKIE_TIMEOUT" default:"720h"` + Secret string `envconfig:"DRONE_COOKIE_SECRET"` + Secure bool `envconfig:"DRONE_COOKIE_SECURE"` } // Status provides status configurations. diff --git a/cmd/drone-server/inject_service.go b/cmd/drone-server/inject_service.go index ceb47cd8e..f844c892f 100644 --- a/cmd/drone-server/inject_service.go +++ b/cmd/drone-server/inject_service.go @@ -120,15 +120,6 @@ func provideRepositoryService(client *scm.Client, renewer core.Renewer, config c // provideSession is a Wire provider function that returns a // user session based on the environment configuration. func provideSession(store core.UserStore, config config.Config) (core.Session, error) { - if config.Session.MappingFile != "" { - return session.Legacy(store, session.Config{ - Secure: config.Session.Secure, - Secret: config.Session.Secret, - Timeout: config.Session.Timeout, - MappingFile: config.Session.MappingFile, - }) - } - return session.New(store, session.NewConfig( config.Session.Secret, config.Session.Timeout, diff --git a/go.mod b/go.mod index 157301100..d7bf0ed71 100644 --- a/go.mod +++ b/go.mod @@ -12,13 +12,12 @@ require ( github.com/coreos/go-semver v0.2.0 github.com/dchest/authcookie v0.0.0-20120917135355-fbdef6e99866 github.com/dchest/uniuri v0.0.0-20160212164326-8902c56451e9 - github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/drone/drone-go v1.4.1-0.20201109202657-b9e58bbbcf27 github.com/drone/drone-runtime v1.1.1-0.20200623162453-61e33e2cab5d github.com/drone/drone-ui v2.0.1+incompatible github.com/drone/drone-yaml v1.2.4-0.20200326192514-6f4d6dfb39e4 github.com/drone/envsubst v1.0.3-0.20200709231038-aa43e1c1a629 - github.com/drone/funcmap v0.0.0-20210823160631-9e9dec149056 // indirect + github.com/drone/funcmap v0.0.0-20210823160631-9e9dec149056 github.com/drone/go-license v1.0.2 github.com/drone/go-login v1.0.4-0.20190311170324-2a4df4f242a2 github.com/drone/go-scm v1.15.2 diff --git a/go.sum b/go.sum index 60801fd5b..5f65e0b7d 100644 --- a/go.sum +++ b/go.sum @@ -78,16 +78,12 @@ github.com/drone/drone-go v1.4.1-0.20201109202657-b9e58bbbcf27/go.mod h1:fxCf9jA github.com/drone/drone-runtime v1.0.7-0.20190729202838-87c84080f4a1/go.mod h1:+osgwGADc/nyl40J0fdsf8Z09bgcBZXvXXnLOY48zYs= github.com/drone/drone-runtime v1.1.1-0.20200623162453-61e33e2cab5d h1:P5HI/Y9hARTZ3F3EKs0kYijhjXZWQRQHYn1neTi0pWM= github.com/drone/drone-runtime v1.1.1-0.20200623162453-61e33e2cab5d/go.mod h1:4/2QToW5+HGD0y1sTw7X35W1f7YINS14UfDY4isggT8= -github.com/drone/drone-ui v0.0.0-20210812155550-12795bc368b3 h1:03iiv5fPLbTpz5Xh0w/Agc4p9UBub+bNFgIhIV6rwVU= -github.com/drone/drone-ui v0.0.0-20210812155550-12795bc368b3/go.mod h1:NBtVWW7NNJpD9+huMD/5TAE1db2nrEh0i35/9Rf1MPI= github.com/drone/drone-ui v2.0.1+incompatible h1:p+cFE2xB5zlQKaEDWXNe2SGzbzyy0oAcmQE2oe8h/xw= github.com/drone/drone-ui v2.0.1+incompatible/go.mod h1:NBtVWW7NNJpD9+huMD/5TAE1db2nrEh0i35/9Rf1MPI= github.com/drone/drone-yaml v1.2.4-0.20200326192514-6f4d6dfb39e4 h1:XsstoCeXC2t8lA9OLTdoFwckaptqahxwjCWsenySfX8= github.com/drone/drone-yaml v1.2.4-0.20200326192514-6f4d6dfb39e4/go.mod h1:QsqliFK8nG04AHFN9tTn9XJomRBQHD4wcejWW1uz/10= github.com/drone/envsubst v1.0.3-0.20200709231038-aa43e1c1a629 h1:rIaZZalMGGPb2cU/+ypuggZ8aMlpa17RUlJUtsMv8pw= github.com/drone/envsubst v1.0.3-0.20200709231038-aa43e1c1a629/go.mod h1:N2jZmlMufstn1KEqvbHjw40h1KyTmnVzHcSc9bFiJ2g= -github.com/drone/funcmap v0.0.0-20190918184546-d4ef6e88376d h1:/IO7UVVu191Jc0DajV4cDVoO+91cuppvgxg2MZl+AXI= -github.com/drone/funcmap v0.0.0-20190918184546-d4ef6e88376d/go.mod h1:Hph0/pT6ZxbujnE1Z6/08p5I0XXuOsppqF6NQlGOK0E= github.com/drone/funcmap v0.0.0-20210823160631-9e9dec149056 h1:SCJwMR0FMA0aKwAntCBh02YmtHEnU40zaDzeeCvIRug= github.com/drone/funcmap v0.0.0-20210823160631-9e9dec149056/go.mod h1:Hph0/pT6ZxbujnE1Z6/08p5I0XXuOsppqF6NQlGOK0E= github.com/drone/go-license v1.0.2 h1:7OwndfYk+Lp/cGHkxe4HUn/Ysrrw3WYH2pnd99yrkok= diff --git a/session/config.go b/session/config.go index 08a580cd0..bb7191e03 100644 --- a/session/config.go +++ b/session/config.go @@ -18,10 +18,9 @@ import "time" // Config provides the session configuration. type Config struct { - Secure bool - Secret string - Timeout time.Duration - MappingFile string + Secure bool + Secret string + Timeout time.Duration } // NewConfig returns a new session configuration. diff --git a/session/legacy.go b/session/legacy.go deleted file mode 100644 index 77f58accf..000000000 --- a/session/legacy.go +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright 2019 Drone IO, 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 session - -import ( - "encoding/json" - "errors" - "io/ioutil" - "net/http" - - "github.com/drone/drone/core" - - "github.com/dgrijalva/jwt-go" -) - -type legacy struct { - *session - mapping map[string]string -} - -// Legacy returns a session manager that is capable of mapping -// legacy tokens to 1.0 users using a mapping file. -func Legacy(users core.UserStore, config Config) (core.Session, error) { - base := &session{ - secret: []byte(config.Secret), - secure: config.Secure, - timeout: config.Timeout, - users: users, - } - out, err := ioutil.ReadFile(config.MappingFile) - if err != nil { - return nil, err - } - mapping := map[string]string{} - err = json.Unmarshal(out, &mapping) - if err != nil { - return nil, err - } - return &legacy{base, mapping}, nil -} - -func (s *legacy) Get(r *http.Request) (*core.User, error) { - switch { - case isAuthorizationToken(r): - return s.fromToken(r) - case isAuthorizationParameter(r): - return s.fromToken(r) - default: - return s.fromSession(r) - } -} - -func (s *legacy) fromToken(r *http.Request) (*core.User, error) { - extracted := extractToken(r) - - // determine if the token is a legacy token based on length. - // legacy tokens are > 64 characters. - if len(extracted) < 64 { - return s.users.FindToken(r.Context(), extracted) - } - - token, err := jwt.Parse(extracted, func(token *jwt.Token) (interface{}, error) { - // validate the signing method - _, ok := token.Method.(*jwt.SigningMethodHMAC) - if !ok { - return nil, errors.New("Legacy token: invalid signature") - } - - claims, ok := token.Claims.(jwt.MapClaims) - if !ok { - return nil, errors.New("Legacy token: invalid claim format") - } - - // extract the username claim - claim, ok := claims["text"] - if !ok { - return nil, errors.New("Legacy token: invalid format") - } - - // lookup the username to get the secret - secret, ok := s.mapping[claim.(string)] - if !ok { - return nil, errors.New("Legacy token: cannot lookup user") - } - return []byte(secret), nil - }) - if err != nil { - return nil, err - } - - return s.users.FindLogin( - r.Context(), - token.Claims.(jwt.MapClaims)["text"].(string), - ) -} - diff --git a/session/legacy_test.go b/session/legacy_test.go deleted file mode 100644 index 42d920b84..000000000 --- a/session/legacy_test.go +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2019 Drone.IO Inc. All rights reserved. -// Use of this source code is governed by the Drone Non-Commercial License -// that can be found in the LICENSE file. - -// +build !oss - -package session - -import ( - "net/http/httptest" - "testing" - "time" - - "github.com/drone/drone/core" - "github.com/drone/drone/mock" - "github.com/golang/mock/gomock" -) - -func TestLegacyGet_NotLegacy(t *testing.T) { - controller := gomock.NewController(t) - defer controller.Finish() - - mockUser := &core.User{ - Login: "octocat", - Hash: "ulSxuA0FKjNiOFIchk18NNvC6ygSxdtKjiOAS", - } - - users := mock.NewMockUserStore(controller) - users.EXPECT().FindToken(gomock.Any(), mockUser.Hash).Return(mockUser, nil) - - r := httptest.NewRequest("GET", "/", nil) - r.Header.Set("Authorization", "Bearer ulSxuA0FKjNiOFIchk18NNvC6ygSxdtKjiOAS") - - session, _ := Legacy(users, Config{Secure: false, Timeout: time.Hour, MappingFile: "testdata/mapping.json"}) - user, _ := session.Get(r) - if user != mockUser { - t.Errorf("Want authenticated user") - } -} - -func TestLegacyGet(t *testing.T) { - controller := gomock.NewController(t) - defer controller.Finish() - - mockUser := &core.User{ - Login: "octocat", - Hash: "ulSxuA0FKjNiOFIchk18NNvC6ygSxdtKjiOAS", - } - - users := mock.NewMockUserStore(controller) - users.EXPECT().FindLogin(gomock.Any(), gomock.Any()).Return(mockUser, nil) - r := httptest.NewRequest("GET", "/?access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwidGV4dCI6Im9jdG9jYXQiLCJpYXQiOjE1MTYyMzkwMjJ9.jf17GpOuKu-KAhuvxtjVvmZfwyeC7mEpKNiM6_cGOvo", nil) - - session, _ := Legacy(users, Config{Secure: false, Timeout: time.Hour, MappingFile: "testdata/mapping.json"}) - user, err := session.Get(r) - if err != nil { - t.Error(err) - return - } - if user != mockUser { - t.Errorf("Want authenticated user") - } -} - -func TestLegacyGet_UserNotFound(t *testing.T) { - controller := gomock.NewController(t) - defer controller.Finish() - - users := mock.NewMockUserStore(controller) - r := httptest.NewRequest("GET", "/?access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwidGV4dCI6ImJpbGx5aWRvbCIsImlhdCI6MTUxNjIzOTAyMn0.yxTCucstDM7BaixXBMAJCXup9zBaFr02Kalv_PqCDM4", nil) - - session, _ := Legacy(users, Config{Secure: false, Timeout: time.Hour, MappingFile: "testdata/mapping.json"}) - _, err := session.Get(r) - if err == nil || err.Error() != "Legacy token: cannot lookup user" { - t.Errorf("Expect user lookup error, got %v", err) - return - } -} - -func TestLegacyGet_InvalidSignature(t *testing.T) { - controller := gomock.NewController(t) - defer controller.Finish() - - users := mock.NewMockUserStore(controller) - r := httptest.NewRequest("GET", "/?access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwidGV4dCI6InNwYWNlZ2hvc3QiLCJpYXQiOjE1MTYyMzkwMjJ9.jlGcn2WI_oEZyLqYrvNvDXNbG3H3rqMyqQI2Gc6CHIY", nil) - - session, _ := Legacy(users, Config{Secure: false, Timeout: time.Hour, MappingFile: "testdata/mapping.json"}) - _, err := session.Get(r) - if err == nil || err.Error() != "signature is invalid" { - t.Errorf("Expect user lookup error, got %v", err) - return - } -}