You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

auth.go 2.4 kB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. package auth
  2. import (
  3. "crypto/tls"
  4. "github.com/gin-gonic/gin"
  5. "gitlink.org.cn/cloudream/common/pkgs/logger"
  6. "gitlink.org.cn/cloudream/jcs-pub/client/internal/http/types"
  7. "gitlink.org.cn/cloudream/jcs-pub/client/sdk/signer"
  8. "gitlink.org.cn/cloudream/jcs-pub/common/ecode"
  9. )
  10. type ClusterProxyRequestKey string
  11. const (
  12. ClientInternalSNI = "client.jcs-pub.internal"
  13. ClusterProxyRequest ClusterProxyRequestKey = "ClusterProxyRequest"
  14. )
  15. type Auth struct {
  16. cfg *types.Config
  17. }
  18. func New(cfg *types.Config) *Auth {
  19. return &Auth{
  20. cfg: cfg,
  21. }
  22. }
  23. func (a *Auth) TLSConfigSelector(hello *tls.ClientHelloInfo) (*tls.Config, error) {
  24. switch hello.ServerName {
  25. case ClientInternalSNI:
  26. return &tls.Config{
  27. Certificates: []tls.Certificate{a.cfg.ServerCert},
  28. ClientAuth: tls.RequireAndVerifyClientCert,
  29. ClientCAs: a.cfg.RootCA,
  30. NextProtos: []string{"h2", "http/1.1"},
  31. }, nil
  32. default:
  33. return &tls.Config{
  34. Certificates: []tls.Certificate{a.cfg.ServerCert},
  35. ClientAuth: tls.NoClientCert,
  36. NextProtos: []string{"h2", "http/1.1"},
  37. }, nil
  38. }
  39. }
  40. func (a *Auth) RejectNoCertAuth(c *gin.Context) {
  41. if c.Request.Context().Value(ClusterProxyRequest) != nil {
  42. c.Next()
  43. return
  44. }
  45. if c.Request.TLS == nil || c.Request.TLS.ServerName != ClientInternalSNI {
  46. c.AbortWithStatusJSON(401, types.Failed(ecode.Unauthorized, "must provide client certificate"))
  47. return
  48. }
  49. c.Next()
  50. }
  51. func (a *Auth) Presigned(c *gin.Context) {
  52. log := logger.WithField("HTTP", "Auth")
  53. if c.Request.Context().Value(ClusterProxyRequest) != nil {
  54. c.Next()
  55. return
  56. }
  57. accID := signer.GetAccessKeyID(c.Request.URL)
  58. if accID == "" {
  59. log.Warn("access key id not found in query string")
  60. c.AbortWithStatusJSON(401, types.Failed(ecode.Unauthorized, "access key id not found in query string"))
  61. return
  62. }
  63. cliCert := a.cfg.ClientCerts[accID]
  64. if cliCert == nil {
  65. log.Warnf("client cert not found for access key id %s", accID)
  66. c.AbortWithStatusJSON(401, types.Failed(ecode.Unauthorized, "client cert not found for access key id %s", accID))
  67. return
  68. }
  69. c.Request.URL.Host = c.Request.Host
  70. err := signer.VerifyPresigned(cliCert.VerifyKey, c.Request.Method, c.Request.URL)
  71. if err != nil {
  72. log.Warn(err.Error())
  73. c.AbortWithStatusJSON(401, types.Failed(ecode.Unauthorized, err.Error()))
  74. return
  75. }
  76. c.Next()
  77. }

本项目旨在将云际存储公共基础设施化,使个人及企业可低门槛使用高效的云际存储服务(安装开箱即用云际存储客户端即可,无需关注其他组件的部署),同时支持用户灵活便捷定制云际存储的功能细节。