...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package gcp
17
18 import (
19 "net/http"
20 "net/url"
21 "path"
22
23 "github.com/gin-gonic/gin"
24 "github.com/go-logr/logr"
25 "golang.org/x/oauth2"
26 "golang.org/x/oauth2/google"
27
28 config "github.com/chaos-mesh/chaos-mesh/pkg/config"
29 "github.com/chaos-mesh/chaos-mesh/pkg/dashboard/apiserver/utils"
30 )
31
32 type Service struct {
33 clientId string
34 clientSecret string
35 rootUrl *url.URL
36 logger logr.Logger
37 }
38
39
40 func NewService(
41 conf *config.ChaosDashboardConfig,
42 logger logr.Logger,
43 ) (*Service, error) {
44 rootUrl, err := url.Parse(conf.RootUrl)
45 if err != nil {
46 return nil, err
47 }
48 if rootUrl.Path == "" {
49 rootUrl.Path = "/"
50 }
51
52 return &Service{
53 clientId: conf.GcpClientId,
54 clientSecret: conf.GcpClientSecret,
55 rootUrl: rootUrl,
56 logger: logger.WithName("gcp auth api"),
57 }, nil
58 }
59
60
61 func Register(r *gin.RouterGroup, s *Service, conf *config.ChaosDashboardConfig) {
62
63 if !conf.GcpSecurityMode {
64 return
65 }
66
67 r.Use(s.Middleware)
68
69 endpoint := r.Group("/auth/gcp")
70 endpoint.GET("/redirect", s.handleRedirect)
71 endpoint.GET("/callback", s.authCallback)
72 }
73
74 func (s *Service) getOauthConfig(c *gin.Context) oauth2.Config {
75 url := *s.rootUrl
76 url.Path = path.Join(s.rootUrl.Path, "./api/auth/gcp/callback")
77
78 return oauth2.Config{
79 ClientID: s.clientId,
80 ClientSecret: s.clientSecret,
81 RedirectURL: url.String(),
82 Scopes: []string{
83 "email", "profile",
84 "https://www.googleapis.com/auth/userinfo.email",
85 "https://www.googleapis.com/auth/compute",
86 "https://www.googleapis.com/auth/cloud-platform",
87 },
88 Endpoint: google.Endpoint,
89 }
90 }
91
92 func (s *Service) handleRedirect(c *gin.Context) {
93 oauth := s.getOauthConfig(c)
94 uri := oauth.AuthCodeURL("", oauth2.AccessTypeOffline, oauth2.ApprovalForce)
95
96 c.Redirect(http.StatusFound, uri)
97 }
98
99 func (s *Service) authCallback(c *gin.Context) {
100 ctx := c.Request.Context()
101
102 oauth := s.getOauthConfig(c)
103 oauth2Token, err := oauth.Exchange(ctx, c.Request.URL.Query().Get("code"), oauth2.AccessTypeOffline, oauth2.ApprovalForce)
104 if err != nil {
105 utils.SetAPIError(c, utils.ErrInternalServer.WrapWithNoMessage(err))
106 return
107 }
108
109 setCookie(c, oauth2Token)
110 target := url.URL{
111 Path: "/",
112 }
113 c.Redirect(http.StatusFound, target.RequestURI())
114 }
115