package auth import ( "crypto/tls" "github.com/gin-gonic/gin" "gitlink.org.cn/cloudream/common/pkgs/logger" "gitlink.org.cn/cloudream/jcs-pub/client/internal/http/types" "gitlink.org.cn/cloudream/jcs-pub/client/sdk/signer" "gitlink.org.cn/cloudream/jcs-pub/common/ecode" ) const ( ClientInternalSNI = "client.jcs-pub.internal" ) type Auth struct { cfg *types.Config } func New(cfg *types.Config) *Auth { return &Auth{ cfg: cfg, } } func (a *Auth) TLSConfigSelector(hello *tls.ClientHelloInfo) (*tls.Config, error) { switch hello.ServerName { case ClientInternalSNI: return &tls.Config{ Certificates: []tls.Certificate{a.cfg.ServerCert}, ClientAuth: tls.RequireAndVerifyClientCert, ClientCAs: a.cfg.RootCA, NextProtos: []string{"h2", "http/1.1"}, }, nil default: return &tls.Config{ Certificates: []tls.Certificate{a.cfg.ServerCert}, ClientAuth: tls.NoClientCert, NextProtos: []string{"h2", "http/1.1"}, }, nil } } func (a *Auth) RejectNoCertAuth(c *gin.Context) { if c.Request.TLS == nil || c.Request.TLS.ServerName != ClientInternalSNI { c.AbortWithStatusJSON(401, types.Failed(ecode.Unauthorized, "must provide client certificate")) return } c.Next() } func (a *Auth) Presigned(c *gin.Context) { log := logger.WithField("HTTP", "Auth") accID := signer.GetAccessKeyID(c.Request.URL) if accID == "" { log.Warn("access key id not found in query string") c.AbortWithStatusJSON(401, types.Failed(ecode.Unauthorized, "access key id not found in query string")) return } cliCert := a.cfg.ClientCerts[accID] if cliCert == nil { log.Warnf("client cert not found for access key id %s", accID) c.AbortWithStatusJSON(401, types.Failed(ecode.Unauthorized, "client cert not found for access key id %s", accID)) return } err := signer.VerifyPresigned(cliCert.VerifyKey, c.Request.Method, c.Request.URL) if err != nil { log.Warn(err.Error()) c.AbortWithStatusJSON(401, types.Failed(ecode.Unauthorized, err.Error())) return } c.Next() }