mirror of
https://github.com/kubeshark/kubeshark.git
synced 2026-03-17 09:00:20 +00:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
10e695d7a0 | ||
|
|
837e35255b | ||
|
|
56e801a582 | ||
|
|
04c0f8cbcd |
@@ -34,3 +34,13 @@ func PostTappedPods(c *gin.Context) {
|
||||
func GetTappersCount(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, providers.TappersCount)
|
||||
}
|
||||
|
||||
func GetAuthStatus(c *gin.Context) {
|
||||
authStatus, err := providers.GetAuthStatus()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, authStatus)
|
||||
}
|
||||
|
||||
29
agent/pkg/providers/auth_provider.go
Normal file
29
agent/pkg/providers/auth_provider.go
Normal file
@@ -0,0 +1,29 @@
|
||||
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
|
||||
}
|
||||
@@ -11,4 +11,6 @@ func StatusRoutes(ginApp *gin.Engine) {
|
||||
routeGroup.POST("/tappedPods", controllers.PostTappedPods)
|
||||
|
||||
routeGroup.GET("/tappersCount", controllers.GetTappersCount)
|
||||
|
||||
routeGroup.GET("/auth", controllers.GetAuthStatus)
|
||||
}
|
||||
|
||||
@@ -55,8 +55,12 @@ func CreateAnonymousToken(envPrefix string) (*GuestToken, error) {
|
||||
return token, nil
|
||||
}
|
||||
|
||||
func GetRemoteUrl(analyzeDestination string, analyzeToken string) string {
|
||||
return fmt.Sprintf("https://%s/share/%s", analyzeDestination, analyzeToken)
|
||||
func GetRemoteUrl(analyzeDestination string, analyzeModel string, analyzeToken string, guestMode bool) string {
|
||||
if guestMode {
|
||||
return fmt.Sprintf("https://%s/share/%s", analyzeDestination, analyzeToken)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("https://%s/app/workspaces/%s", analyzeDestination, analyzeModel)
|
||||
}
|
||||
|
||||
func CheckIfModelReady(analyzeDestination string, analyzeModel string, analyzeToken string, guestMode bool) bool {
|
||||
@@ -123,7 +127,7 @@ var analyzeInformation = &AnalyzeInformation{}
|
||||
func GetAnalyzeInfo() *shared.AnalyzeStatus {
|
||||
return &shared.AnalyzeStatus{
|
||||
IsAnalyzing: analyzeInformation.IsAnalyzing,
|
||||
RemoteUrl: GetRemoteUrl(analyzeInformation.AnalyzeDestination, analyzeInformation.AnalyzeToken),
|
||||
RemoteUrl: GetRemoteUrl(analyzeInformation.AnalyzeDestination, analyzeInformation.AnalyzedModel, analyzeInformation.AnalyzeToken, analyzeInformation.GuestMode),
|
||||
IsRemoteReady: CheckIfModelReady(analyzeInformation.AnalyzeDestination, analyzeInformation.AnalyzedModel, analyzeInformation.AnalyzeToken, analyzeInformation.GuestMode),
|
||||
SentCount: analyzeInformation.SentCount,
|
||||
}
|
||||
|
||||
@@ -82,11 +82,11 @@ func (provider *apiServerProvider) ReportTappedPods(pods []core.Pod) error {
|
||||
}
|
||||
}
|
||||
|
||||
func (provider *apiServerProvider) RequestSyncEntries(analysisDestination string, sleepIntervalSec int) 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&interval=%v", provider.url, url.QueryEscape(analysisDestination), sleepIntervalSec)
|
||||
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)
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/creasty/defaults"
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/google/uuid"
|
||||
"github.com/up9inc/mizu/cli/config"
|
||||
@@ -24,14 +23,9 @@ const loginTimeoutInMin = 2
|
||||
var listenPorts = []int{3141, 4001, 5002, 6003, 7004, 8005, 9006, 10007}
|
||||
|
||||
func IsTokenExpired(tokenString string) (bool, error) {
|
||||
token, _, err := new(jwt.Parser).ParseUnverified(tokenString, jwt.MapClaims{})
|
||||
claims, err := getTokenClaims(tokenString)
|
||||
if err != nil {
|
||||
return true, fmt.Errorf("failed to parse token, err: %v", err)
|
||||
}
|
||||
|
||||
claims, ok := token.Claims.(jwt.MapClaims)
|
||||
if !ok {
|
||||
return true, fmt.Errorf("can't convert token's claims to standard claims")
|
||||
return true, err
|
||||
}
|
||||
|
||||
expiry := time.Unix(int64(claims["exp"].(float64)), 0)
|
||||
@@ -39,10 +33,33 @@ func IsTokenExpired(tokenString string) (bool, error) {
|
||||
return time.Now().After(expiry), nil
|
||||
}
|
||||
|
||||
func Login() error {
|
||||
token, err := loginInteractively()
|
||||
func GetTokenEmail(tokenString string) (string, error) {
|
||||
claims, err := getTokenClaims(tokenString)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed login interactively, err: %v", err)
|
||||
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 {
|
||||
return fmt.Errorf("failed login interactively, err: %v", loginErr)
|
||||
}
|
||||
|
||||
authConfig := configStructs.AuthConfig{
|
||||
@@ -50,18 +67,18 @@ func Login() error {
|
||||
Token: token.AccessToken,
|
||||
}
|
||||
|
||||
configFile := config.ConfigStruct{}
|
||||
if err := defaults.Set(&configFile); err != nil {
|
||||
return fmt.Errorf("failed inserting default values to config, err: %v", err)
|
||||
configFile, defaultConfigErr := config.GetConfigWithDefaults()
|
||||
if defaultConfigErr != nil {
|
||||
return fmt.Errorf("failed getting config with defaults, err: %v", defaultConfigErr)
|
||||
}
|
||||
|
||||
if err := config.LoadConfigFile(config.Config.ConfigFilePath, &configFile); err != nil && !os.IsNotExist(err) {
|
||||
if err := config.LoadConfigFile(config.Config.ConfigFilePath, configFile); err != nil && !os.IsNotExist(err) {
|
||||
return fmt.Errorf("failed getting config file, err: %v", err)
|
||||
}
|
||||
|
||||
configFile.Auth = authConfig
|
||||
|
||||
if err := config.WriteConfig(&configFile); err != nil {
|
||||
if err := config.WriteConfig(configFile); err != nil {
|
||||
return fmt.Errorf("failed writing config with auth, err: %v", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -2,20 +2,20 @@ package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
|
||||
"github.com/up9inc/mizu/cli/config"
|
||||
"github.com/up9inc/mizu/cli/config/configStructs"
|
||||
"github.com/up9inc/mizu/cli/logger"
|
||||
"github.com/up9inc/mizu/cli/telemetry"
|
||||
|
||||
"fmt"
|
||||
"github.com/creasty/defaults"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/up9inc/mizu/cli/auth"
|
||||
"github.com/up9inc/mizu/cli/config"
|
||||
"github.com/up9inc/mizu/cli/config/configStructs"
|
||||
"github.com/up9inc/mizu/cli/errormessage"
|
||||
"github.com/up9inc/mizu/cli/logger"
|
||||
"github.com/up9inc/mizu/cli/telemetry"
|
||||
"github.com/up9inc/mizu/cli/uiUtils"
|
||||
"os"
|
||||
)
|
||||
|
||||
const analysisMessageToConfirm = `NOTE: running mizu with --analysis flag will upload recorded traffic for further analysis and enriched presentation options.`
|
||||
const uploadTrafficMessageToConfirm = `NOTE: running mizu with --%s flag will upload recorded traffic for further analysis and enriched presentation options.`
|
||||
|
||||
var tapCmd = &cobra.Command{
|
||||
Use: "tap [POD REGEX]",
|
||||
@@ -38,20 +38,52 @@ Supported protocols are HTTP and gRPC.`,
|
||||
return errormessage.FormatError(err)
|
||||
}
|
||||
|
||||
logger.Log.Infof("Mizu will store up to %s of traffic, old traffic will be cleared once the limit is reached.", config.Config.Tap.HumanMaxEntriesDBSize)
|
||||
if config.Config.Tap.Workspace != "" {
|
||||
askConfirmation(configStructs.WorkspaceTapName)
|
||||
|
||||
if config.Config.Tap.Analysis {
|
||||
logger.Log.Infof(analysisMessageToConfirm)
|
||||
if !uiUtils.AskForConfirmation("Would you like to proceed [Y/n]: ") {
|
||||
logger.Log.Infof("You can always run mizu without analysis, aborting")
|
||||
os.Exit(0)
|
||||
if config.Config.Auth.Token == "" {
|
||||
logger.Log.Infof("This action requires authentication, please log in to continue")
|
||||
if err := auth.Login(); err != nil {
|
||||
logger.Log.Errorf("failed to log in, err: %v", err)
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
tokenExpired, err := auth.IsTokenExpired(config.Config.Auth.Token)
|
||||
if err != nil {
|
||||
logger.Log.Errorf("failed to check if token is expired, err: %v", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
if tokenExpired {
|
||||
logger.Log.Infof("Token expired, please log in again to continue")
|
||||
if err := auth.Login(); err != nil {
|
||||
logger.Log.Errorf("failed to log in, err: %v", err)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if config.Config.Tap.Analysis {
|
||||
askConfirmation(configStructs.AnalysisTapName)
|
||||
|
||||
config.Config.Auth.Token = ""
|
||||
}
|
||||
|
||||
logger.Log.Infof("Mizu will store up to %s of traffic, old traffic will be cleared once the limit is reached.", config.Config.Tap.HumanMaxEntriesDBSize)
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func askConfirmation(flagName string) {
|
||||
logger.Log.Infof(fmt.Sprintf(uploadTrafficMessageToConfirm, flagName))
|
||||
if !uiUtils.AskForConfirmation("Would you like to proceed [Y/n]: ") {
|
||||
logger.Log.Infof("You can always run mizu without %s, aborting", flagName)
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(tapCmd)
|
||||
|
||||
@@ -66,5 +98,6 @@ func init() {
|
||||
tapCmd.Flags().Bool(configStructs.DisableRedactionTapName, defaultTapConfig.DisableRedaction, "Disables redaction of potentially sensitive request/response headers and body values")
|
||||
tapCmd.Flags().String(configStructs.HumanMaxEntriesDBSizeTapName, defaultTapConfig.HumanMaxEntriesDBSize, "Override the default max entries db size")
|
||||
tapCmd.Flags().Bool(configStructs.DryRunTapName, defaultTapConfig.DryRun, "Preview of all pods matching the regex, without tapping them")
|
||||
tapCmd.Flags().StringP(configStructs.WorkspaceTapName, "w", defaultTapConfig.Workspace, "Uploads traffic to your UP9 workspace for further analysis (requires auth)")
|
||||
tapCmd.Flags().String(configStructs.EnforcePolicyFile, defaultTapConfig.EnforcePolicyFile, "Yaml file path with policy rules")
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package cmd
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/up9inc/mizu/cli/auth"
|
||||
"path"
|
||||
"regexp"
|
||||
"strings"
|
||||
@@ -48,6 +49,12 @@ 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)
|
||||
@@ -103,7 +110,7 @@ func RunMizuTap() {
|
||||
}
|
||||
|
||||
defer finishMizuExecution(kubernetesProvider)
|
||||
if err := createMizuResources(ctx, kubernetesProvider, mizuApiFilteringOptions, mizuValidationRules); err != nil {
|
||||
if err := createMizuResources(ctx, kubernetesProvider, mizuApiFilteringOptions, mizuValidationRules, authStatus); err != nil {
|
||||
logger.Log.Errorf(uiUtils.Error, fmt.Sprintf("Error creating resources: %v", errormessage.FormatError(err)))
|
||||
return
|
||||
}
|
||||
@@ -125,14 +132,14 @@ func readValidationRules(file string) (string, error) {
|
||||
return string(newContent), nil
|
||||
}
|
||||
|
||||
func createMizuResources(ctx context.Context, kubernetesProvider *kubernetes.Provider, mizuApiFilteringOptions *api.TrafficFilteringOptions, mizuValidationRules string) error {
|
||||
func createMizuResources(ctx context.Context, kubernetesProvider *kubernetes.Provider, mizuApiFilteringOptions *api.TrafficFilteringOptions, mizuValidationRules string, authStatus *shared.AuthStatus) error {
|
||||
if !config.Config.IsNsRestrictedMode() {
|
||||
if err := createMizuNamespace(ctx, kubernetesProvider); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := createMizuApiServer(ctx, kubernetesProvider, mizuApiFilteringOptions); err != nil {
|
||||
if err := createMizuApiServer(ctx, kubernetesProvider, mizuApiFilteringOptions, authStatus); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -153,7 +160,7 @@ func createMizuNamespace(ctx context.Context, kubernetesProvider *kubernetes.Pro
|
||||
return err
|
||||
}
|
||||
|
||||
func createMizuApiServer(ctx context.Context, kubernetesProvider *kubernetes.Provider, mizuApiFilteringOptions *api.TrafficFilteringOptions) error {
|
||||
func createMizuApiServer(ctx context.Context, kubernetesProvider *kubernetes.Provider, mizuApiFilteringOptions *api.TrafficFilteringOptions, authStatus *shared.AuthStatus) error {
|
||||
var err error
|
||||
|
||||
state.mizuServiceAccountExists, err = createRBACIfNecessary(ctx, kubernetesProvider)
|
||||
@@ -175,6 +182,7 @@ func createMizuApiServer(ctx context.Context, kubernetesProvider *kubernetes.Pro
|
||||
ServiceAccountName: serviceAccountName,
|
||||
IsNamespaceRestricted: config.Config.IsNsRestrictedMode(),
|
||||
MizuApiFilteringOptions: mizuApiFilteringOptions,
|
||||
AuthStatus: authStatus,
|
||||
MaxEntriesDBSizeBytes: config.Config.Tap.MaxEntriesDBSizeBytes(),
|
||||
Resources: config.Config.Tap.ApiServerResources,
|
||||
ImagePullPolicy: config.Config.ImagePullPolicy(),
|
||||
@@ -215,6 +223,22 @@ func getMizuApiFilteringOptions() (*api.TrafficFilteringOptions, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func getAuthStatus() (*shared.AuthStatus, error) {
|
||||
if config.Config.Tap.Workspace == "" {
|
||||
return &shared.AuthStatus{}, nil
|
||||
}
|
||||
|
||||
email, err := auth.GetTokenEmail(config.Config.Auth.Token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &shared.AuthStatus{
|
||||
Email: email,
|
||||
Model: config.Config.Tap.Workspace,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func updateMizuTappers(ctx context.Context, kubernetesProvider *kubernetes.Provider, mizuApiFilteringOptions *api.TrafficFilteringOptions) error {
|
||||
nodeToTappedPodIPMap := getNodeHostToTappedPodIpsMap(state.currentlyTappedPods)
|
||||
|
||||
@@ -672,10 +696,11 @@ func watchTapperPod(ctx context.Context, kubernetesProvider *kubernetes.Provider
|
||||
}
|
||||
|
||||
func requestForSyncEntriesIfNeeded() {
|
||||
if !config.Config.Tap.Analysis {
|
||||
if !config.Config.Tap.Analysis && config.Config.Tap.Workspace == "" {
|
||||
return
|
||||
}
|
||||
if err := apiserver.Provider.RequestSyncEntries(config.Config.Tap.AnalysisDestination, config.Config.Tap.UploadIntervalSec); err != nil {
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,11 +16,11 @@ const (
|
||||
DisableRedactionTapName = "no-redact"
|
||||
HumanMaxEntriesDBSizeTapName = "max-entries-db-size"
|
||||
DryRunTapName = "dry-run"
|
||||
WorkspaceTapName = "workspace"
|
||||
EnforcePolicyFile = "traffic-validation-file"
|
||||
)
|
||||
|
||||
type TapConfig struct {
|
||||
AnalysisDestination string `yaml:"dest" default:"up9.app"`
|
||||
UploadIntervalSec int `yaml:"upload-interval" default:"10"`
|
||||
PodRegexStr string `yaml:"regex" default:".*"`
|
||||
GuiPort uint16 `yaml:"gui-port" default:"8899"`
|
||||
@@ -32,6 +32,7 @@ type TapConfig struct {
|
||||
DisableRedaction bool `yaml:"no-redact" default:"false"`
|
||||
HumanMaxEntriesDBSize string `yaml:"max-entries-db-size" default:"200MB"`
|
||||
DryRun bool `yaml:"dry-run" default:"false"`
|
||||
Workspace string `yaml:"workspace"`
|
||||
EnforcePolicyFile string `yaml:"traffic-validation-file"`
|
||||
ApiServerResources Resources `yaml:"api-server-resources"`
|
||||
TapperResources Resources `yaml:"tapper-resources"`
|
||||
@@ -65,5 +66,16 @@ func (config *TapConfig) Validate() error {
|
||||
return errors.New(fmt.Sprintf("Could not parse --%s value %s", HumanMaxEntriesDBSizeTapName, config.HumanMaxEntriesDBSize))
|
||||
}
|
||||
|
||||
if config.Workspace != "" {
|
||||
workspaceRegex, _ := regexp.Compile("[A-Za-z0-9][-A-Za-z0-9_.]*[A-Za-z0-9]+$")
|
||||
if len(config.Workspace) > 63 || !workspaceRegex.MatchString(config.Workspace) {
|
||||
return errors.New("invalid workspace name")
|
||||
}
|
||||
}
|
||||
|
||||
if config.Analysis && config.Workspace != "" {
|
||||
return errors.New(fmt.Sprintf("Can't run with both --%s and --%s flags", AnalysisTapName, WorkspaceTapName))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -152,6 +152,7 @@ type ApiServerOptions struct {
|
||||
ServiceAccountName string
|
||||
IsNamespaceRestricted bool
|
||||
MizuApiFilteringOptions *api.TrafficFilteringOptions
|
||||
AuthStatus *shared.AuthStatus
|
||||
MaxEntriesDBSizeBytes int64
|
||||
Resources configStructs.Resources
|
||||
ImagePullPolicy core.PullPolicy
|
||||
@@ -162,6 +163,12 @@ func (provider *Provider) CreateMizuApiServerPod(ctx context.Context, opts *ApiS
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
marshaledAuthStatus, err := json.Marshal(opts.AuthStatus)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
configMapVolumeName := &core.ConfigMapVolumeSource{}
|
||||
configMapVolumeName.Name = mizu.ConfigMapName
|
||||
configMapOptional := true
|
||||
@@ -217,6 +224,10 @@ func (provider *Provider) CreateMizuApiServerPod(ctx context.Context, opts *ApiS
|
||||
Name: shared.MizuFilteringOptionsEnvVar,
|
||||
Value: string(marshaledFilteringOptions),
|
||||
},
|
||||
{
|
||||
Name: shared.AuthStatusEnvVar,
|
||||
Value: string(marshaledAuthStatus),
|
||||
},
|
||||
{
|
||||
Name: shared.MaxEntriesDBSizeBytesEnvVar,
|
||||
Value: strconv.FormatInt(opts.MaxEntriesDBSizeBytes, 10),
|
||||
|
||||
@@ -2,6 +2,7 @@ package shared
|
||||
|
||||
const (
|
||||
MizuFilteringOptionsEnvVar = "SENSITIVE_DATA_FILTERING_OPTIONS"
|
||||
AuthStatusEnvVar = "AUTH_STATUS"
|
||||
HostModeEnvVar = "HOST_MODE"
|
||||
NodeNameEnvVar = "NODE_NAME"
|
||||
TappedAddressesPerNodeDictEnvVar = "TAPPED_ADDRESSES_PER_HOST"
|
||||
|
||||
@@ -56,6 +56,11 @@ type TLSLinkInfo struct {
|
||||
ResolvedSourceName string `json:"resolvedSourceName"`
|
||||
}
|
||||
|
||||
type AuthStatus struct {
|
||||
Email string `json:"email"`
|
||||
Model string `json:"model"`
|
||||
}
|
||||
|
||||
func CreateWebSocketStatusMessage(tappingStatus TapStatus) WebSocketStatusMessage {
|
||||
return WebSocketStatusMessage{
|
||||
WebSocketMessageMetadata: &WebSocketMessageMetadata{
|
||||
|
||||
@@ -16,13 +16,12 @@
|
||||
line-height: 0.92
|
||||
margin-right: .5rem
|
||||
font-weight: 800
|
||||
color: $blue-color
|
||||
color: $main-background-color
|
||||
background-color: $light-blue-color
|
||||
&.expanded
|
||||
@extend .button
|
||||
line-height: .75rem
|
||||
background-color: $blue-color
|
||||
color: $main-background-color
|
||||
|
||||
.dataLine
|
||||
font-weight: 600
|
||||
|
||||
Reference in New Issue
Block a user