Documentation ¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
View Source
var ( Run = &cli.Command{ Name: "run", Usage: "Runs the varys server process.", Flags: flagset.ExtractPrefix("varys", runConfig), ArgsUsage: " ", Action: func(ctx *cli.Context) error { log := zaputil.Extract(ctx.Context) if v := runConfig.Basic.StaticGroups.Value(); len(v) == 0 { _ = runConfig.Basic.StaticGroups.Set("admin:varys") } tlsConfig, err := livetls.New(ctx.Context, runConfig.TLS) if err != nil { return err } log.Info("configuring auth", zap.String("kind", runConfig.AuthType)) var authFn auth.HandlerFunc switch runConfig.AuthType { case "basic": authFn, err = basicauth.Handler(ctx.Context, runConfig.Basic) if err != nil { return err } case "oidc": return fmt.Errorf("oidc not yet supported") default: return fmt.Errorf("unsupported auth type: %s", runConfig.AuthType) } log.Info("opening database") encryptionKey := sha256.Sum256([]byte(runConfig.Database.Encryption.Key)) opts := badger.DefaultOptions(runConfig.Database.Path) opts.Logger = zaputil.Badger(log) opts.EncryptionKey = encryptionKey[:] opts.EncryptionKeyRotationDuration = runConfig.Database.Encryption.KeyDuration opts.IndexCacheSize = 128 << 20 db, err := badger.Open(opts) if err != nil { return err } defer db.Close() adapter := engine.NewCasbinAdapter(db) model, err := model.NewModelFromString(engine.Model) if err != nil { return err } enforcer, _ := casbin.NewEnforcer() enforcer.SetModel(model) enforcer.SetAdapter(adapter) enforcer.EnableAutoSave(true) enforcer.EnableAutoBuildRoleLinks(true) err = enforcer.LoadPolicy() if err != nil { return err } err = engine.EnsurePolicy(enforcer, engine.DefaultPolicy) if err != nil { return err } log.Info("setting up api") api := engine.NewAPI(db, enforcer, runConfig.Credential.RootKey) router := mux.NewRouter() router.StrictSlash(true) router.SkipClean(true) router.Use(mux.CORSMethodMiddleware(router)) apiRouter := router.PathPrefix("/api/").Subrouter() apiRouter.Use(func(handler http.Handler) http.Handler { handler = engine.Middleware(handler, api, runConfig.AuthType) handler = httpauth.Handler(handler, authFn, auth.Required()) handler = headers.HTTP(handler) return handler }) credentials := apiRouter.PathPrefix("/v1/credentials").Subrouter() credentials.HandleFunc("/{kind}/{name}", api.ListCredentials).Methods(http.MethodGet) services := apiRouter.PathPrefix("/v1/services").Subrouter() services.HandleFunc("", api.ListServices).Methods(http.MethodGet) services.HandleFunc("", api.CreateService).Methods(http.MethodPost) services.HandleFunc("/{kind}/{name}", api.GetService).Methods(http.MethodGet) services.HandleFunc("/{kind}/{name}", api.UpdateService).Methods(http.MethodPut) services.HandleFunc("/{kind}/{name}", api.DeleteService).Methods(http.MethodDelete) services.HandleFunc("/{kind}/{name}/credentials", api.GetServiceCredentials).Methods(http.MethodGet) services.HandleFunc("/{kind}/{name}/grants", api.ListGrants).Methods(http.MethodGet) services.HandleFunc("/{kind}/{name}/grants", api.PutGrant).Methods(http.MethodPut) services.HandleFunc("/{kind}/{name}/grants", api.DeleteGrant).Methods(http.MethodDelete) users := apiRouter.PathPrefix("/v1/users").Subrouter() users.HandleFunc("", api.ListUsers).Methods(http.MethodGet) users.HandleFunc("/self", api.GetCurrentUser).Methods(http.MethodGet) users.HandleFunc("/self", api.UpdateCurrentUser).Methods(http.MethodPut) group, done := errgroup.WithContext(ctx.Context) group.Go(func() error { listener, err := net.Listen("tcp", runConfig.BindAddress) if err != nil { return err } if tlsConfig != nil { log.Info("setting up tls") listener = tls.NewListener(listener, tlsConfig) } svr := &http.Server{ Handler: router, BaseContext: func(listener net.Listener) context.Context { return ctx.Context }, } return svr.Serve(listener) }) log.Info("starting", zap.String("address", runConfig.BindAddress)) if log.Core().Enabled(zapcore.DebugLevel) { _ = router.Walk(func(route *mux.Route, router *mux.Router, ancestors []*mux.Route) error { path, _ := route.GetPathTemplate() methods, _ := route.GetMethods() if len(methods) > 0 { log.Debug("route", zap.String("path", path), zap.Strings("methods", methods)) } return nil }) } select { case <-done.Done(): return group.Wait() case <-ctx.Done(): } return nil }, HideHelpCommand: true, } )
View Source
var ( Services = &cli.Command{ Name: "services", Usage: "Perform operations against the Services API.", Flags: flagset.ExtractPrefix("varys", &client.DefaultConfig), Before: func(ctx *cli.Context) error { api, err := client.NewAPI(client.DefaultConfig) if err != nil { return err } ctx.Context = client.WithContext(ctx.Context, api) return nil }, Subcommands: []*cli.Command{ { Name: "connect", Usage: "Connects to a service managed by varys.", ArgsUsage: "<kind> <name> [program...]", Action: func(ctx *cli.Context) error { args := ctx.Args().Slice() switch { case len(args) < 2: return fmt.Errorf("expecting two arguments: <kind> <name>") case len(args) < 3: return fmt.Errorf("missing program to execute") } kind := args[0] name := args[1] program := args[2:] api := client.Extract(ctx.Context) serviceCreds, err := api.Services().Credentials(ctx.Context, kind, name) if err != nil { return err } pargs := make([]string, 0) if len(program) > 1 { pargs = program[1:] } prefix := strings.ToUpper(kind) + "_" + strings.ToUpper(name) cmd := exec.Command(program[0], pargs...) cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr cmd.Env = append(cmd.Env, prefix+"_ADDRESS="+serviceCreds.Address, prefix+"_USERNAME="+serviceCreds.Credentials.Username, prefix+"_PASSWORD="+serviceCreds.Credentials.Password, ) err = cmd.Run() if err != nil { return err } return nil }, }, { Name: "create", Usage: "Create a new service in varys.", ArgsUsage: "<kind> <name>", Flags: flagset.ExtractPrefix("varys_create_service", &createServiceRequest), Action: func(ctx *cli.Context) error { args := ctx.Args() createServiceRequest.Kind = args.Get(0) createServiceRequest.Name = args.Get(1) if createServiceRequest.Kind == "" || createServiceRequest.Name == "" { return fmt.Errorf("expecting two arguments: <kind> <name>") } api := client.Extract(ctx.Context) return api.Services().Create(ctx.Context, createServiceRequest) }, }, { Name: "delete", Usage: "Delete a service in varys.", ArgsUsage: "<kind> <name>", Action: func(ctx *cli.Context) error { args := ctx.Args() kind := args.Get(0) name := args.Get(1) if kind == "" || name == "" { return fmt.Errorf("expecting two arguments: <kind> <name>") } api := client.Extract(ctx.Context) return api.Services().Delete(ctx.Context, kind, name) }, }, { Name: "get", Usage: "Get a service from varys.", ArgsUsage: "<kind> <name>", Action: func(ctx *cli.Context) error { args := ctx.Args() kind := args.Get(0) name := args.Get(1) if kind == "" || name == "" { return fmt.Errorf("expecting two arguments: <kind> <name>") } api := client.Extract(ctx.Context) service, err := api.Services().Get(ctx.Context, kind, name) if err != nil { return err } table := newTable(ctx.App.Writer) table.Append([]string{"KIND", service.Kind}) table.Append([]string{"NAME", service.Name}) table.Append([]string{"ADDRESS", service.Address}) table.Append([]string{"USER TEMPLATE", string(service.Templates.UserTemplate)}) table.Append([]string{"PASSWORD TEMPLATE", string(service.Templates.PasswordTemplate)}) table.Render() return nil }, }, { Name: "grants", Usage: "Manage who has access to a given service.", Subcommands: []*cli.Command{ { Name: "list", Usage: "List all users who have access to a service and their permissions.", ArgsUsage: " ", Action: func(ctx *cli.Context) error { args := ctx.Args() kind := args.Get(0) name := args.Get(1) if kind == "" || name == "" { return fmt.Errorf("expecting two arguments: <kind> <name>") } api := client.Extract(ctx.Context) grants, err := api.Services().Grants().List(ctx.Context, kind, name) if err != nil { return err } table := newTable(ctx.App.Writer) table.SetHeader([]string{"UserKind", "UserID", "UserName", "Roles"}) for _, grant := range grants { table.Append([]string{ grant.User.Kind, grant.User.Name, grant.User.ID, strings.Join(grant.Roles, ", "), }) } table.Render() return nil }, }, { Name: "update", Usage: "Update a user's access to a service in varys.", ArgsUsage: "<kind> <name>", Flags: flagset.ExtractPrefix("varys_update_service_grant", &updateGrantRequest), Action: func(ctx *cli.Context) error { args := ctx.Args() kind := args.Get(0) name := args.Get(1) if kind == "" || name == "" { return fmt.Errorf("expecting two arguments: <kind> <name>") } permissions := updateGrantRequest.Permission.Value() if len(permissions) == 0 { return fmt.Errorf("must provide at least one permission") } suffix := fmt.Sprintf("%s:%s", kind, name) roles := make([]string, 0) for _, permission := range permissions { roles = append(roles, permission+":"+suffix) } api := client.Extract(ctx.Context) return api.Services().Grants().Update(ctx.Context, kind, name, engine.UserGrant{ User: engine.User{ Kind: updateGrantRequest.User.Kind, ID: updateGrantRequest.User.ID, }, Roles: roles, }) }, }, { Name: "delete", Usage: "Remove a user's access to a service in varys.", ArgsUsage: "<kind> <name>", Flags: flagset.ExtractPrefix("varys_delete_service_grant", &deleteGrantRequest), Action: func(ctx *cli.Context) error { args := ctx.Args() kind := args.Get(0) name := args.Get(1) if kind == "" || name == "" { return fmt.Errorf("expecting two arguments: <kind> <name>") } permissions := updateGrantRequest.Permission.Value() if len(permissions) == 0 { return fmt.Errorf("must provide at least one permission") } suffix := fmt.Sprintf("%s:%s", kind, name) roles := make([]string, 0) for _, permission := range permissions { roles = append(roles, permission+":"+suffix) } api := client.Extract(ctx.Context) return api.Services().Grants().Delete(ctx.Context, kind, name, engine.UserGrant{ User: engine.User{ Kind: updateGrantRequest.User.Kind, ID: updateGrantRequest.User.ID, }, Roles: roles, }) }, }, }, }, { Name: "list", Usage: "List all services managed by varys.", ArgsUsage: " ", Action: func(ctx *cli.Context) error { api := client.Extract(ctx.Context) services, err := api.Services().List(ctx.Context) if err != nil { return err } table := newTable(ctx.App.Writer) table.SetHeader([]string{"Kind", "Name", "Address"}) for _, service := range services { table.Append([]string{service.Kind, service.Name, service.Address}) } table.Render() return nil }, }, { Name: "update", Usage: "Update a service in varys.", ArgsUsage: "<kind> <name>", Flags: flagset.ExtractPrefix("varys_update_service", &updateServiceRequest), Action: func(ctx *cli.Context) error { args := ctx.Args() kind := args.Get(0) name := args.Get(1) if kind == "" || name == "" { return fmt.Errorf("expecting two arguments: <kind> <name>") } api := client.Extract(ctx.Context) return api.Services().Update(ctx.Context, kind, name, updateServiceRequest) }, }, }, HideHelpCommand: true, } )
View Source
var ( Users = &cli.Command{ Name: "users", Usage: "Perform operations against the Users API.", Flags: flagset.ExtractPrefix("varys", &client.DefaultConfig), Before: func(ctx *cli.Context) error { api, err := client.NewAPI(client.DefaultConfig) if err != nil { return err } ctx.Context = client.WithContext(ctx.Context, api) return nil }, Subcommands: []*cli.Command{ { Name: "list", Usage: "List all users known to varys.", ArgsUsage: " ", Action: func(ctx *cli.Context) error { api := client.Extract(ctx.Context) users, err := api.Users().List(ctx.Context) if err != nil { return err } table := newTable(ctx.App.Writer) table.SetHeader([]string{"Kind", "ID", "Name"}) for _, user := range users { table.Append([]string{user.Kind, user.ID, user.Name}) } table.Render() return nil }, }, { Name: "current", Usage: "Interact with the currently authenticated user.", Subcommands: []*cli.Command{ { Name: "get", Usage: "Output information about the current user.", ArgsUsage: " ", Action: func(ctx *cli.Context) error { api := client.Extract(ctx.Context) user, err := api.Users().Current().Get(ctx.Context) if err != nil { return err } table := newTable(ctx.App.Writer) table.Append([]string{"ID", user.Subject}) table.Append([]string{"PROFILE", user.Profile}) table.Append([]string{"EMAIL", user.Email}) table.Append([]string{"EMAIL VERIFIED", strconv.FormatBool(user.EmailVerified)}) table.Append([]string{"GROUPS", strings.Join(user.Groups, ", ")}) table.Render() return nil }, }, { Name: "update", Usage: "Update information about the current user.", ArgsUsage: " ", Flags: flagset.ExtractPrefix("varys_update_user", &updateUserRequest), Action: func(ctx *cli.Context) error { api := client.Extract(ctx.Context) return api.Users().Current().Update(ctx.Context, engine.UpdateUserRequest{ RotateService: engine.Service{ Kind: updateUserRequest.RotateServiceKind, Name: updateUserRequest.RotateServiceName, }, }) }, }, }, }, }, HideHelpCommand: true, } )
View Source
var Version = &cli.Command{ Name: "version", Usage: "Print the binary version information.", UsageText: "varys version", Action: func(ctx *cli.Context) error { return template. Must(template.New("version").Parse(versionTemplate)). Execute(ctx.App.Writer, ctx.App) }, HideHelpCommand: true, }
Functions ¶
This section is empty.
Types ¶
type CredentialConfig ¶
type CredentialConfig struct {
RootKey string `json:"root_key" usage:"specify the root key used to derive credentials from"`
}
type DatabaseConfig ¶
type DatabaseConfig struct { Path string `json:"path" usage:"configure the path to the database" default:"db.badger"` Encryption EncryptionConfig `json:"encryption" ` }
type EncryptionConfig ¶
type RunConfig ¶
type RunConfig struct { BindAddress string `json:"bind_address" usage:"specify the address to bind to" default:"localhost:3456"` TLS livetls.Config `json:"tls"` Database DatabaseConfig `json:"database"` Credential CredentialConfig `json:"credential"` auth.Config Basic basicauth.Config `json:"basic"` }
type UpdateUserRequest ¶
Click to show internal directories.
Click to hide internal directories.