/* Copyright © 2026 Thomas von Dein This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ package es import ( "context" "fmt" "log/slog" "strings" "codeberg.org/scip/esctl/pkg/cfg" "codeberg.org/scip/esctl/pkg/printer" "github.com/elastic/go-elasticsearch/v9/typedapi/types" ) func RoleList(conf *cfg.Config) error { res, err := conf.DefaultCluster.ES.Security.GetRole(). Do(context.Background()) if err != nil { return fmt.Errorf("failed to get roles: %s", esErrorString(err)) } slog.Debug("ES result", "roles", res) table := printer.NewTable(conf, 3, len(res)) table.Addheaders("role", "index roles", "cluster roles") idx := 0 for name, role := range res { table.Entries[idx] = []string{ name, fmt.Sprintf("%d", len(role.Cluster)), fmt.Sprintf("%d", len(role.Indices)), } idx++ } table.Sort() if err := table.Print(); err != nil { return err } return nil } func RoleShow(conf *cfg.Config, rolename string) error { res, err := conf.DefaultCluster.ES.Security.GetRole(). Name(rolename). Do(context.Background()) if err != nil { return fmt.Errorf("failed to get role: %s", esErrorString(err)) } slog.Debug("ES result", "role", res) role, exists := res[rolename] if !exists { return fmt.Errorf("role %s does not exist", rolename) } if len(role.Indices) > 0 { if err := roleIndices(conf, role); err != nil { return err } fmt.Println() } if len(role.RemoteIndices) > 0 { if err := roleRemoteIndices(conf, role); err != nil { return err } fmt.Println() } if len(role.Cluster) > 0 { if err := roleClusters(conf, role); err != nil { return err } fmt.Println() } if len(role.RemoteCluster) > 0 { if err := roleRemoteClusters(conf, role); err != nil { return err } fmt.Println() } if len(role.Applications) > 0 { if err := roleApplications(conf, role); err != nil { return err } } return nil } func roleRemoteClusters(conf *cfg.Config, role types.Role) error { if len(role.RemoteCluster) == 0 { return nil } table := printer.NewTable(conf, 2, len(role.RemoteCluster)) table.Addheaders("remote cluster", "privilege") idx := 0 for _, priv := range role.RemoteCluster { perms := []string{} for _, perm := range priv.Privileges { perms = append(perms, perm.Name) } table.Entries[idx] = []string{ strings.Join(priv.Clusters, ","), strings.Join(perms, ","), } idx++ } table.Sort() return table.Print() } func roleClusters(conf *cfg.Config, role types.Role) error { if len(role.Cluster) == 0 { return nil } table := printer.NewTable(conf, 1, len(role.Cluster)) table.Addheaders("cluster rights") idx := 0 for _, cluster := range role.Cluster { table.Entries[idx] = []string{cluster.Name} idx++ } table.Sort() return table.Print() } func roleRemoteIndices(conf *cfg.Config, role types.Role) error { if len(role.RemoteIndices) == 0 { return nil } table := printer.NewTable(conf, 3, len(role.RemoteIndices)) table.Addheaders("remote index names", "index permissions", "allow restricted") idx := 0 for _, priv := range role.RemoteIndices { perms := []string{} for _, perm := range priv.Privileges { perms = append(perms, perm.Name) } table.Entries[idx] = []string{ strings.Join(priv.Names, ", "), strings.Join(perms, ", "), fmt.Sprintf("%t", *priv.AllowRestrictedIndices), } idx++ } table.Sort() return table.Print() } func roleIndices(conf *cfg.Config, role types.Role) error { if len(role.Indices) == 0 { return nil } table := printer.NewTable(conf, 3, len(role.Indices)) table.Addheaders("index names", "index permissions", "allow restricted") idx := 0 for _, priv := range role.Indices { perms := []string{} for _, perm := range priv.Privileges { perms = append(perms, perm.Name) } table.Entries[idx] = []string{ strings.Join(priv.Names, ", "), strings.Join(perms, ", "), fmt.Sprintf("%t", *priv.AllowRestrictedIndices), } idx++ } table.Sort() return table.Print() } func roleApplications(conf *cfg.Config, role types.Role) error { if len(role.Applications) == 0 { return nil } table := printer.NewTable(conf, 3, len(role.Applications)) table.Addheaders("application", "privileges", "resources") idx := 0 for _, priv := range role.Applications { table.Entries[idx] = []string{ priv.Application, strings.Join(priv.Privileges, ", "), strings.Join(priv.Resources, ", "), } idx++ } table.Sort() return table.Print() }