...
1 package view
2
3 import (
4 "context"
5 "encoding/json"
6 "fmt"
7 "slices"
8
9 "github.com/shurcooL/graphql"
10
11 "edge-infra.dev/pkg/edge/api/client"
12 "edge-infra.dev/pkg/edge/api/graph/model"
13 "edge-infra.dev/pkg/edge/edgeadmin/commands/operatorintervention/edgeextension"
14 "edge-infra.dev/pkg/edge/edgecli"
15 "edge-infra.dev/pkg/edge/edgecli/flagutil"
16 "edge-infra.dev/pkg/lib/cli/command"
17 "edge-infra.dev/pkg/lib/cli/rags"
18 )
19
20 const (
21 longHelpStr = `
22 This command returns a readable JSON-formatted summary of all role mappings and their allowed commands from the database.
23
24 $ edgeadmin operatorintervention view summary
25
26 By default this command will return a summary of all roles on the database, but you can also specify just a subset of roles
27 using any number of optional --role flags.
28
29 $ edgeadmin operatorintervention view summary --role role1 --role role2 --role role3
30 `
31 )
32
33 type RoleConfiguration struct {
34 Role string
35 Privileges []model.Rule
36 }
37
38 func NewSummary(cfg *edgecli.Config) *command.Command {
39 var (
40 edge = &edgeextension.Ext{Cfg: cfg}
41 roles []string
42 )
43
44 return &command.Command{
45 ShortUsage: "edgeadmin operatorintervention view summary [--role <role>]",
46 ShortHelp: "view the summary of the full operator intervention rules configuration",
47 LongHelp: longHelpStr,
48 Flags: []*rags.Rag{
49 {
50 Name: flagutil.RoleFlag,
51 Usage: "(optional) filter results by edge role name",
52 Value: &rags.StringSet{
53 Var: &roles,
54 },
55 },
56 },
57
58 Extensions: []command.Extension{
59 edge,
60 },
61
62 Exec: func(ctx context.Context, _ []string) error {
63 roleMappings, rules, err := retrieveRolesAndRules(ctx, edge.Client, roles)
64 if err != nil {
65 return err
66 }
67
68 roleConfigs := assembleRoleConfigurations(roleMappings, rules)
69 output, err := json.MarshalIndent(roleConfigs, "", " ")
70 if err != nil {
71 return err
72 }
73
74 fmt.Println(string(output))
75
76 return nil
77 },
78 }
79 }
80
81
82
83 func retrieveRolesAndRules(ctx context.Context, bffClient *client.EdgeClient, roles []string) ([]model.OiRoleMapping, []model.Rule, error) {
84 var query struct {
85 OiRoleMappings []model.OiRoleMapping `graphql:"operatorInterventionRoleMappings(roles: $roles)"`
86 Rules []model.Rule `graphql:"operatorInterventionRules"`
87 }
88
89 graphqlRoles := []graphql.String{}
90 for _, role := range roles {
91 graphqlRoles = append(graphqlRoles, graphql.String(role))
92 }
93 variables := map[string]any{
94 "roles": graphqlRoles,
95 }
96
97 err := bffClient.Query(ctx, &query, variables)
98 if err != nil {
99 return nil, nil, fmt.Errorf("error calling Edge API: %w", err)
100 }
101 return query.OiRoleMappings, query.Rules, nil
102 }
103
104
105 func assembleRoleConfigurations(roleMappings []model.OiRoleMapping, rules []model.Rule) []RoleConfiguration {
106 var roleConfigs []RoleConfiguration
107 for _, roleMapping := range roleMappings {
108
109 roleConfig := assembleRulesForRole(roleMapping, rules)
110 roleConfigs = append(roleConfigs, roleConfig)
111 }
112 return roleConfigs
113 }
114
115
116 func assembleRulesForRole(roleMapping model.OiRoleMapping, rules []model.Rule) RoleConfiguration {
117 roleConfig := RoleConfiguration{Role: roleMapping.Role.String()}
118 for _, priv := range roleMapping.Privileges {
119 rule := model.Rule{Privilege: priv}
120
121 if slices.ContainsFunc(rules, func(r model.Rule) bool {
122 rule.Commands = r.Commands
123 return *r.Privilege == *priv
124 }) {
125 roleConfig.Privileges = append(roleConfig.Privileges, rule)
126 }
127 }
128 return roleConfig
129 }
130
View as plain text