config data desensitization
Signed-off-by: hongming <talonwan@yunify.com>
This commit is contained in:
1
go.mod
1
go.mod
@@ -51,6 +51,7 @@ require (
|
|||||||
github.com/kubernetes-csi/external-snapshotter/v2 v2.1.0
|
github.com/kubernetes-csi/external-snapshotter/v2 v2.1.0
|
||||||
github.com/kubesphere/sonargo v0.0.2
|
github.com/kubesphere/sonargo v0.0.2
|
||||||
github.com/lib/pq v1.2.0 // indirect
|
github.com/lib/pq v1.2.0 // indirect
|
||||||
|
github.com/mitchellh/mapstructure v1.2.2
|
||||||
github.com/onsi/ginkgo v1.12.0
|
github.com/onsi/ginkgo v1.12.0
|
||||||
github.com/onsi/gomega v1.9.0
|
github.com/onsi/gomega v1.9.0
|
||||||
github.com/open-policy-agent/opa v0.18.0
|
github.com/open-policy-agent/opa v0.18.0
|
||||||
|
|||||||
@@ -17,9 +17,11 @@ limitations under the License.
|
|||||||
package oauth
|
package oauth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -74,8 +76,57 @@ type Options struct {
|
|||||||
AccessTokenInactivityTimeout time.Duration `json:"accessTokenInactivityTimeout" yaml:"accessTokenInactivityTimeout"`
|
AccessTokenInactivityTimeout time.Duration `json:"accessTokenInactivityTimeout" yaml:"accessTokenInactivityTimeout"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// the type of key must be string
|
||||||
type DynamicOptions map[string]interface{}
|
type DynamicOptions map[string]interface{}
|
||||||
|
|
||||||
|
func (o DynamicOptions) MarshalJSON() ([]byte, error) {
|
||||||
|
data, err := json.Marshal(desensitize(o))
|
||||||
|
return data, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
sensitiveKeys = [...]string{"password", "secret"}
|
||||||
|
)
|
||||||
|
|
||||||
|
// isSensitiveData returns whether the input string contains sensitive information
|
||||||
|
func isSensitiveData(key string) bool {
|
||||||
|
for _, v := range sensitiveKeys {
|
||||||
|
if strings.Contains(strings.ToLower(key), v) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// desensitize returns the desensitized data
|
||||||
|
func desensitize(data map[string]interface{}) map[string]interface{} {
|
||||||
|
output := make(map[string]interface{})
|
||||||
|
for k, v := range data {
|
||||||
|
if isSensitiveData(k) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
switch v.(type) {
|
||||||
|
case map[interface{}]interface{}:
|
||||||
|
output[k] = desensitize(convert(v.(map[interface{}]interface{})))
|
||||||
|
default:
|
||||||
|
output[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert returns formatted data
|
||||||
|
func convert(m map[interface{}]interface{}) map[string]interface{} {
|
||||||
|
output := make(map[string]interface{})
|
||||||
|
for k, v := range m {
|
||||||
|
switch k.(type) {
|
||||||
|
case string:
|
||||||
|
output[k.(string)] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output
|
||||||
|
}
|
||||||
|
|
||||||
type IdentityProviderOptions struct {
|
type IdentityProviderOptions struct {
|
||||||
// The provider name.
|
// The provider name.
|
||||||
Name string `json:"name" yaml:"name"`
|
Name string `json:"name" yaml:"name"`
|
||||||
|
|||||||
@@ -17,7 +17,9 @@ limitations under the License.
|
|||||||
package oauth
|
package oauth
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -101,3 +103,42 @@ func TestClientResolveRedirectURL(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDynamicOptions_MarshalJSON(t *testing.T) {
|
||||||
|
config := `
|
||||||
|
accessTokenMaxAge: 1h
|
||||||
|
accessTokenInactivityTimeout: 30m
|
||||||
|
identityProviders:
|
||||||
|
- name: ldap
|
||||||
|
type: LDAPIdentityProvider
|
||||||
|
mappingMethod: auto
|
||||||
|
provider:
|
||||||
|
host: xxxx.sn.mynetname.net:389
|
||||||
|
managerDN: uid=root,cn=users,dc=xxxx,dc=sn,dc=mynetname,dc=net
|
||||||
|
managerPassword: xxxx
|
||||||
|
userSearchBase: dc=xxxx,dc=sn,dc=mynetname,dc=net
|
||||||
|
loginAttribute: uid
|
||||||
|
mailAttribute: mail
|
||||||
|
- name: github
|
||||||
|
type: GitHubIdentityProvider
|
||||||
|
mappingMethod: mixed
|
||||||
|
provider:
|
||||||
|
clientID: 'xxxxxx'
|
||||||
|
clientSecret: 'xxxxxx'
|
||||||
|
endpoint:
|
||||||
|
authURL: 'https://github.com/login/oauth/authorize'
|
||||||
|
tokenURL: 'https://github.com/login/oauth/access_token'
|
||||||
|
redirectURL: 'https://ks-console/oauth/redirect'
|
||||||
|
scopes:
|
||||||
|
- user
|
||||||
|
`
|
||||||
|
var options Options
|
||||||
|
if err := yaml.Unmarshal([]byte(config), &options); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
expected := `{"identityProviders":[{"name":"ldap","mappingMethod":"auto","type":"LDAPIdentityProvider","provider":{"host":"xxxx.sn.mynetname.net:389","loginAttribute":"uid","mailAttribute":"mail","managerDN":"uid=root,cn=users,dc=xxxx,dc=sn,dc=mynetname,dc=net","userSearchBase":"dc=xxxx,dc=sn,dc=mynetname,dc=net"}},{"name":"github","mappingMethod":"mixed","type":"GitHubIdentityProvider","provider":{"clientID":"xxxxxx","endpoint":{"authURL":"https://github.com/login/oauth/authorize","tokenURL":"https://github.com/login/oauth/access_token"},"redirectURL":"https://ks-console/oauth/redirect","scopes":["user"]}}],"accessTokenMaxAge":3600000000000,"accessTokenInactivityTimeout":1800000000000}`
|
||||||
|
output, _ := json.Marshal(options)
|
||||||
|
if expected != string(output) {
|
||||||
|
t.Errorf("expected: %s, but got: %s", expected, output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -18,11 +18,7 @@ package v1alpha2
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/emicklei/go-restful"
|
"github.com/emicklei/go-restful"
|
||||||
"gopkg.in/yaml.v3"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/klog"
|
|
||||||
"kubesphere.io/kubesphere/pkg/api"
|
|
||||||
"kubesphere.io/kubesphere/pkg/apiserver/authentication/oauth"
|
|
||||||
kubesphereconfig "kubesphere.io/kubesphere/pkg/apiserver/config"
|
kubesphereconfig "kubesphere.io/kubesphere/pkg/apiserver/config"
|
||||||
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
|
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
|
||||||
)
|
)
|
||||||
@@ -39,20 +35,7 @@ func AddToContainer(c *restful.Container, config *kubesphereconfig.Config) error
|
|||||||
webservice.Route(webservice.GET("/configs/oauth").
|
webservice.Route(webservice.GET("/configs/oauth").
|
||||||
Doc("Information about the authorization server are published.").
|
Doc("Information about the authorization server are published.").
|
||||||
To(func(request *restful.Request, response *restful.Response) {
|
To(func(request *restful.Request, response *restful.Response) {
|
||||||
// workaround for this issue https://github.com/go-yaml/yaml/issues/139
|
response.WriteEntity(config.AuthenticationOptions.OAuthOptions)
|
||||||
// fixed in gopkg.in/yaml.v3
|
|
||||||
yamlData, err := yaml.Marshal(config.AuthenticationOptions.OAuthOptions)
|
|
||||||
if err != nil {
|
|
||||||
klog.Error(err)
|
|
||||||
api.HandleInternalError(response, request, err)
|
|
||||||
}
|
|
||||||
var options oauth.Options
|
|
||||||
err = yaml.Unmarshal(yamlData, &options)
|
|
||||||
if err != nil {
|
|
||||||
klog.Error(err)
|
|
||||||
api.HandleInternalError(response, request, err)
|
|
||||||
}
|
|
||||||
response.WriteEntity(options)
|
|
||||||
}))
|
}))
|
||||||
|
|
||||||
webservice.Route(webservice.GET("/configs/configz").
|
webservice.Route(webservice.GET("/configs/configz").
|
||||||
|
|||||||
Reference in New Issue
Block a user