From b40104b74c530b4f5554230a37b187686dbb9216 Mon Sep 17 00:00:00 2001 From: RoyUP9 <87927115+RoyUP9@users.noreply.github.com> Date: Wed, 13 Oct 2021 11:48:42 +0300 Subject: [PATCH] changed sync entries to start on startup (#344) --- agent/go.sum | 2 + agent/main.go | 23 ++++++ agent/pkg/controllers/entries_controller.go | 54 -------------- agent/pkg/models/models.go | 12 ++- agent/pkg/providers/auth_provider.go | 29 ------- agent/pkg/providers/status_provider.go | 38 ++++++++++ agent/pkg/routes/entries_routes.go | 1 - agent/pkg/up9/main.go | 83 +++++++++++++++------ cli/apiserver/provider.go | 22 ------ cli/auth/authProvider.go | 35 --------- cli/cmd/tap.go | 3 +- cli/cmd/tapRunner.go | 47 ++++-------- cli/go.mod | 1 - cli/kubernetes/provider.go | 15 ++-- shared/consts.go | 2 +- shared/go.mod | 2 +- shared/go.sum | 4 +- shared/models.go | 8 +- shared/tokenUtils.go | 41 ++++++++++ 19 files changed, 201 insertions(+), 221 deletions(-) delete mode 100644 agent/pkg/providers/auth_provider.go create mode 100644 shared/tokenUtils.go diff --git a/agent/go.sum b/agent/go.sum index c49e1f152..75977af59 100644 --- a/agent/go.sum +++ b/agent/go.sum @@ -125,6 +125,8 @@ github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/V github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt/v4 v4.1.0 h1:XUgk2Ex5veyVFVeLm0xhusUTQybEbexJXrvPNOKkSY0= +github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= diff --git a/agent/main.go b/agent/main.go index 53ae74fa7..d3ef37458 100644 --- a/agent/main.go +++ b/agent/main.go @@ -17,6 +17,7 @@ import ( "mizuserver/pkg/controllers" "mizuserver/pkg/models" "mizuserver/pkg/routes" + "mizuserver/pkg/up9" "mizuserver/pkg/utils" "net/http" "os" @@ -91,6 +92,13 @@ func main() { go filterItems(outputItemsChannel, filteredOutputItemsChannel) go api.StartReadingEntries(filteredOutputItemsChannel, nil, extensionsMap) + syncEntriesConfig := getSyncEntriesConfig() + if syncEntriesConfig != nil { + if err := up9.SyncEntries(syncEntriesConfig); err != nil { + panic(fmt.Sprintf("Error syncing entries, err: %v", err)) + } + } + hostApi(outputItemsChannel) } else if *harsReaderMode { outputItemsChannel := make(chan *tapApi.OutputChannelItem, 1000) @@ -275,3 +283,18 @@ func pipeTapChannelToSocket(connection *websocket.Conn, messageDataChannel <-cha } } } + +func getSyncEntriesConfig() *shared.SyncEntriesConfig { + syncEntriesConfigJson := os.Getenv(shared.SyncEntriesConfigEnvVar) + if syncEntriesConfigJson == "" { + return nil + } + + var syncEntriesConfig = &shared.SyncEntriesConfig{} + err := json.Unmarshal([]byte(syncEntriesConfigJson), syncEntriesConfig) + if err != nil { + panic(fmt.Sprintf("env var %s's value of %s is invalid! json must match the shared.SyncEntriesConfig struct, err: %v", shared.SyncEntriesConfigEnvVar, syncEntriesConfigJson, err)) + } + + return syncEntriesConfig +} diff --git a/agent/pkg/controllers/entries_controller.go b/agent/pkg/controllers/entries_controller.go index 3d2f0438d..99fe7fb4a 100644 --- a/agent/pkg/controllers/entries_controller.go +++ b/agent/pkg/controllers/entries_controller.go @@ -10,14 +10,11 @@ import ( "mizuserver/pkg/utils" "mizuserver/pkg/validation" "net/http" - "regexp" "time" "github.com/google/martian/har" "github.com/gin-gonic/gin" - "github.com/romana/rlog" - tapApi "github.com/up9inc/mizu/tap/api" ) @@ -65,57 +62,6 @@ func GetEntries(c *gin.Context) { c.JSON(http.StatusOK, baseEntries) } -func SyncEntries(c *gin.Context) { - rlog.Infof("Sync entries - started\n") - - syncParams := &models.SyncEntriesRequestQuery{} - if err := c.BindQuery(syncParams); err != nil { - c.JSON(http.StatusBadRequest, err) - return - } - - if err := validation.Validate(syncParams); err != nil { - c.JSON(http.StatusBadRequest, err) - return - } - - if up9.GetAnalyzeInfo().IsAnalyzing { - c.String(http.StatusBadRequest, "Cannot analyze, mizu is already analyzing") - return - } - - var ( - token, model string - guestMode bool - ) - if syncParams.Token == "" { - rlog.Infof("Sync entries - creating token. env %s\n", syncParams.Env) - guestToken, err := up9.CreateAnonymousToken(syncParams.Env) - if err != nil { - c.String(http.StatusServiceUnavailable, "Failed creating anonymous token") - return - } - - token = guestToken.Token - model = guestToken.Model - guestMode = true - } else { - token = fmt.Sprintf("bearer %s", syncParams.Token) - model = syncParams.Workspace - guestMode = false - } - - modelRegex, _ := regexp.Compile("[A-Za-z0-9][-A-Za-z0-9_.]*[A-Za-z0-9]+$") - if len(model) > 63 || !modelRegex.MatchString(model) { - c.String(http.StatusBadRequest, "Invalid model name") - return - } - - rlog.Infof("Sync entries - syncing. token: %s, model: %s, guest mode: %v\n", token, model, guestMode) - go up9.SyncEntriesImpl(token, model, syncParams.Env, syncParams.UploadIntervalSec, guestMode) - c.String(http.StatusOK, "OK") -} - func GetFullEntries(c *gin.Context) { entriesFilter := &models.HarFetchRequestQuery{} if err := c.BindQuery(entriesFilter); err != nil { diff --git a/agent/pkg/models/models.go b/agent/pkg/models/models.go index 884ba7da1..abb5d1e3f 100644 --- a/agent/pkg/models/models.go +++ b/agent/pkg/models/models.go @@ -22,13 +22,6 @@ type EntriesFilter struct { Timestamp int64 `form:"timestamp" validate:"required,min=1"` } -type SyncEntriesRequestQuery struct { - Token string `form:"token"` - Env string `form:"env"` - Workspace string `form:"workspace"` - UploadIntervalSec int `form:"interval"` -} - type HarFetchRequestQuery struct { From int64 `form:"from"` To int64 `form:"to"` @@ -49,6 +42,11 @@ type WebsocketOutboundLinkMessage struct { Data *tap.OutboundLink } +type AuthStatus struct { + Email string `json:"email"` + Model string `json:"model"` +} + func CreateBaseEntryWebSocketMessage(base *tapApi.BaseEntryDetails) ([]byte, error) { message := &WebSocketEntryMessage{ WebSocketMessageMetadata: &shared.WebSocketMessageMetadata{ diff --git a/agent/pkg/providers/auth_provider.go b/agent/pkg/providers/auth_provider.go deleted file mode 100644 index 05bfc2d2d..000000000 --- a/agent/pkg/providers/auth_provider.go +++ /dev/null @@ -1,29 +0,0 @@ -package providers - -import ( - "encoding/json" - "fmt" - "github.com/up9inc/mizu/shared" - "os" -) - -var authStatus *shared.AuthStatus - -func GetAuthStatus() (*shared.AuthStatus, error) { - if authStatus == nil { - authStatus = &shared.AuthStatus{} - - authStatusJson := os.Getenv(shared.AuthStatusEnvVar) - if authStatusJson == "" { - return authStatus, nil - } - - err := json.Unmarshal([]byte(authStatusJson), authStatus) - if err != nil { - authStatus = nil - return nil, fmt.Errorf("failed to marshal auth status, err: %v", err) - } - } - - return authStatus, nil -} diff --git a/agent/pkg/providers/status_provider.go b/agent/pkg/providers/status_provider.go index b8971ee4b..15928b9bf 100644 --- a/agent/pkg/providers/status_provider.go +++ b/agent/pkg/providers/status_provider.go @@ -1,9 +1,13 @@ package providers import ( + "encoding/json" + "fmt" "github.com/patrickmn/go-cache" "github.com/up9inc/mizu/shared" "github.com/up9inc/mizu/tap" + "mizuserver/pkg/models" + "os" "sync" "time" ) @@ -13,11 +17,45 @@ const tlsLinkRetainmentTime = time.Minute * 15 var ( TappersCount int TapStatus shared.TapStatus + authStatus *models.AuthStatus RecentTLSLinks = cache.New(tlsLinkRetainmentTime, tlsLinkRetainmentTime) tappersCountLock = sync.Mutex{} ) +func GetAuthStatus() (*models.AuthStatus, error) { + if authStatus == nil { + syncEntriesConfigJson := os.Getenv(shared.SyncEntriesConfigEnvVar) + if syncEntriesConfigJson == "" { + authStatus = &models.AuthStatus{} + return authStatus, nil + } + + syncEntriesConfig := &shared.SyncEntriesConfig{} + err := json.Unmarshal([]byte(syncEntriesConfigJson), syncEntriesConfig) + if err != nil { + return nil, fmt.Errorf("failed to marshal sync entries config, err: %v", err) + } + + if syncEntriesConfig.Token == "" { + authStatus = &models.AuthStatus{} + return authStatus, nil + } + + tokenEmail, err := shared.GetTokenEmail(syncEntriesConfig.Token) + if err != nil { + return nil, fmt.Errorf("failed to get token email, err: %v", err) + } + + authStatus = &models.AuthStatus{ + Email: tokenEmail, + Model: syncEntriesConfig.Workspace, + } + } + + return authStatus, nil +} + func GetAllRecentTLSAddresses() []string { recentTLSLinks := make([]string, 0) diff --git a/agent/pkg/routes/entries_routes.go b/agent/pkg/routes/entries_routes.go index 1267a5ea1..aa4066506 100644 --- a/agent/pkg/routes/entries_routes.go +++ b/agent/pkg/routes/entries_routes.go @@ -12,7 +12,6 @@ func EntriesRoutes(ginApp *gin.Engine) { routeGroup.GET("/entries", controllers.GetEntries) // get entries (base/thin entries) routeGroup.GET("/entries/:entryId", controllers.GetEntry) // get single (full) entry routeGroup.GET("/exportEntries", controllers.GetFullEntries) - routeGroup.GET("/syncEntries", controllers.SyncEntries) routeGroup.GET("/resolving", controllers.GetCurrentResolvingInformation) routeGroup.GET("/resetDB", controllers.DeleteAllEntries) // get single (full) entry diff --git a/agent/pkg/up9/main.go b/agent/pkg/up9/main.go index d0ec22353..c33f38070 100644 --- a/agent/pkg/up9/main.go +++ b/agent/pkg/up9/main.go @@ -15,6 +15,7 @@ import ( "mizuserver/pkg/utils" "net/http" "net/url" + "regexp" "strings" "time" ) @@ -32,29 +33,6 @@ type ModelStatus struct { LastMajorGeneration float64 `json:"lastMajorGeneration"` } -func getGuestToken(url string, target *GuestToken) error { - resp, err := http.Get(url) - if err != nil { - return err - } - defer resp.Body.Close() - rlog.Infof("Got token from the server, starting to json decode... status code: %v", resp.StatusCode) - return json.NewDecoder(resp.Body).Decode(target) -} - -func CreateAnonymousToken(envPrefix string) (*GuestToken, error) { - tokenUrl := fmt.Sprintf("https://trcc.%s/anonymous/token", envPrefix) - if strings.HasPrefix(envPrefix, "http") { - tokenUrl = fmt.Sprintf("%s/api/token", envPrefix) - } - token := &GuestToken{} - if err := getGuestToken(tokenUrl, token); err != nil { - rlog.Infof("Failed to get token, %s", err) - return nil, err - } - return token, nil -} - func GetRemoteUrl(analyzeDestination string, analyzeModel string, analyzeToken string, guestMode bool) string { if guestMode { return fmt.Sprintf("https://%s/share/%s", analyzeDestination, analyzeToken) @@ -133,7 +111,64 @@ func GetAnalyzeInfo() *shared.AnalyzeStatus { } } -func SyncEntriesImpl(token string, model string, envPrefix string, uploadIntervalSec int, guestMode bool) { +func SyncEntries(syncEntriesConfig *shared.SyncEntriesConfig) error { + rlog.Infof("Sync entries - started\n") + + var ( + token, model string + guestMode bool + ) + if syncEntriesConfig.Token == "" { + rlog.Infof("Sync entries - creating anonymous token. env %s\n", syncEntriesConfig.Env) + guestToken, err := createAnonymousToken(syncEntriesConfig.Env) + if err != nil { + return fmt.Errorf("failed creating anonymous token, err: %v", err) + } + + token = guestToken.Token + model = guestToken.Model + guestMode = true + } else { + token = fmt.Sprintf("bearer %s", syncEntriesConfig.Token) + model = syncEntriesConfig.Workspace + guestMode = false + } + + modelRegex, _ := regexp.Compile("[A-Za-z0-9][-A-Za-z0-9_.]*[A-Za-z0-9]+$") + if len(model) > 63 || !modelRegex.MatchString(model) { + return fmt.Errorf("invalid model name, model name: %s", model) + } + + rlog.Infof("Sync entries - syncing. token: %s, model: %s, guest mode: %v\n", token, model, guestMode) + go syncEntriesImpl(token, model, syncEntriesConfig.Env, syncEntriesConfig.UploadIntervalSec, guestMode) + + return nil +} + +func createAnonymousToken(envPrefix string) (*GuestToken, error) { + tokenUrl := fmt.Sprintf("https://trcc.%s/anonymous/token", envPrefix) + if strings.HasPrefix(envPrefix, "http") { + tokenUrl = fmt.Sprintf("%s/api/token", envPrefix) + } + token := &GuestToken{} + if err := getGuestToken(tokenUrl, token); err != nil { + rlog.Infof("Failed to get token, %s", err) + return nil, err + } + return token, nil +} + +func getGuestToken(url string, target *GuestToken) error { + resp, err := http.Get(url) + if err != nil { + return err + } + defer resp.Body.Close() + rlog.Infof("Got token from the server, starting to json decode... status code: %v", resp.StatusCode) + return json.NewDecoder(resp.Body).Decode(target) +} + +func syncEntriesImpl(token string, model string, envPrefix string, uploadIntervalSec int, guestMode bool) { analyzeInformation.IsAnalyzing = true analyzeInformation.GuestMode = guestMode analyzeInformation.AnalyzedModel = model diff --git a/cli/apiserver/provider.go b/cli/apiserver/provider.go index 4be8ea2f2..6369a4a34 100644 --- a/cli/apiserver/provider.go +++ b/cli/apiserver/provider.go @@ -6,7 +6,6 @@ import ( "fmt" "github.com/up9inc/mizu/cli/config" "github.com/up9inc/mizu/cli/logger" - "github.com/up9inc/mizu/cli/uiUtils" "github.com/up9inc/mizu/shared" "io/ioutil" core "k8s.io/api/core/v1" @@ -82,27 +81,6 @@ func (provider *apiServerProvider) ReportTappedPods(pods []core.Pod) error { } } -func (provider *apiServerProvider) RequestSyncEntries(envName string, workspace string, uploadIntervalSec int, token string) error { - if !provider.isReady { - return fmt.Errorf("trying to reach api server when not initialized yet") - } - urlPath := fmt.Sprintf("%s/api/syncEntries?env=%s&workspace=%s&token=%s&interval=%v", provider.url, url.QueryEscape(envName), url.QueryEscape(workspace), url.QueryEscape(token), uploadIntervalSec) - syncEntriesUrl, parseErr := url.ParseRequestURI(urlPath) - if parseErr != nil { - logger.Log.Fatal("Failed parsing the URL (consider changing the env name), err: %v", parseErr) - } - - logger.Log.Debugf("Sync entries url %v", syncEntriesUrl.String()) - if response, requestErr := http.Get(syncEntriesUrl.String()); requestErr != nil { - return fmt.Errorf("failed to notify api server for sync entries, err: %w", requestErr) - } else if response.StatusCode != 200 { - return fmt.Errorf("failed to notify api server for sync entries, status code: %v", response.StatusCode) - } else { - logger.Log.Infof(uiUtils.Purple, "Entries are syncing to UP9 for further analysis") - return nil - } -} - func (provider *apiServerProvider) GetGeneralStats() (map[string]interface{}, error) { if !provider.isReady { return nil, fmt.Errorf("trying to reach api server when not initialized yet") diff --git a/cli/auth/authProvider.go b/cli/auth/authProvider.go index f5d7b979c..0e065e15c 100644 --- a/cli/auth/authProvider.go +++ b/cli/auth/authProvider.go @@ -4,7 +4,6 @@ import ( "context" "errors" "fmt" - "github.com/golang-jwt/jwt/v4" "github.com/google/uuid" "github.com/up9inc/mizu/cli/config" "github.com/up9inc/mizu/cli/config/configStructs" @@ -22,40 +21,6 @@ const loginTimeoutInMin = 2 // Ports are configured in keycloak "cli" client as valid redirect URIs. A change here must be reflected there as well. var listenPorts = []int{3141, 4001, 5002, 6003, 7004, 8005, 9006, 10007} -func IsTokenExpired(tokenString string) (bool, error) { - claims, err := getTokenClaims(tokenString) - if err != nil { - return true, err - } - - expiry := time.Unix(int64(claims["exp"].(float64)), 0) - - return time.Now().After(expiry), nil -} - -func GetTokenEmail(tokenString string) (string, error) { - claims, err := getTokenClaims(tokenString) - if err != nil { - return "", err - } - - return claims["email"].(string), nil -} - -func getTokenClaims(tokenString string) (jwt.MapClaims, error) { - token, _, err := new(jwt.Parser).ParseUnverified(tokenString, jwt.MapClaims{}) - if err != nil { - return nil, fmt.Errorf("failed to parse token, err: %v", err) - } - - claims, ok := token.Claims.(jwt.MapClaims) - if !ok { - return nil, fmt.Errorf("can't convert token's claims to standard claims") - } - - return claims, nil -} - func Login() error { token, loginErr := loginInteractively() if loginErr != nil { diff --git a/cli/cmd/tap.go b/cli/cmd/tap.go index 6984cea2a..dfb9ff539 100644 --- a/cli/cmd/tap.go +++ b/cli/cmd/tap.go @@ -12,6 +12,7 @@ import ( "github.com/up9inc/mizu/cli/logger" "github.com/up9inc/mizu/cli/telemetry" "github.com/up9inc/mizu/cli/uiUtils" + "github.com/up9inc/mizu/shared" "os" ) @@ -48,7 +49,7 @@ Supported protocols are HTTP and gRPC.`, return nil } } else { - tokenExpired, err := auth.IsTokenExpired(config.Config.Auth.Token) + tokenExpired, err := shared.IsTokenExpired(config.Config.Auth.Token) if err != nil { logger.Log.Errorf("failed to check if token is expired, err: %v", err) return nil diff --git a/cli/cmd/tapRunner.go b/cli/cmd/tapRunner.go index 27637c47c..8046b041d 100644 --- a/cli/cmd/tapRunner.go +++ b/cli/cmd/tapRunner.go @@ -3,7 +3,6 @@ package cmd import ( "context" "fmt" - "github.com/up9inc/mizu/cli/auth" "path" "regexp" "strings" @@ -49,12 +48,6 @@ func RunMizuTap() { return } - authStatus, err := getAuthStatus() - if err != nil { - logger.Log.Errorf(uiUtils.Error, fmt.Sprintf("Error getting auth status: %v", errormessage.FormatError(err))) - return - } - var mizuValidationRules string if config.Config.Tap.EnforcePolicyFile != "" { mizuValidationRules, err = readValidationRules(config.Config.Tap.EnforcePolicyFile) @@ -110,7 +103,7 @@ func RunMizuTap() { } defer finishMizuExecution(kubernetesProvider) - if err := createMizuResources(ctx, kubernetesProvider, mizuApiFilteringOptions, mizuValidationRules, authStatus); err != nil { + if err := createMizuResources(ctx, kubernetesProvider, mizuApiFilteringOptions, mizuValidationRules); err != nil { logger.Log.Errorf(uiUtils.Error, fmt.Sprintf("Error creating resources: %v", errormessage.FormatError(err))) return } @@ -132,14 +125,14 @@ func readValidationRules(file string) (string, error) { return string(newContent), nil } -func createMizuResources(ctx context.Context, kubernetesProvider *kubernetes.Provider, mizuApiFilteringOptions *api.TrafficFilteringOptions, mizuValidationRules string, authStatus *shared.AuthStatus) error { +func createMizuResources(ctx context.Context, kubernetesProvider *kubernetes.Provider, mizuApiFilteringOptions *api.TrafficFilteringOptions, mizuValidationRules string) error { if !config.Config.IsNsRestrictedMode() { if err := createMizuNamespace(ctx, kubernetesProvider); err != nil { return err } } - if err := createMizuApiServer(ctx, kubernetesProvider, mizuApiFilteringOptions, authStatus); err != nil { + if err := createMizuApiServer(ctx, kubernetesProvider, mizuApiFilteringOptions); err != nil { return err } @@ -160,7 +153,7 @@ func createMizuNamespace(ctx context.Context, kubernetesProvider *kubernetes.Pro return err } -func createMizuApiServer(ctx context.Context, kubernetesProvider *kubernetes.Provider, mizuApiFilteringOptions *api.TrafficFilteringOptions, authStatus *shared.AuthStatus) error { +func createMizuApiServer(ctx context.Context, kubernetesProvider *kubernetes.Provider, mizuApiFilteringOptions *api.TrafficFilteringOptions) error { var err error state.mizuServiceAccountExists, err = createRBACIfNecessary(ctx, kubernetesProvider) @@ -182,7 +175,7 @@ func createMizuApiServer(ctx context.Context, kubernetesProvider *kubernetes.Pro ServiceAccountName: serviceAccountName, IsNamespaceRestricted: config.Config.IsNsRestrictedMode(), MizuApiFilteringOptions: mizuApiFilteringOptions, - AuthStatus: authStatus, + SyncEntriesConfig: getSyncEntriesConfig(), MaxEntriesDBSizeBytes: config.Config.Tap.MaxEntriesDBSizeBytes(), Resources: config.Config.Tap.ApiServerResources, ImagePullPolicy: config.Config.ImagePullPolicy(), @@ -223,20 +216,17 @@ func getMizuApiFilteringOptions() (*api.TrafficFilteringOptions, error) { }, nil } -func getAuthStatus() (*shared.AuthStatus, error) { - if config.Config.Tap.Workspace == "" { - return &shared.AuthStatus{}, nil +func getSyncEntriesConfig() *shared.SyncEntriesConfig { + if !config.Config.Tap.Analysis && config.Config.Tap.Workspace == "" { + return nil } - email, err := auth.GetTokenEmail(config.Config.Auth.Token) - if err != nil { - return nil, err + return &shared.SyncEntriesConfig{ + Token: config.Config.Auth.Token, + Env: config.Config.Auth.EnvName, + Workspace: config.Config.Tap.Workspace, + UploadIntervalSec: config.Config.Tap.UploadIntervalSec, } - - return &shared.AuthStatus{ - Email: email, - Model: config.Config.Tap.Workspace, - }, nil } func updateMizuTappers(ctx context.Context, kubernetesProvider *kubernetes.Provider, mizuApiFilteringOptions *api.TrafficFilteringOptions) error { @@ -603,7 +593,6 @@ func watchApiServerPod(ctx context.Context, kubernetesProvider *kubernetes.Provi logger.Log.Infof("Mizu is available at %s\n", url) uiUtils.OpenBrowser(url) - requestForSyncEntriesIfNeeded() if err := apiserver.Provider.ReportTappedPods(state.currentlyTappedPods); err != nil { logger.Log.Debugf("[Error] failed update tapped pods %v", err) } @@ -695,16 +684,6 @@ func watchTapperPod(ctx context.Context, kubernetesProvider *kubernetes.Provider } } -func requestForSyncEntriesIfNeeded() { - if !config.Config.Tap.Analysis && config.Config.Tap.Workspace == "" { - return - } - - if err := apiserver.Provider.RequestSyncEntries(config.Config.Auth.EnvName, config.Config.Tap.Workspace, config.Config.Tap.UploadIntervalSec, config.Config.Auth.Token); err != nil { - logger.Log.Debugf("[Error] failed requesting for sync entries, err: %v", err) - } -} - func createRBACIfNecessary(ctx context.Context, kubernetesProvider *kubernetes.Provider) (bool, error) { if !config.Config.IsNsRestrictedMode() { err := kubernetesProvider.CreateMizuRBAC(ctx, config.Config.MizuResourcesNamespace, mizu.ServiceAccountName, mizu.ClusterRoleName, mizu.ClusterRoleBindingName, mizu.RBACVersion) diff --git a/cli/go.mod b/cli/go.mod index 6e35a73c5..11c0f116a 100644 --- a/cli/go.mod +++ b/cli/go.mod @@ -5,7 +5,6 @@ go 1.16 require ( github.com/creasty/defaults v1.5.1 github.com/denisbrodbeck/machineid v1.0.1 - github.com/golang-jwt/jwt/v4 v4.1.0 github.com/google/go-github/v37 v37.0.0 github.com/google/uuid v1.1.2 github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 diff --git a/cli/kubernetes/provider.go b/cli/kubernetes/provider.go index 49dbbd08f..9d5c2dce3 100644 --- a/cli/kubernetes/provider.go +++ b/cli/kubernetes/provider.go @@ -152,7 +152,7 @@ type ApiServerOptions struct { ServiceAccountName string IsNamespaceRestricted bool MizuApiFilteringOptions *api.TrafficFilteringOptions - AuthStatus *shared.AuthStatus + SyncEntriesConfig *shared.SyncEntriesConfig MaxEntriesDBSizeBytes int64 Resources configStructs.Resources ImagePullPolicy core.PullPolicy @@ -164,9 +164,12 @@ func (provider *Provider) CreateMizuApiServerPod(ctx context.Context, opts *ApiS return nil, err } - marshaledAuthStatus, err := json.Marshal(opts.AuthStatus) - if err != nil { - return nil, err + var marshaledSyncEntriesConfig []byte + if opts.SyncEntriesConfig != nil { + marshaledSyncEntriesConfig, err = json.Marshal(opts.SyncEntriesConfig) + if err != nil { + return nil, err + } } configMapVolumeName := &core.ConfigMapVolumeSource{} @@ -225,8 +228,8 @@ func (provider *Provider) CreateMizuApiServerPod(ctx context.Context, opts *ApiS Value: string(marshaledFilteringOptions), }, { - Name: shared.AuthStatusEnvVar, - Value: string(marshaledAuthStatus), + Name: shared.SyncEntriesConfigEnvVar, + Value: string(marshaledSyncEntriesConfig), }, { Name: shared.MaxEntriesDBSizeBytesEnvVar, diff --git a/shared/consts.go b/shared/consts.go index 57ba71aec..42f1b5090 100644 --- a/shared/consts.go +++ b/shared/consts.go @@ -2,7 +2,7 @@ package shared const ( MizuFilteringOptionsEnvVar = "SENSITIVE_DATA_FILTERING_OPTIONS" - AuthStatusEnvVar = "AUTH_STATUS" + SyncEntriesConfigEnvVar = "SYNC_ENTRIES_CONFIG" HostModeEnvVar = "HOST_MODE" NodeNameEnvVar = "NODE_NAME" TappedAddressesPerNodeDictEnvVar = "TAPPED_ADDRESSES_PER_HOST" diff --git a/shared/go.mod b/shared/go.mod index 5e50ad375..83dd85f40 100644 --- a/shared/go.mod +++ b/shared/go.mod @@ -4,6 +4,6 @@ go 1.16 require ( github.com/docker/go-units v0.4.0 - github.com/gorilla/websocket v1.4.2 + github.com/golang-jwt/jwt/v4 v4.1.0 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b ) diff --git a/shared/go.sum b/shared/go.sum index 65c692cb5..d80d9eb99 100644 --- a/shared/go.sum +++ b/shared/go.sum @@ -1,7 +1,7 @@ github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= -github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/golang-jwt/jwt/v4 v4.1.0 h1:XUgk2Ex5veyVFVeLm0xhusUTQybEbexJXrvPNOKkSY0= +github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= diff --git a/shared/models.go b/shared/models.go index 28c577e5b..2577dd4cc 100644 --- a/shared/models.go +++ b/shared/models.go @@ -56,9 +56,11 @@ type TLSLinkInfo struct { ResolvedSourceName string `json:"resolvedSourceName"` } -type AuthStatus struct { - Email string `json:"email"` - Model string `json:"model"` +type SyncEntriesConfig struct { + Token string `json:"token"` + Env string `json:"env"` + Workspace string `json:"workspace"` + UploadIntervalSec int `json:"interval"` } func CreateWebSocketStatusMessage(tappingStatus TapStatus) WebSocketStatusMessage { diff --git a/shared/tokenUtils.go b/shared/tokenUtils.go new file mode 100644 index 000000000..0bd212a3a --- /dev/null +++ b/shared/tokenUtils.go @@ -0,0 +1,41 @@ +package shared + +import ( + "fmt" + "github.com/golang-jwt/jwt/v4" + "time" +) + +func IsTokenExpired(tokenString string) (bool, error) { + claims, err := getTokenClaims(tokenString) + if err != nil { + return true, err + } + + expiry := time.Unix(int64(claims["exp"].(float64)), 0) + + return time.Now().After(expiry), nil +} + +func GetTokenEmail(tokenString string) (string, error) { + claims, err := getTokenClaims(tokenString) + if err != nil { + return "", err + } + + return claims["email"].(string), nil +} + +func getTokenClaims(tokenString string) (jwt.MapClaims, error) { + token, _, err := new(jwt.Parser).ParseUnverified(tokenString, jwt.MapClaims{}) + if err != nil { + return nil, fmt.Errorf("failed to parse token, err: %v", err) + } + + claims, ok := token.Claims.(jwt.MapClaims) + if !ok { + return nil, fmt.Errorf("can't convert token's claims to standard claims") + } + + return claims, nil +}