/* 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" "maps" "slices" "codeberg.org/scip/esctl/pkg/cfg" "codeberg.org/scip/esctl/pkg/printer" "github.com/elastic/go-elasticsearch/v9/typedapi/types" ) func RoleNames(conf *cfg.Config) ([]string, error) { res, err := conf.DefaultCluster.ES().Security.GetRole(). Do(context.Background()) if err != nil { return nil, fmt.Errorf("failed to get roles: %w", esErrorString(err)) } return slices.Collect(maps.Keys(res)), nil } 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: %w", 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] = []any{ name, role.Cluster, role.Indices, } idx++ } table.Sort() return table.Print() } 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: %w", 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] = []any{priv.Clusters, 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] = []any{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] = []any{priv.Names, perms, *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] = []any{priv.Names, perms, *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] = []any{ priv.Application, priv.Privileges, priv.Resources, } idx++ } table.Sort() return table.Print() }