17
17
KubectlReadOperations = []string {
18
18
"get" , "describe" , "explain" , "logs" , "top" , "auth" , "config" ,
19
19
"cluster-info" , "api-resources" , "api-versions" , "version" , "diff" ,
20
- "completion" , "help" , "kustomize" , "options" , "plugin" , "proxy" , "wait" , "cp" ,
20
+ "completion" , "help" , "kustomize" , "options" , "plugin" , "proxy" , "wait" , "events" ,
21
+ }
22
+
23
+ // KubectlReadWriteOperations defines kubectl operations that modify state but are not admin operations
24
+ KubectlReadWriteOperations = []string {
25
+ "create" , "delete" , "apply" , "expose" , "run" , "set" , "rollout" , "scale" ,
26
+ "autoscale" , "label" , "annotate" , "patch" , "replace" , "cp" , "exec" ,
27
+ }
28
+
29
+ // KubectlAdminOperations defines kubectl operations that require admin privileges
30
+ KubectlAdminOperations = []string {
31
+ "cordon" , "uncordon" , "drain" , "taint" , "certificate" ,
21
32
}
22
33
23
34
// HelmReadOperations defines helm operations that don't modify state
@@ -69,12 +80,46 @@ func (v *Validator) getReadOperationsList(commandType string) []string {
69
80
}
70
81
}
71
82
83
+ // getReadWriteOperationsList returns the appropriate list of read-write operations based on command type
84
+ func (v * Validator ) getReadWriteOperationsList (commandType string ) []string {
85
+ switch commandType {
86
+ case CommandTypeKubectl :
87
+ return KubectlReadWriteOperations
88
+ case CommandTypeHelm :
89
+ // For now, assume helm write operations are same as read operations
90
+ // This can be expanded when helm write operations are defined
91
+ return []string {}
92
+ case CommandTypeCilium :
93
+ // For now, assume cilium write operations are same as read operations
94
+ // This can be expanded when cilium write operations are defined
95
+ return []string {}
96
+ default :
97
+ return []string {}
98
+ }
99
+ }
100
+
101
+ // getAdminOperationsList returns the appropriate list of admin operations based on command type
102
+ func (v * Validator ) getAdminOperationsList (commandType string ) []string {
103
+ switch commandType {
104
+ case CommandTypeKubectl :
105
+ return KubectlAdminOperations
106
+ case CommandTypeHelm :
107
+ // For now, assume helm admin operations are not defined
108
+ // This can be expanded when helm admin operations are defined
109
+ return []string {}
110
+ case CommandTypeCilium :
111
+ // For now, assume cilium admin operations are not defined
112
+ // This can be expanded when cilium admin operations are defined
113
+ return []string {}
114
+ default :
115
+ return []string {}
116
+ }
117
+ }
118
+
72
119
// ValidateCommand validates a command against all security settings
73
120
func (v * Validator ) ValidateCommand (command , commandType string ) error {
74
- readOperations := v .getReadOperationsList (commandType )
75
-
76
- // Check readonly restrictions
77
- if err := v .validateReadOnly (command , readOperations ); err != nil {
121
+ // Check access level restrictions
122
+ if err := v .validateAccessLevel (command , commandType ); err != nil {
78
123
return err
79
124
}
80
125
@@ -86,11 +131,36 @@ func (v *Validator) ValidateCommand(command, commandType string) error {
86
131
return nil
87
132
}
88
133
89
- // validateReadOnly validates if a command is allowed in read-only mode
90
- func (v * Validator ) validateReadOnly (command string , readOperations []string ) error {
91
- // Check if we're in readonly mode and if this is a write operation
92
- if v .secConfig .ReadOnly && ! v .isReadOperation (command , readOperations ) {
93
- return & ValidationError {Message : "Error: Cannot execute write operations in read-only mode" }
134
+ // validateAccessLevel validates if a command is allowed based on the configured access level
135
+ func (v * Validator ) validateAccessLevel (command , commandType string ) error {
136
+ readOperations := v .getReadOperationsList (commandType )
137
+ readWriteOperations := v .getReadWriteOperationsList (commandType )
138
+ adminOperations := v .getAdminOperationsList (commandType )
139
+
140
+ operation := v .extractOperationFromCommand (command , commandType )
141
+
142
+ switch v .secConfig .AccessLevel {
143
+ case AccessLevelReadOnly :
144
+ if ! v .isOperationInList (operation , readOperations ) {
145
+ return & ValidationError {Message : "Error: Cannot execute write or admin operations in read-only mode" }
146
+ }
147
+ case AccessLevelReadWrite :
148
+ if ! v .isOperationInList (operation , readOperations ) && ! v .isOperationInList (operation , readWriteOperations ) {
149
+ // Check if it's an admin operation to provide better error message
150
+ if v .isOperationInList (operation , adminOperations ) {
151
+ return & ValidationError {Message : "Error: Cannot execute admin operations in read-write mode" }
152
+ }
153
+ return & ValidationError {Message : "Error: Operation not allowed in read-write mode" }
154
+ }
155
+ case AccessLevelAdmin :
156
+ // Admin level allows all operations (read, write, and admin)
157
+ if ! v .isOperationInList (operation , readOperations ) &&
158
+ ! v .isOperationInList (operation , readWriteOperations ) &&
159
+ ! v .isOperationInList (operation , adminOperations ) {
160
+ return & ValidationError {Message : "Error: Unknown operation" }
161
+ }
162
+ default :
163
+ return & ValidationError {Message : "Error: Invalid access level configuration" }
94
164
}
95
165
96
166
return nil
@@ -118,28 +188,32 @@ func (v *Validator) validateNamespaceScope(command string) error {
118
188
return nil
119
189
}
120
190
121
- // isReadOperation checks if a command is a read operation
122
- func (v * Validator ) isReadOperation (command string , allowedOperations []string ) bool {
191
+ // isOperationInList checks if an operation is in the given list
192
+ func (v * Validator ) isOperationInList (operation string , allowedOperations []string ) bool {
193
+ for _ , allowed := range allowedOperations {
194
+ if operation == allowed {
195
+ return true
196
+ }
197
+ }
198
+ return false
199
+ }
200
+
201
+ // extractOperationFromCommand extracts the operation from a command
202
+ func (v * Validator ) extractOperationFromCommand (command , commandType string ) string {
123
203
cmdParts := strings .Fields (command )
124
204
var operation string
125
205
126
206
for _ , part := range cmdParts {
127
207
if ! strings .HasPrefix (part , "-" ) {
128
208
// Skip the initial command name (kubectl, helm, cilium)
129
- if part != CommandTypeKubectl && part != CommandTypeHelm && part != CommandTypeCilium {
209
+ if part != commandType {
130
210
operation = part
131
211
break
132
212
}
133
213
}
134
214
}
135
215
136
- for _ , allowed := range allowedOperations {
137
- if operation == allowed {
138
- return true
139
- }
140
- }
141
-
142
- return false
216
+ return operation
143
217
}
144
218
145
219
// extractNamespaceFromCommand extracts the namespace from a command
0 commit comments