k8s: Validate API server not excluded admission plugins
[integration.git] / test / security / k8s / src / check / validators / master / api.go
1 package master
2
3 import (
4         "strconv"
5         "strings"
6 )
7
8 const (
9         portDisabled = 0
10         portLowest   = 1
11         portHighest  = 65536
12 )
13
14 // IsBasicAuthFileAbsent validates there is no basic authentication file specified.
15 func IsBasicAuthFileAbsent(params []string) bool {
16         return isFlagAbsent("--basic-auth-file=", params)
17 }
18
19 // IsTokenAuthFileAbsent validates there is no token based authentication file specified.
20 func IsTokenAuthFileAbsent(params []string) bool {
21         return isFlagAbsent("--token-auth-file=", params)
22 }
23
24 // IsInsecureAllowAnyTokenAbsent validates insecure tokens are not accepted.
25 func IsInsecureAllowAnyTokenAbsent(params []string) bool {
26         return isFlagAbsent("--insecure-allow-any-token", params)
27 }
28
29 // isFlagAbsent checks absence of selected flag in parameters.
30 func isFlagAbsent(flag string, params []string) bool {
31         found := filterFlags(params, flag)
32         if len(found) != 0 {
33                 return false
34         }
35         return true
36 }
37
38 // IsAnonymousAuthDisabled validates there is single "--anonymous-auth" flag and it is set to "false".
39 func IsAnonymousAuthDisabled(params []string) bool {
40         return hasSingleFlagArgument("--anonymous-auth=", "false", params)
41 }
42
43 // IsInsecurePortUnbound validates there is single "--insecure-port" flag and it is set to "0" (disabled).
44 func IsInsecurePortUnbound(params []string) bool {
45         return hasSingleFlagArgument("--insecure-port=", strconv.Itoa(portDisabled), params)
46 }
47
48 // IsProfilingDisabled validates there is single "--profiling" flag and it is set to "false".
49 func IsProfilingDisabled(params []string) bool {
50         return hasSingleFlagArgument("--profiling=", "false", params)
51 }
52
53 // IsRepairMalformedUpdatesDisabled validates there is single "--repair-malformed-updates" flag and it is set to "false".
54 func IsRepairMalformedUpdatesDisabled(params []string) bool {
55         return hasSingleFlagArgument("--repair-malformed-updates=", "false", params)
56 }
57
58 // IsServiceAccountLookupEnabled validates there is single "--service-account-lookup" flag and it is set to "true".
59 func IsServiceAccountLookupEnabled(params []string) bool {
60         return hasSingleFlagArgument("--service-account-lookup=", "true", params)
61 }
62
63 // hasSingleFlagArgument checks whether selected flag was used once and has requested argument.
64 func hasSingleFlagArgument(flag string, argument string, params []string) bool {
65         found := filterFlags(params, flag)
66         if len(found) != 1 {
67                 return false
68         }
69
70         _, value := splitKV(found[0], "=")
71         if value != argument {
72                 return false
73         }
74         return true
75 }
76
77 // filterFlags returns all occurrences of selected flag.
78 func filterFlags(strs []string, flag string) []string {
79         var filtered []string
80         for _, str := range strs {
81                 if strings.HasPrefix(str, flag) {
82                         filtered = append(filtered, str)
83                 }
84         }
85         return filtered
86 }
87
88 // splitKV splits key and value (after first occurrence of separator).
89 func splitKV(s, sep string) (string, string) {
90         ret := strings.SplitN(s, sep, 2)
91         return ret[0], ret[1]
92 }
93
94 // IsKubeletHTTPSAbsentOrEnabled validates there is single "--kubelet-https" flag and it is set to "true".
95 func IsKubeletHTTPSAbsentOrEnabled(params []string) bool {
96         return isFlagAbsent("--kubelet-https=", params) ||
97                 hasSingleFlagArgument("--kubelet-https=", "true", params)
98 }
99
100 // IsInsecureBindAddressAbsentOrLoopback validates there is no insecure bind address or it is loopback address.
101 func IsInsecureBindAddressAbsentOrLoopback(params []string) bool {
102         return isFlagAbsent("--insecure-bind-address=", params) ||
103                 hasSingleFlagArgument("--insecure-bind-address=", "127.0.0.1", params)
104 }
105
106 // IsSecurePortAbsentOrValid validates there is no secure port set explicitly or it has legal value.
107 func IsSecurePortAbsentOrValid(params []string) bool {
108         return isFlagAbsent("--secure-port=", params) ||
109                 hasFlagValidPort("--secure-port=", params)
110 }
111
112 // hasFlagValidPort checks whether selected flag has valid port as an argument in given command.
113 func hasFlagValidPort(flag string, params []string) bool {
114         found := filterFlags(params, flag)
115         if len(found) != 1 {
116                 return false
117         }
118
119         _, value := splitKV(found[0], "=")
120         port, err := strconv.Atoi(value) // what about empty parameter?
121         if err != nil {
122                 return false
123         }
124         if port < portLowest || port > portHighest {
125                 return false
126         }
127         return true
128 }
129
130 // IsAlwaysAdmitAdmissionControlPluginExcluded validates AlwaysAdmit is excluded from admission control plugins.
131 func IsAlwaysAdmitAdmissionControlPluginExcluded(params []string) bool {
132         if isSingleFlagPresent("--enable-admission-plugins=", params) {
133                 return !hasFlagArgumentIncluded("--enable-admission-plugins=", "AlwaysAdmit", params)
134         }
135         if isSingleFlagPresent("--admission-control=", params) {
136                 return !hasFlagArgumentIncluded("--admission-control=", "AlwaysAdmit", params)
137         }
138         return false
139 }
140
141 // IsAlwaysPullImagesAdmissionControlPluginIncluded validates AlwaysPullImages is included in admission control plugins.
142 func IsAlwaysPullImagesAdmissionControlPluginIncluded(params []string) bool {
143         if isSingleFlagPresent("--enable-admission-plugins=", params) {
144                 return hasFlagArgumentIncluded("--enable-admission-plugins=", "AlwaysPullImages", params)
145         }
146         if isSingleFlagPresent("--admission-control=", params) {
147                 return hasFlagArgumentIncluded("--admission-control=", "AlwaysPullImages", params)
148         }
149         return false
150 }
151
152 // IsDenyEscalatingExecAdmissionControlPluginIncluded validates DenyEscalatingExec is included in admission control plugins.
153 func IsDenyEscalatingExecAdmissionControlPluginIncluded(params []string) bool {
154         if isSingleFlagPresent("--enable-admission-plugins=", params) {
155                 return hasFlagArgumentIncluded("--enable-admission-plugins=", "DenyEscalatingExec", params)
156         }
157         if isSingleFlagPresent("--admission-control=", params) {
158                 return hasFlagArgumentIncluded("--admission-control=", "DenyEscalatingExec", params)
159         }
160         return false
161 }
162
163 // IsSecurityContextDenyAdmissionControlPluginIncluded validates SecurityContextDeny is included in admission control plugins.
164 func IsSecurityContextDenyAdmissionControlPluginIncluded(params []string) bool {
165         if isSingleFlagPresent("--enable-admission-plugins=", params) {
166                 return hasFlagArgumentIncluded("--enable-admission-plugins=", "SecurityContextDeny", params)
167         }
168         if isSingleFlagPresent("--admission-control=", params) {
169                 return hasFlagArgumentIncluded("--admission-control=", "SecurityContextDeny", params)
170         }
171         return false
172 }
173
174 // IsPodSecurityPolicyAdmissionControlPluginIncluded validates PodSecurityPolicy is included in admission control plugins.
175 func IsPodSecurityPolicyAdmissionControlPluginIncluded(params []string) bool {
176         if isSingleFlagPresent("--enable-admission-plugins=", params) {
177                 return hasFlagArgumentIncluded("--enable-admission-plugins=", "PodSecurityPolicy", params)
178         }
179         if isSingleFlagPresent("--admission-control=", params) {
180                 return hasFlagArgumentIncluded("--admission-control=", "PodSecurityPolicy", params)
181         }
182         return false
183 }
184
185 // IsServiceAccountAdmissionControlPluginIncluded validates ServiceAccount is included in admission control plugins.
186 func IsServiceAccountAdmissionControlPluginIncluded(params []string) bool {
187         if isSingleFlagPresent("--enable-admission-plugins=", params) {
188                 return hasFlagArgumentIncluded("--enable-admission-plugins=", "ServiceAccount", params)
189         }
190         if isSingleFlagPresent("--admission-control=", params) {
191                 return hasFlagArgumentIncluded("--admission-control=", "ServiceAccount", params)
192         }
193         return false
194 }
195
196 // IsNodeRestrictionAdmissionControlPluginIncluded validates NodeRestriction is included in admission control plugins.
197 func IsNodeRestrictionAdmissionControlPluginIncluded(params []string) bool {
198         if isSingleFlagPresent("--enable-admission-plugins=", params) {
199                 return hasFlagArgumentIncluded("--enable-admission-plugins=", "NodeRestriction", params)
200         }
201         if isSingleFlagPresent("--admission-control=", params) {
202                 return hasFlagArgumentIncluded("--admission-control=", "NodeRestriction", params)
203         }
204         return false
205 }
206
207 // IsEventRateLimitAdmissionControlPluginIncluded validates EventRateLimit is included in admission control plugins.
208 func IsEventRateLimitAdmissionControlPluginIncluded(params []string) bool {
209         if isSingleFlagPresent("--enable-admission-plugins=", params) {
210                 return hasFlagArgumentIncluded("--enable-admission-plugins=", "EventRateLimit", params)
211         }
212         if isSingleFlagPresent("--admission-control=", params) {
213                 return hasFlagArgumentIncluded("--admission-control=", "EventRateLimit", params)
214         }
215         return false
216 }
217
218 // IsNamespaceLifecycleAdmissionControlPluginNotExcluded validates NamespaceLifecycle is excluded from admission control plugins.
219 func IsNamespaceLifecycleAdmissionControlPluginNotExcluded(params []string) bool {
220         if isSingleFlagPresent("--disable-admission-plugins=", params) {
221                 return !hasFlagArgumentIncluded("--disable-admission-plugins=", "NamespaceLifecycle", params)
222         }
223         return true
224 }
225
226 // isSingleFlagPresent checks presence of selected flag and whether it was used once.
227 func isSingleFlagPresent(flag string, params []string) bool {
228         found := filterFlags(params, flag)
229         if len(found) != 1 {
230                 return false
231         }
232         return true
233 }
234
235 // hasFlagArgumentIncluded checks whether selected flag includes requested argument.
236 func hasFlagArgumentIncluded(flag string, argument string, params []string) bool {
237         found := filterFlags(params, flag)
238         if len(found) != 1 {
239                 return false
240         }
241
242         _, values := splitKV(found[0], "=")
243         for _, v := range strings.Split(values, ",") {
244                 if v == argument {
245                         return true
246                 }
247         }
248         return false
249 }