223 lines
5.5 KiB
Go
223 lines
5.5 KiB
Go
package auth
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/influxdata/influx-cli/v2/pkg/tabwriter"
|
|
"github.com/influxdata/influxdb/v2"
|
|
"github.com/influxdata/influxdb/v2/authorization"
|
|
"github.com/influxdata/influxdb/v2/bolt"
|
|
"github.com/influxdata/influxdb/v2/logger"
|
|
"github.com/influxdata/influxdb/v2/tenant"
|
|
"github.com/spf13/cobra"
|
|
"go.uber.org/zap"
|
|
"go.uber.org/zap/zapcore"
|
|
)
|
|
|
|
func NewAuthCommand() *cobra.Command {
|
|
base := &cobra.Command{
|
|
Use: "auth",
|
|
Short: "On-disk authorization management commands, for recovery",
|
|
Args: cobra.NoArgs,
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
cmd.PrintErrf("See '%s -h' for help\n", cmd.CommandPath())
|
|
},
|
|
}
|
|
|
|
base.AddCommand(NewAuthListCommand())
|
|
base.AddCommand(NewAuthCreateCommand())
|
|
|
|
return base
|
|
}
|
|
|
|
type authListCommand struct {
|
|
logger *zap.Logger
|
|
boltPath string
|
|
out io.Writer
|
|
}
|
|
|
|
func NewAuthListCommand() *cobra.Command {
|
|
var authCmd authListCommand
|
|
cmd := &cobra.Command{
|
|
Use: "list",
|
|
Short: "List authorizations",
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
config := logger.NewConfig()
|
|
config.Level = zapcore.InfoLevel
|
|
|
|
newLogger, err := config.New(cmd.ErrOrStderr())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
authCmd.logger = newLogger
|
|
authCmd.out = cmd.OutOrStdout()
|
|
return authCmd.run()
|
|
},
|
|
}
|
|
|
|
defaultPath := filepath.Join(os.Getenv("HOME"), ".influxdbv2", "influxd.bolt")
|
|
|
|
cmd.Flags().StringVar(&authCmd.boltPath, "bolt-path", defaultPath, "Path to the BoltDB file.")
|
|
|
|
return cmd
|
|
}
|
|
|
|
func (cmd *authListCommand) run() error {
|
|
ctx := context.Background()
|
|
store := bolt.NewKVStore(cmd.logger.With(zap.String("system", "bolt-kvstore")), cmd.boltPath)
|
|
if err := store.Open(ctx); err != nil {
|
|
return err
|
|
}
|
|
defer store.Close()
|
|
tenantStore := tenant.NewStore(store)
|
|
tenantService := tenant.NewService(tenantStore)
|
|
authStore, err := authorization.NewStore(store)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
auth := authorization.NewService(authStore, tenantService)
|
|
filter := influxdb.AuthorizationFilter{}
|
|
auths, _, err := auth.FindAuthorizations(ctx, filter)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return PrintAuth(ctx, cmd.out, auths, tenantService)
|
|
}
|
|
|
|
type authCreateCommand struct {
|
|
logger *zap.Logger
|
|
boltPath string
|
|
out io.Writer
|
|
username string
|
|
org string
|
|
}
|
|
|
|
func NewAuthCreateCommand() *cobra.Command {
|
|
var authCmd authCreateCommand
|
|
cmd := &cobra.Command{
|
|
Use: "create-operator",
|
|
Short: "Create new operator token for a user",
|
|
RunE: func(cmd *cobra.Command, args []string) error {
|
|
config := logger.NewConfig()
|
|
config.Level = zapcore.InfoLevel
|
|
|
|
newLogger, err := config.New(cmd.ErrOrStderr())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
authCmd.logger = newLogger
|
|
authCmd.out = cmd.OutOrStdout()
|
|
return authCmd.run()
|
|
},
|
|
}
|
|
|
|
defaultPath := filepath.Join(os.Getenv("HOME"), ".influxdbv2", "influxd.bolt")
|
|
cmd.Flags().StringVar(&authCmd.boltPath, "bolt-path", defaultPath, "Path to the BoltDB file")
|
|
cmd.Flags().StringVar(&authCmd.username, "username", "", "Name of the user")
|
|
cmd.Flags().StringVar(&authCmd.org, "org", "", "Name of the org")
|
|
|
|
return cmd
|
|
}
|
|
|
|
func (cmd *authCreateCommand) run() error {
|
|
ctx := context.Background()
|
|
store := bolt.NewKVStore(cmd.logger.With(zap.String("system", "bolt-kvstore")), cmd.boltPath)
|
|
if err := store.Open(ctx); err != nil {
|
|
return err
|
|
}
|
|
defer store.Close()
|
|
tenantStore := tenant.NewStore(store)
|
|
tenantService := tenant.NewService(tenantStore)
|
|
authStore, err := authorization.NewStore(store)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
auth := authorization.NewService(authStore, tenantService)
|
|
|
|
if cmd.username == "" {
|
|
return fmt.Errorf("must provide --username")
|
|
}
|
|
if cmd.org == "" {
|
|
return fmt.Errorf("must provide --org")
|
|
}
|
|
|
|
// Find the user
|
|
user, err := tenantService.FindUser(ctx, influxdb.UserFilter{Name: &cmd.username})
|
|
if err != nil {
|
|
return fmt.Errorf("could not find user %q: %w", cmd.username, err)
|
|
}
|
|
|
|
orgs, _, err := tenantService.FindOrganizations(ctx, influxdb.OrganizationFilter{
|
|
Name: &cmd.org,
|
|
})
|
|
if err != nil {
|
|
return fmt.Errorf("could not find org %q: %w", cmd.org, err)
|
|
}
|
|
org := orgs[0]
|
|
|
|
// Create operator token
|
|
authToCreate := &influxdb.Authorization{
|
|
Description: fmt.Sprintf("%s's Recovery Token", cmd.username),
|
|
Permissions: influxdb.OperPermissions(),
|
|
UserID: user.ID,
|
|
OrgID: org.ID,
|
|
}
|
|
if err := auth.CreateAuthorization(ctx, authToCreate); err != nil {
|
|
return fmt.Errorf("could not create recovery token: %w", err)
|
|
}
|
|
|
|
// Print all authorizations now that we have added one
|
|
filter := influxdb.AuthorizationFilter{}
|
|
auths, _, err := auth.FindAuthorizations(ctx, filter)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return PrintAuth(ctx, cmd.out, auths, tenantService)
|
|
}
|
|
|
|
func PrintAuth(ctx context.Context, w io.Writer, v []*influxdb.Authorization, userSvc influxdb.UserService) error {
|
|
headers := []string{
|
|
"ID",
|
|
"User Name",
|
|
"User ID",
|
|
"Description",
|
|
"Token",
|
|
"Permissions",
|
|
}
|
|
|
|
var rows []map[string]interface{}
|
|
for _, t := range v {
|
|
user, err := userSvc.FindUserByID(ctx, t.UserID)
|
|
userName := ""
|
|
if err == nil && user != nil {
|
|
userName = user.Name
|
|
}
|
|
row := map[string]interface{}{
|
|
"ID": t.ID,
|
|
"Description": t.Description,
|
|
"User Name": userName,
|
|
"User ID": t.UserID,
|
|
"Token": t.Token,
|
|
"Permissions": t.Permissions,
|
|
}
|
|
rows = append(rows, row)
|
|
}
|
|
|
|
writer := tabwriter.NewTabWriter(w, false)
|
|
defer writer.Flush()
|
|
if err := writer.WriteHeaders(headers...); err != nil {
|
|
return err
|
|
}
|
|
for _, row := range rows {
|
|
if err := writer.Write(row); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|