Shadow the password on cache and session config on admin panel (#7300)
* shadow the password on cache and session config on admin panel * add shadow password of mysql/postgres/couchbase * fix log import
This commit is contained in:
		
							parent
							
								
									42729b7562
								
							
						
					
					
						commit
						161e12e157
					
				
					 2 changed files with 135 additions and 2 deletions
				
			
		|  | @ -1,4 +1,5 @@ | ||||||
| // Copyright 2014 The Gogs Authors. All rights reserved.
 | // Copyright 2014 The Gogs Authors. All rights reserved.
 | ||||||
|  | // Copyright 2019 The Gitea Authors. All rights reserved.
 | ||||||
| // Use of this source code is governed by a MIT-style
 | // Use of this source code is governed by a MIT-style
 | ||||||
| // license that can be found in the LICENSE file.
 | // license that can be found in the LICENSE file.
 | ||||||
| 
 | 
 | ||||||
|  | @ -6,6 +7,7 @@ package admin | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"net/url" | ||||||
| 	"os" | 	"os" | ||||||
| 	"runtime" | 	"runtime" | ||||||
| 	"strings" | 	"strings" | ||||||
|  | @ -19,6 +21,7 @@ import ( | ||||||
| 	"code.gitea.io/gitea/modules/context" | 	"code.gitea.io/gitea/modules/context" | ||||||
| 	"code.gitea.io/gitea/modules/cron" | 	"code.gitea.io/gitea/modules/cron" | ||||||
| 	"code.gitea.io/gitea/modules/git" | 	"code.gitea.io/gitea/modules/git" | ||||||
|  | 	"code.gitea.io/gitea/modules/log" | ||||||
| 	"code.gitea.io/gitea/modules/process" | 	"code.gitea.io/gitea/modules/process" | ||||||
| 	"code.gitea.io/gitea/modules/setting" | 	"code.gitea.io/gitea/modules/setting" | ||||||
| ) | ) | ||||||
|  | @ -202,6 +205,63 @@ func SendTestMail(ctx *context.Context) { | ||||||
| 	ctx.Redirect(setting.AppSubURL + "/admin/config") | 	ctx.Redirect(setting.AppSubURL + "/admin/config") | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func shadownPasswordKV(cfgItem, splitter string) string { | ||||||
|  | 	fields := strings.Split(cfgItem, splitter) | ||||||
|  | 	for i := 0; i < len(fields); i++ { | ||||||
|  | 		if strings.HasPrefix(fields[i], "password=") { | ||||||
|  | 			fields[i] = "password=******" | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return strings.Join(fields, splitter) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func shadownURL(provider, cfgItem string) string { | ||||||
|  | 	u, err := url.Parse(cfgItem) | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Error("shodowPassword %v failed: %v", provider, err) | ||||||
|  | 		return cfgItem | ||||||
|  | 	} | ||||||
|  | 	if u.User != nil { | ||||||
|  | 		atIdx := strings.Index(cfgItem, "@") | ||||||
|  | 		if atIdx > 0 { | ||||||
|  | 			colonIdx := strings.LastIndex(cfgItem[:atIdx], ":") | ||||||
|  | 			if colonIdx > 0 { | ||||||
|  | 				return cfgItem[:colonIdx+1] + "******" + cfgItem[atIdx:] | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return cfgItem | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func shadowPassword(provider, cfgItem string) string { | ||||||
|  | 	switch provider { | ||||||
|  | 	case "redis": | ||||||
|  | 		return shadownPasswordKV(cfgItem, ",") | ||||||
|  | 	case "mysql": | ||||||
|  | 		//root:@tcp(localhost:3306)/macaron?charset=utf8
 | ||||||
|  | 		atIdx := strings.Index(cfgItem, "@") | ||||||
|  | 		if atIdx > 0 { | ||||||
|  | 			colonIdx := strings.Index(cfgItem[:atIdx], ":") | ||||||
|  | 			if colonIdx > 0 { | ||||||
|  | 				return cfgItem[:colonIdx+1] + "******" + cfgItem[atIdx:] | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		return cfgItem | ||||||
|  | 	case "postgres": | ||||||
|  | 		// user=jiahuachen dbname=macaron port=5432 sslmode=disable
 | ||||||
|  | 		if !strings.HasPrefix(cfgItem, "postgres://") { | ||||||
|  | 			return shadownPasswordKV(cfgItem, " ") | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		// postgres://pqgotest:password@localhost/pqgotest?sslmode=verify-full
 | ||||||
|  | 		// Notice: use shadwonURL
 | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// "couchbase"
 | ||||||
|  | 	return shadownURL(provider, cfgItem) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // Config show admin config page
 | // Config show admin config page
 | ||||||
| func Config(ctx *context.Context) { | func Config(ctx *context.Context) { | ||||||
| 	ctx.Data["Title"] = ctx.Tr("admin.config") | 	ctx.Data["Title"] = ctx.Tr("admin.config") | ||||||
|  | @ -239,10 +299,14 @@ func Config(ctx *context.Context) { | ||||||
| 
 | 
 | ||||||
| 	ctx.Data["CacheAdapter"] = setting.CacheService.Adapter | 	ctx.Data["CacheAdapter"] = setting.CacheService.Adapter | ||||||
| 	ctx.Data["CacheInterval"] = setting.CacheService.Interval | 	ctx.Data["CacheInterval"] = setting.CacheService.Interval | ||||||
| 	ctx.Data["CacheConn"] = setting.CacheService.Conn | 
 | ||||||
|  | 	ctx.Data["CacheConn"] = shadowPassword(setting.CacheService.Adapter, setting.CacheService.Conn) | ||||||
| 	ctx.Data["CacheItemTTL"] = setting.CacheService.TTL | 	ctx.Data["CacheItemTTL"] = setting.CacheService.TTL | ||||||
| 
 | 
 | ||||||
| 	ctx.Data["SessionConfig"] = setting.SessionConfig | 	sessionCfg := setting.SessionConfig | ||||||
|  | 	sessionCfg.ProviderConfig = shadowPassword(sessionCfg.Provider, sessionCfg.ProviderConfig) | ||||||
|  | 
 | ||||||
|  | 	ctx.Data["SessionConfig"] = sessionCfg | ||||||
| 
 | 
 | ||||||
| 	ctx.Data["DisableGravatar"] = setting.DisableGravatar | 	ctx.Data["DisableGravatar"] = setting.DisableGravatar | ||||||
| 	ctx.Data["EnableFederatedAvatar"] = setting.EnableFederatedAvatar | 	ctx.Data["EnableFederatedAvatar"] = setting.EnableFederatedAvatar | ||||||
|  |  | ||||||
							
								
								
									
										69
									
								
								routers/admin/admin_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								routers/admin/admin_test.go
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,69 @@ | ||||||
|  | // Copyright 2019 The Gitea Authors. All rights reserved.
 | ||||||
|  | // Use of this source code is governed by a MIT-style
 | ||||||
|  | // license that can be found in the LICENSE file.
 | ||||||
|  | 
 | ||||||
|  | package admin | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"testing" | ||||||
|  | 
 | ||||||
|  | 	"github.com/stretchr/testify/assert" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func TestShadowPassword(t *testing.T) { | ||||||
|  | 	var kases = []struct { | ||||||
|  | 		Provider string | ||||||
|  | 		CfgItem  string | ||||||
|  | 		Result   string | ||||||
|  | 	}{ | ||||||
|  | 		{ | ||||||
|  | 			Provider: "redis", | ||||||
|  | 			CfgItem:  "network=tcp,addr=:6379,password=gitea,db=0,pool_size=100,idle_timeout=180", | ||||||
|  | 			Result:   "network=tcp,addr=:6379,password=******,db=0,pool_size=100,idle_timeout=180", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			Provider: "mysql", | ||||||
|  | 			CfgItem:  "root:@tcp(localhost:3306)/gitea?charset=utf8", | ||||||
|  | 			Result:   "root:******@tcp(localhost:3306)/gitea?charset=utf8", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			Provider: "mysql", | ||||||
|  | 			CfgItem:  "/gitea?charset=utf8", | ||||||
|  | 			Result:   "/gitea?charset=utf8", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			Provider: "mysql", | ||||||
|  | 			CfgItem:  "user:mypassword@/dbname", | ||||||
|  | 			Result:   "user:******@/dbname", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			Provider: "postgres", | ||||||
|  | 			CfgItem:  "user=pqgotest dbname=pqgotest sslmode=verify-full", | ||||||
|  | 			Result:   "user=pqgotest dbname=pqgotest sslmode=verify-full", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			Provider: "postgres", | ||||||
|  | 			CfgItem:  "user=pqgotest password= dbname=pqgotest sslmode=verify-full", | ||||||
|  | 			Result:   "user=pqgotest password=****** dbname=pqgotest sslmode=verify-full", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			Provider: "postgres", | ||||||
|  | 			CfgItem:  "postgres://user:pass@hostname/dbname", | ||||||
|  | 			Result:   "postgres://user:******@hostname/dbname", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			Provider: "couchbase", | ||||||
|  | 			CfgItem:  "http://dev-couchbase.example.com:8091/", | ||||||
|  | 			Result:   "http://dev-couchbase.example.com:8091/", | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			Provider: "couchbase", | ||||||
|  | 			CfgItem:  "http://user:the_password@dev-couchbase.example.com:8091/", | ||||||
|  | 			Result:   "http://user:******@dev-couchbase.example.com:8091/", | ||||||
|  | 		}, | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	for _, k := range kases { | ||||||
|  | 		assert.EqualValues(t, k.Result, shadowPassword(k.Provider, k.CfgItem)) | ||||||
|  | 	} | ||||||
|  | } | ||||||
		Loading…
	
		Reference in a new issue