From cea31b050339842cc30b5fea544669ccd1afddec Mon Sep 17 00:00:00 2001 From: Ti Chi Robot Date: Thu, 7 Nov 2024 14:02:22 +0800 Subject: [PATCH] *: add share code revoke api; add a config to allow disabling custom prom addr (#1717) (#1752) * user: add share code revoke api Signed-off-by: mornyx * *: add a config to allow disabling custom prom addr Signed-off-by: mornyx * fix lint Signed-off-by: mornyx --------- Signed-off-by: mornyx Co-authored-by: mornyx Co-authored-by: Sparkle <1284531+baurine@users.noreply.github.com> Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com> --- cmd/tidb-dashboard/main.go | 1 + pkg/apiserver/metrics/router.go | 4 ++++ pkg/apiserver/metrics/service.go | 2 ++ pkg/apiserver/user/code/router.go | 11 ++++++++++ pkg/apiserver/user/code/service.go | 16 ++++++++++++-- pkg/config/config.go | 34 ++++++++++++++++-------------- 6 files changed, 50 insertions(+), 18 deletions(-) diff --git a/cmd/tidb-dashboard/main.go b/cmd/tidb-dashboard/main.go index a302cb90cc..0e0e6fa44b 100755 --- a/cmd/tidb-dashboard/main.go +++ b/cmd/tidb-dashboard/main.go @@ -70,6 +70,7 @@ func NewCLIConfig() *DashboardCLIConfig { flag.StringVar(&cfg.CoreConfig.FeatureVersion, "feature-version", cfg.CoreConfig.FeatureVersion, "target TiDB version for standalone mode") flag.IntVar(&cfg.CoreConfig.NgmTimeout, "ngm-timeout", cfg.CoreConfig.NgmTimeout, "timeout secs for accessing the ngm API") flag.BoolVar(&cfg.CoreConfig.EnableKeyVisualizer, "keyviz", true, "enable/disable key visualizer(default: true)") + flag.BoolVar(&cfg.CoreConfig.DisableCustomPromAddr, "disable-custom-prom-addr", false, "do not allow custom prometheus address") showVersion := flag.BoolP("version", "v", false, "print version information and exit") diff --git a/pkg/apiserver/metrics/router.go b/pkg/apiserver/metrics/router.go index 847a154edf..5b21e880cc 100644 --- a/pkg/apiserver/metrics/router.go +++ b/pkg/apiserver/metrics/router.go @@ -142,6 +142,10 @@ func (s *Service) putCustomPromAddress(c *gin.Context) { rest.Error(c, rest.ErrBadRequest.NewWithNoMessage()) return } + if s.params.Config.DisableCustomPromAddr && req.Addr != "" { + rest.Error(c, rest.ErrForbidden.New("custom prometheus address has been disabled")) + return + } addr, err := s.setCustomPromAddress(req.Addr) if err != nil { rest.Error(c, err) diff --git a/pkg/apiserver/metrics/service.go b/pkg/apiserver/metrics/service.go index c85593c863..69aae861d6 100644 --- a/pkg/apiserver/metrics/service.go +++ b/pkg/apiserver/metrics/service.go @@ -12,6 +12,7 @@ import ( "go.uber.org/fx" "golang.org/x/sync/singleflight" + "github.com/pingcap/tidb-dashboard/pkg/config" "github.com/pingcap/tidb-dashboard/pkg/httpc" "github.com/pingcap/tidb-dashboard/pkg/pd" ) @@ -29,6 +30,7 @@ const ( type ServiceParams struct { fx.In + Config *config.Config HTTPClient *httpc.Client EtcdClient *clientv3.Client PDClient *pd.Client diff --git a/pkg/apiserver/user/code/router.go b/pkg/apiserver/user/code/router.go index b2d0967d6e..4d5895eab8 100644 --- a/pkg/apiserver/user/code/router.go +++ b/pkg/apiserver/user/code/router.go @@ -17,6 +17,7 @@ func registerRouter(r *gin.RouterGroup, auth *user.AuthService, s *Service) { endpoint := r.Group("/user/share") endpoint.Use(auth.MWAuthRequired()) endpoint.POST("/code", auth.MWRequireSharePriv(), s.ShareHandler) + endpoint.POST("/revoke", auth.MWRequireSharePriv(), s.RevokeHandler) } type ShareRequest struct { @@ -57,3 +58,13 @@ func (s *Service) ShareHandler(c *gin.Context) { c.JSON(http.StatusOK, ShareResponse{Code: *code}) } + +// @ID userRevokeSession +// @Summary Reset encryption key to revoke all authorized codes +// @Security JwtAuth +// @Success 200 +// @Router /user/share/revoke [post] +func (s *Service) RevokeHandler(c *gin.Context) { + s.ResetEncryptionKey() + c.JSON(http.StatusOK, nil) +} diff --git a/pkg/apiserver/user/code/service.go b/pkg/apiserver/user/code/service.go index 5d46ef4c88..c74e8a8dbd 100644 --- a/pkg/apiserver/user/code/service.go +++ b/pkg/apiserver/user/code/service.go @@ -5,7 +5,9 @@ package code import ( "encoding/hex" "fmt" + "sync/atomic" "time" + "unsafe" "github.com/gtank/cryptopasta" "github.com/joomcode/errorx" @@ -52,7 +54,7 @@ func (s *Service) NewSessionFromSharingCode(codeInHex string) *utils.SessionUser return nil } - b, err := cryptopasta.Decrypt(encrypted, s.sharingSecret) + b, err := cryptopasta.Decrypt(encrypted, s.loadShareingSecret()) if err != nil { return nil } @@ -99,7 +101,7 @@ func (s *Service) SharingCodeFromSession(session *utils.SessionUser, expireIn ti return nil } - encrypted, err := cryptopasta.Encrypt(b, s.sharingSecret) + encrypted, err := cryptopasta.Encrypt(b, s.loadShareingSecret()) if err != nil { return nil } @@ -107,3 +109,13 @@ func (s *Service) SharingCodeFromSession(session *utils.SessionUser, expireIn ti codeInHex := hex.EncodeToString(encrypted) return &codeInHex } + +func (s *Service) ResetEncryptionKey() { + //nolint:gosec // Using unsafe is necessary because atomic pointer operations are required. + atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&s.sharingSecret)), unsafe.Pointer(cryptopasta.NewEncryptionKey())) +} + +func (s *Service) loadShareingSecret() *[32]byte { + //nolint:gosec // Using unsafe is necessary because atomic pointer operations are required. + return (*[32]byte)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&s.sharingSecret)))) +} diff --git a/pkg/config/config.go b/pkg/config/config.go index fc3f6274ed..9f645676f8 100755 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -30,28 +30,30 @@ type Config struct { ClusterTLSInfo *transport.TLSInfo // TLS info for mTLS authentication between TiDB components. TiDBTLSConfig *tls.Config // TLS config for mTLS authentication between TiDB and MySQL client. - EnableTelemetry bool - EnableExperimental bool - EnableKeyVisualizer bool - FeatureVersion string // assign the target TiDB version when running TiDB Dashboard as standalone mode + EnableTelemetry bool + EnableExperimental bool + EnableKeyVisualizer bool + DisableCustomPromAddr bool + FeatureVersion string // assign the target TiDB version when running TiDB Dashboard as standalone mode NgmTimeout int // in seconds } func Default() *Config { return &Config{ - DataDir: "/tmp/dashboard-data", - TempDir: "", - PDEndPoint: "http://127.0.0.1:2379", - PublicPathPrefix: defaultPublicPathPrefix, - ClusterTLSConfig: nil, - ClusterTLSInfo: nil, - TiDBTLSConfig: nil, - EnableTelemetry: false, - EnableExperimental: false, - EnableKeyVisualizer: true, - FeatureVersion: version.PDVersion, - NgmTimeout: 30, // s + DataDir: "/tmp/dashboard-data", + TempDir: "", + PDEndPoint: "http://127.0.0.1:2379", + PublicPathPrefix: defaultPublicPathPrefix, + ClusterTLSConfig: nil, + ClusterTLSInfo: nil, + TiDBTLSConfig: nil, + EnableTelemetry: false, + EnableExperimental: false, + EnableKeyVisualizer: true, + DisableCustomPromAddr: false, + FeatureVersion: version.PDVersion, + NgmTimeout: 30, // s } }