api: redact password in responses (#6110)
passwords are not exposed anymore through the API. They can only be set, not read.
This commit is contained in:
@@ -20,6 +20,7 @@ import (
|
||||
|
||||
const (
|
||||
maxInboundConfigSize = 10 * 1024 * 1024
|
||||
redactedCredential = "<redacted>"
|
||||
)
|
||||
|
||||
func interfaceIsEmpty(i any) bool {
|
||||
@@ -47,6 +48,34 @@ func paramName(ctx *gin.Context) (string, bool) {
|
||||
return name[1:], true
|
||||
}
|
||||
|
||||
func redactCredentials(c *conf.Conf) *conf.Conf {
|
||||
c = c.Clone()
|
||||
|
||||
for i := range c.AuthInternalUsers {
|
||||
if c.AuthInternalUsers[i].Pass != "" {
|
||||
c.AuthInternalUsers[i].Pass = conf.Credential(redactedCredential)
|
||||
}
|
||||
}
|
||||
|
||||
if c.PathDefaults.PublishPass != nil && *c.PathDefaults.PublishPass != "" {
|
||||
*c.PathDefaults.PublishPass = conf.Credential(redactedCredential)
|
||||
}
|
||||
if c.PathDefaults.ReadPass != nil && *c.PathDefaults.ReadPass != "" {
|
||||
*c.PathDefaults.ReadPass = conf.Credential(redactedCredential)
|
||||
}
|
||||
|
||||
for _, pathConf := range c.Paths {
|
||||
if pathConf.PublishPass != nil && *pathConf.PublishPass != "" {
|
||||
*pathConf.PublishPass = conf.Credential(redactedCredential)
|
||||
}
|
||||
if pathConf.ReadPass != nil && *pathConf.ReadPass != "" {
|
||||
*pathConf.ReadPass = conf.Credential(redactedCredential)
|
||||
}
|
||||
}
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
type apiAuthManager interface {
|
||||
Authenticate(req *auth.Request) (string, *auth.Error)
|
||||
RefreshJWTJWKS()
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
)
|
||||
|
||||
func (a *API) onConfigGlobalGet(ctx *gin.Context) {
|
||||
c := a.Parent.APIConfigSnapshot()
|
||||
c := redactCredentials(a.Parent.APIConfigSnapshot())
|
||||
|
||||
ctx.JSON(http.StatusOK, c.Global())
|
||||
}
|
||||
|
||||
@@ -15,7 +15,12 @@ import (
|
||||
)
|
||||
|
||||
func TestConfigGlobalGet(t *testing.T) {
|
||||
cnf := tempConf(t, "api: yes\n")
|
||||
cnf := tempConf(t, "api: yes\n"+
|
||||
"authInternalUsers:\n"+
|
||||
" - user: myuser\n"+
|
||||
" pass: mypass\n"+
|
||||
" permissions:\n"+
|
||||
" - action: api\n")
|
||||
checked := false
|
||||
|
||||
api := API{
|
||||
@@ -45,6 +50,10 @@ func TestConfigGlobalGet(t *testing.T) {
|
||||
httpRequest(t, hc, http.MethodGet, "http://myuser:mypass@localhost:9997/v3/config/global/get", nil, &out)
|
||||
require.Equal(t, true, out["api"])
|
||||
|
||||
authInternalUsers := out["authInternalUsers"].([]any)
|
||||
require.Len(t, authInternalUsers, 1)
|
||||
require.Equal(t, redactedCredential, authInternalUsers[0].(map[string]any)["pass"])
|
||||
|
||||
require.True(t, checked)
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
)
|
||||
|
||||
func (a *API) onConfigPathDefaultsGet(ctx *gin.Context) {
|
||||
c := a.Parent.APIConfigSnapshot()
|
||||
c := redactCredentials(a.Parent.APIConfigSnapshot())
|
||||
|
||||
ctx.JSON(http.StatusOK, c.PathDefaults)
|
||||
}
|
||||
|
||||
@@ -12,7 +12,10 @@ import (
|
||||
)
|
||||
|
||||
func TestConfigPathDefaultsGet(t *testing.T) {
|
||||
cnf := tempConf(t, "api: yes\n")
|
||||
cnf := tempConf(t, "api: yes\n"+
|
||||
"pathDefaults:\n"+
|
||||
" readUser: myuser\n"+
|
||||
" readPass: mypass\n")
|
||||
|
||||
api := API{
|
||||
Address: "localhost:9997",
|
||||
@@ -32,6 +35,7 @@ func TestConfigPathDefaultsGet(t *testing.T) {
|
||||
var out map[string]any
|
||||
httpRequest(t, hc, http.MethodGet, "http://localhost:9997/v3/config/pathdefaults/get", nil, &out)
|
||||
require.Equal(t, "publisher", out["source"])
|
||||
require.Equal(t, redactedCredential, out["readPass"])
|
||||
}
|
||||
|
||||
func TestConfigPathDefaultsPatch(t *testing.T) {
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
)
|
||||
|
||||
func (a *API) onConfigPathsList(ctx *gin.Context) {
|
||||
c := a.Parent.APIConfigSnapshot()
|
||||
c := redactCredentials(a.Parent.APIConfigSnapshot())
|
||||
|
||||
data := &defs.APIPathConfList{
|
||||
Items: make([]conf.Path, len(c.Paths)),
|
||||
@@ -41,7 +41,7 @@ func (a *API) onConfigPathsGet(ctx *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
c := a.Parent.APIConfigSnapshot()
|
||||
c := redactCredentials(a.Parent.APIConfigSnapshot())
|
||||
|
||||
p, ok := c.Paths[confName]
|
||||
if !ok {
|
||||
|
||||
@@ -52,10 +52,10 @@ func TestConfigPathsList(t *testing.T) {
|
||||
require.Equal(t, 1, out.PageCount)
|
||||
require.Equal(t, "path1", out.Items[0]["name"])
|
||||
require.Equal(t, "myuser1", out.Items[0]["readUser"])
|
||||
require.Equal(t, "mypass1", out.Items[0]["readPass"])
|
||||
require.Equal(t, redactedCredential, out.Items[0]["readPass"])
|
||||
require.Equal(t, "path2", out.Items[1]["name"])
|
||||
require.Equal(t, "myuser2", out.Items[1]["readUser"])
|
||||
require.Equal(t, "mypass2", out.Items[1]["readPass"])
|
||||
require.Equal(t, redactedCredential, out.Items[1]["readPass"])
|
||||
}
|
||||
|
||||
func TestConfigPathsGet(t *testing.T) {
|
||||
@@ -84,6 +84,7 @@ func TestConfigPathsGet(t *testing.T) {
|
||||
httpRequest(t, hc, http.MethodGet, "http://localhost:9997/v3/config/paths/get/my/path", nil, &out)
|
||||
require.Equal(t, "my/path", out["name"])
|
||||
require.Equal(t, "myuser", out["readUser"])
|
||||
require.Equal(t, redactedCredential, out["readPass"])
|
||||
}
|
||||
|
||||
func TestConfigPathsAdd(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user