feat: port influx auth
command (#152)
This commit is contained in:
442
clients/auth/auth.go
Normal file
442
clients/auth/auth.go
Normal file
@ -0,0 +1,442 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/influxdata/influx-cli/v2/api"
|
||||
"github.com/influxdata/influx-cli/v2/clients"
|
||||
"github.com/influxdata/influx-cli/v2/pkg/influxid"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
clients.CLI
|
||||
api.AuthorizationsApi
|
||||
api.UsersApi
|
||||
api.OrganizationsApi
|
||||
}
|
||||
|
||||
const (
|
||||
ReadAction = "read"
|
||||
WriteAction = "write"
|
||||
)
|
||||
|
||||
type token struct {
|
||||
ID string `json:"id"`
|
||||
Description string `json:"description"`
|
||||
Token string `json:"token"`
|
||||
Status string `json:"status"`
|
||||
UserName string `json:"userName"`
|
||||
UserID string `json:"userID"`
|
||||
Permissions []string `json:"permissions"`
|
||||
}
|
||||
|
||||
type printParams struct {
|
||||
deleted bool
|
||||
token *token
|
||||
tokens []token
|
||||
}
|
||||
|
||||
type CreateParams struct {
|
||||
clients.OrgParams
|
||||
User string
|
||||
Description string
|
||||
|
||||
WriteUserPermission bool
|
||||
ReadUserPermission bool
|
||||
|
||||
WriteBucketsPermission bool
|
||||
ReadBucketsPermission bool
|
||||
|
||||
WriteBucketIds []string
|
||||
ReadBucketIds []string
|
||||
|
||||
WriteTasksPermission bool
|
||||
ReadTasksPermission bool
|
||||
|
||||
WriteTelegrafsPermission bool
|
||||
ReadTelegrafsPermission bool
|
||||
|
||||
WriteOrganizationsPermission bool
|
||||
ReadOrganizationsPermission bool
|
||||
|
||||
WriteDashboardsPermission bool
|
||||
ReadDashboardsPermission bool
|
||||
|
||||
WriteCheckPermission bool
|
||||
ReadCheckPermission bool
|
||||
|
||||
WriteNotificationRulePermission bool
|
||||
ReadNotificationRulePermission bool
|
||||
|
||||
WriteNotificationEndpointPermission bool
|
||||
ReadNotificationEndpointPermission bool
|
||||
|
||||
WriteDBRPPermission bool
|
||||
ReadDBRPPermission bool
|
||||
}
|
||||
|
||||
func (c Client) Create(ctx context.Context, params *CreateParams) error {
|
||||
|
||||
orgID, err := c.getOrgID(ctx, params.OrgParams)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bucketPerms := []struct {
|
||||
action string
|
||||
perms []string
|
||||
}{
|
||||
{action: ReadAction, perms: params.ReadBucketIds},
|
||||
{action: WriteAction, perms: params.WriteBucketIds},
|
||||
}
|
||||
|
||||
var permissions []api.Permission
|
||||
for _, bp := range bucketPerms {
|
||||
for _, p := range bp.perms {
|
||||
// verify the input ID
|
||||
if _, err := influxid.IDFromString(p); err != nil {
|
||||
return fmt.Errorf("invalid bucket ID '%s': %w (did you pass a bucket name instead of an ID?)", p, err)
|
||||
}
|
||||
|
||||
newPerm := api.Permission{
|
||||
Action: bp.action,
|
||||
Resource: makePermResource("buckets", p, orgID),
|
||||
}
|
||||
permissions = append(permissions, newPerm)
|
||||
}
|
||||
}
|
||||
|
||||
providedPerm := []struct {
|
||||
readPerm, writePerm bool
|
||||
resourceType string
|
||||
}{
|
||||
{
|
||||
readPerm: params.ReadBucketsPermission,
|
||||
writePerm: params.WriteBucketsPermission,
|
||||
resourceType: "buckets",
|
||||
},
|
||||
{
|
||||
readPerm: params.ReadCheckPermission,
|
||||
writePerm: params.WriteCheckPermission,
|
||||
resourceType: "checks",
|
||||
},
|
||||
{
|
||||
readPerm: params.ReadDashboardsPermission,
|
||||
writePerm: params.WriteDashboardsPermission,
|
||||
resourceType: "dashboards",
|
||||
},
|
||||
{
|
||||
readPerm: params.ReadNotificationEndpointPermission,
|
||||
writePerm: params.WriteNotificationEndpointPermission,
|
||||
resourceType: "notificationEndpoints",
|
||||
},
|
||||
{
|
||||
readPerm: params.ReadNotificationRulePermission,
|
||||
writePerm: params.WriteNotificationRulePermission,
|
||||
resourceType: "notificationRules",
|
||||
},
|
||||
{
|
||||
readPerm: params.ReadOrganizationsPermission,
|
||||
writePerm: params.WriteOrganizationsPermission,
|
||||
resourceType: "orgs",
|
||||
},
|
||||
{
|
||||
readPerm: params.ReadTasksPermission,
|
||||
writePerm: params.WriteTasksPermission,
|
||||
resourceType: "tasks",
|
||||
},
|
||||
{
|
||||
readPerm: params.ReadTelegrafsPermission,
|
||||
writePerm: params.WriteTelegrafsPermission,
|
||||
resourceType: "telegrafs",
|
||||
},
|
||||
{
|
||||
readPerm: params.ReadUserPermission,
|
||||
writePerm: params.WriteUserPermission,
|
||||
resourceType: "users",
|
||||
},
|
||||
{
|
||||
readPerm: params.ReadDBRPPermission,
|
||||
writePerm: params.WriteDBRPPermission,
|
||||
resourceType: "dbrp",
|
||||
},
|
||||
}
|
||||
|
||||
for _, provided := range providedPerm {
|
||||
var actions []string
|
||||
if provided.readPerm {
|
||||
actions = append(actions, ReadAction)
|
||||
}
|
||||
if provided.writePerm {
|
||||
actions = append(actions, WriteAction)
|
||||
}
|
||||
|
||||
for _, action := range actions {
|
||||
p := api.Permission{
|
||||
Action: action,
|
||||
Resource: makePermResource(provided.resourceType, "", orgID),
|
||||
}
|
||||
permissions = append(permissions, p)
|
||||
}
|
||||
}
|
||||
|
||||
// Get the user ID because the command only takes a username, not ID
|
||||
users, err := c.UsersApi.GetUsers(ctx).Name(params.User).Execute()
|
||||
if err != nil || len(users.GetUsers()) == 0 {
|
||||
return fmt.Errorf("could not find user with name %q: %w", params.User, err)
|
||||
}
|
||||
userID := users.GetUsers()[0].GetId()
|
||||
|
||||
authReq := api.AuthorizationPostRequest{
|
||||
OrgID: orgID,
|
||||
UserID: &userID,
|
||||
Permissions: permissions,
|
||||
}
|
||||
if params.Description != "" {
|
||||
authReq.SetDescription(params.Description)
|
||||
}
|
||||
|
||||
auth, err := c.PostAuthorizations(ctx).AuthorizationPostRequest(authReq).Execute()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not write auth with provided arguments: %w", err)
|
||||
}
|
||||
|
||||
ps := make([]string, 0, len(auth.GetPermissions()))
|
||||
for _, p := range auth.GetPermissions() {
|
||||
ps = append(ps, p.String())
|
||||
}
|
||||
|
||||
return c.printAuth(printParams{
|
||||
token: &token{
|
||||
ID: auth.GetId(),
|
||||
Description: auth.GetDescription(),
|
||||
Token: auth.GetToken(),
|
||||
Status: auth.GetStatus(),
|
||||
UserName: auth.GetUser(),
|
||||
UserID: auth.GetUserID(),
|
||||
Permissions: ps,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (c Client) Remove(ctx context.Context, authID string) error {
|
||||
// check if auth exists first for better error logging, and to
|
||||
// acquire the auth that was deleted since the delete
|
||||
// request does not return the Authorization object.
|
||||
a, err := c.GetAuthorizationsID(ctx, authID).Execute()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not find auth with ID %q: %w", authID, err)
|
||||
}
|
||||
|
||||
if err := c.DeleteAuthorizationsID(ctx, authID).Execute(); err != nil {
|
||||
return fmt.Errorf("could not remove auth with ID %q: %w", authID, err)
|
||||
}
|
||||
|
||||
ps := make([]string, 0, len(a.Permissions))
|
||||
for _, p := range a.Permissions {
|
||||
ps = append(ps, p.String())
|
||||
}
|
||||
|
||||
return c.printAuth(printParams{
|
||||
deleted: true,
|
||||
token: &token{
|
||||
ID: a.GetId(),
|
||||
Description: a.GetDescription(),
|
||||
Token: a.GetToken(),
|
||||
Status: a.GetStatus(),
|
||||
UserName: a.GetUser(),
|
||||
UserID: a.GetUserID(),
|
||||
Permissions: ps,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
type ListParams struct {
|
||||
clients.OrgParams
|
||||
Id string
|
||||
User string
|
||||
UserID string
|
||||
}
|
||||
|
||||
func (c Client) List(ctx context.Context, params *ListParams) error {
|
||||
|
||||
// If ID parameter is set, search by that over other filters
|
||||
if params.Id != "" {
|
||||
return c.findAuthorization(ctx, params.Id)
|
||||
}
|
||||
|
||||
req := c.GetAuthorizations(ctx)
|
||||
if params.User != "" {
|
||||
req.User(params.User)
|
||||
}
|
||||
if params.UserID != "" {
|
||||
req.UserID(params.UserID)
|
||||
}
|
||||
if params.OrgName != "" {
|
||||
req.Org(params.OrgName)
|
||||
}
|
||||
if params.OrgID.Valid() {
|
||||
req.OrgID(params.OrgID.String())
|
||||
}
|
||||
|
||||
auths, err := req.Execute()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not find authorization with given parameters: %w", err)
|
||||
}
|
||||
|
||||
var tokens []token
|
||||
for _, a := range auths.GetAuthorizations() {
|
||||
var ps []string
|
||||
for _, p := range a.GetPermissions() {
|
||||
ps = append(ps, p.String())
|
||||
}
|
||||
|
||||
tokens = append(tokens, token{
|
||||
ID: a.GetId(),
|
||||
Description: a.GetDescription(),
|
||||
Token: a.GetToken(),
|
||||
Status: a.GetStatus(),
|
||||
UserName: a.GetUser(),
|
||||
UserID: a.GetUserID(),
|
||||
Permissions: ps,
|
||||
})
|
||||
}
|
||||
|
||||
return c.printAuth(printParams{tokens: tokens})
|
||||
}
|
||||
|
||||
func (c Client) findAuthorization(ctx context.Context, authID string) error {
|
||||
a, err := c.GetAuthorizationsID(ctx, authID).Execute()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not find authorization with ID %q: %w", authID, err)
|
||||
}
|
||||
|
||||
ps := make([]string, 0, len(a.GetPermissions()))
|
||||
for _, p := range a.GetPermissions() {
|
||||
ps = append(ps, p.String())
|
||||
}
|
||||
|
||||
return c.printAuth(printParams{
|
||||
token: &token{
|
||||
ID: a.GetId(),
|
||||
Description: a.GetDescription(),
|
||||
Token: a.GetToken(),
|
||||
Status: a.GetStatus(),
|
||||
UserName: a.GetUser(),
|
||||
UserID: a.GetUserID(),
|
||||
Permissions: ps,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (c Client) SetActive(ctx context.Context, authID string, active bool) error {
|
||||
|
||||
// check if auth exists first for better error logging
|
||||
if _, err := c.GetAuthorizationsID(ctx, authID).Execute(); err != nil {
|
||||
return fmt.Errorf("could not find auth with ID %q: %w", authID, err)
|
||||
}
|
||||
|
||||
var status string
|
||||
if active {
|
||||
status = "active"
|
||||
} else {
|
||||
status = "inactive"
|
||||
}
|
||||
a, err := c.PatchAuthorizationsID(ctx, authID).
|
||||
AuthorizationUpdateRequest(api.AuthorizationUpdateRequest{Status: &status}).
|
||||
Execute()
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not update status of auth with ID %q: %w", authID, err)
|
||||
}
|
||||
|
||||
ps := make([]string, 0, len(a.GetPermissions()))
|
||||
for _, p := range a.GetPermissions() {
|
||||
ps = append(ps, p.String())
|
||||
}
|
||||
|
||||
return c.printAuth(printParams{
|
||||
token: &token{
|
||||
ID: a.GetId(),
|
||||
Description: a.GetDescription(),
|
||||
Token: a.GetToken(),
|
||||
Status: a.GetStatus(),
|
||||
UserName: a.GetUser(),
|
||||
UserID: a.GetUserID(),
|
||||
Permissions: ps,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (c Client) printAuth(opts printParams) error {
|
||||
if c.PrintAsJSON {
|
||||
var v interface{}
|
||||
if opts.token != nil {
|
||||
v = opts.token
|
||||
} else {
|
||||
v = opts.tokens
|
||||
}
|
||||
return c.PrintJSON(v)
|
||||
}
|
||||
|
||||
headers := []string{
|
||||
"ID",
|
||||
"Description",
|
||||
"Token",
|
||||
"User Name",
|
||||
"User ID",
|
||||
"Permissions",
|
||||
}
|
||||
if opts.deleted {
|
||||
headers = append(headers, "Deleted")
|
||||
}
|
||||
|
||||
if opts.token != nil {
|
||||
opts.tokens = append(opts.tokens, *opts.token)
|
||||
}
|
||||
|
||||
var rows []map[string]interface{}
|
||||
for _, t := range opts.tokens {
|
||||
row := map[string]interface{}{
|
||||
"ID": t.ID,
|
||||
"Description": t.Description,
|
||||
"Token": t.Token,
|
||||
"User Name": t.UserName,
|
||||
"User ID": t.UserID,
|
||||
"Permissions": t.Permissions,
|
||||
}
|
||||
if opts.deleted {
|
||||
row["Deleted"] = true
|
||||
}
|
||||
rows = append(rows, row)
|
||||
}
|
||||
return c.PrintTable(headers, rows...)
|
||||
}
|
||||
|
||||
func makePermResource(permType string, id string, orgId string) api.PermissionResource {
|
||||
return api.PermissionResource{
|
||||
Type: permType,
|
||||
Id: &id,
|
||||
OrgID: &orgId,
|
||||
}
|
||||
}
|
||||
|
||||
func (c Client) getOrgID(ctx context.Context, params clients.OrgParams) (string, error) {
|
||||
if !params.OrgID.Valid() && params.OrgName == "" && c.ActiveConfig.Org == "" {
|
||||
return "", clients.ErrMustSpecifyOrg
|
||||
}
|
||||
if params.OrgID.Valid() {
|
||||
return params.OrgID.String(), nil
|
||||
}
|
||||
name := params.OrgName
|
||||
if name == "" {
|
||||
name = c.ActiveConfig.Org
|
||||
}
|
||||
org, err := c.GetOrgs(ctx).Org(name).Execute()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to lookup org with name %q: %w", name, err)
|
||||
}
|
||||
if len(org.GetOrgs()) == 0 {
|
||||
return "", fmt.Errorf("no organization with name %q: %w", name, err)
|
||||
}
|
||||
return org.GetOrgs()[0].GetId(), nil
|
||||
}
|
Reference in New Issue
Block a user