1 package securitypolicy
2
3 import (
4 "fmt"
5 "strconv"
6 "syscall"
7 )
8
9
10 type securityPolicyInternal struct {
11 Containers []*securityPolicyContainer
12 ExternalProcesses []*externalProcess
13 Fragments []*fragment
14 AllowPropertiesAccess bool
15 AllowDumpStacks bool
16 AllowRuntimeLogging bool
17 AllowEnvironmentVariableDropping bool
18 AllowUnencryptedScratch bool
19 AllowCapabilityDropping bool
20 }
21
22 type securityPolicyFragment struct {
23 Namespace string
24 SVN string
25 Containers []*securityPolicyContainer
26 ExternalProcesses []*externalProcess
27 Fragments []*fragment
28 }
29
30 func containersToInternal(containers []*Container) ([]*securityPolicyContainer, error) {
31 result := make([]*securityPolicyContainer, len(containers))
32 for i, cConf := range containers {
33 cInternal, err := cConf.toInternal()
34 if err != nil {
35 return nil, err
36 }
37 result[i] = cInternal
38 }
39
40 return result, nil
41 }
42
43 func externalProcessToInternal(externalProcesses []ExternalProcessConfig) []*externalProcess {
44 result := make([]*externalProcess, len(externalProcesses))
45 for i, pConf := range externalProcesses {
46 pInternal := pConf.toInternal()
47 result[i] = &pInternal
48 }
49
50 return result
51 }
52
53 func fragmentsToInternal(fragments []FragmentConfig) []*fragment {
54 result := make([]*fragment, len(fragments))
55 for i, fConf := range fragments {
56 fInternal := fConf.toInternal()
57 result[i] = &fInternal
58 }
59
60 return result
61 }
62
63 func newSecurityPolicyInternal(
64 containers []*Container,
65 externalProcesses []ExternalProcessConfig,
66 fragments []FragmentConfig,
67 allowPropertiesAccess bool,
68 allowDumpStacks bool,
69 allowRuntimeLogging bool,
70 allowDropEnvironmentVariables bool,
71 allowUnencryptedScratch bool,
72 allowDropCapabilities bool,
73 ) (*securityPolicyInternal, error) {
74 containersInternal, err := containersToInternal(containers)
75 if err != nil {
76 return nil, err
77 }
78
79 return &securityPolicyInternal{
80 Containers: containersInternal,
81 ExternalProcesses: externalProcessToInternal(externalProcesses),
82 Fragments: fragmentsToInternal(fragments),
83 AllowPropertiesAccess: allowPropertiesAccess,
84 AllowDumpStacks: allowDumpStacks,
85 AllowRuntimeLogging: allowRuntimeLogging,
86 AllowEnvironmentVariableDropping: allowDropEnvironmentVariables,
87 AllowUnencryptedScratch: allowUnencryptedScratch,
88 AllowCapabilityDropping: allowDropCapabilities,
89 }, nil
90 }
91
92 func newSecurityPolicyFragment(
93 namespace string,
94 svn string,
95 containers []*Container,
96 externalProcesses []ExternalProcessConfig,
97 fragments []FragmentConfig) (*securityPolicyFragment, error) {
98 containersInternal, err := containersToInternal(containers)
99 if err != nil {
100 return nil, err
101 }
102
103 return &securityPolicyFragment{
104 Namespace: namespace,
105 SVN: svn,
106 Containers: containersInternal,
107 ExternalProcesses: externalProcessToInternal(externalProcesses),
108 Fragments: fragmentsToInternal(fragments),
109 }, nil
110 }
111
112
113 type securityPolicyContainer struct {
114
115 Command []string `json:"command"`
116
117 EnvRules []EnvRuleConfig `json:"env_rules"`
118
119
120
121
122 Layers []string `json:"layers"`
123
124
125 WorkingDir string `json:"working_dir"`
126
127 Mounts []mountInternal `json:"mounts"`
128 AllowElevated bool `json:"allow_elevated"`
129
130
131 ExecProcesses []containerExecProcess `json:"exec_processes"`
132
133
134 Signals []syscall.Signal `json:"signals"`
135
136 AllowStdioAccess bool `json:"allow_stdio_access"`
137
138 NoNewPrivileges bool `json:"no_new_privileges"`
139
140 User UserConfig `json:"user"`
141
142 Capabilities *capabilitiesInternal `json:"capabilities"`
143
144 SeccompProfileSHA256 string `json:"seccomp_profile_sha256"`
145 }
146
147 type containerExecProcess struct {
148 Command []string `json:"command"`
149
150 Signals []syscall.Signal `json:"signals"`
151 }
152
153 type externalProcess struct {
154 command []string
155 envRules []EnvRuleConfig
156 workingDir string
157 allowStdioAccess bool
158 }
159
160
161 type mountInternal struct {
162 Source string `json:"source"`
163 Destination string `json:"destination"`
164 Type string `json:"type"`
165 Options []string `json:"options"`
166 }
167
168
169 type capabilitiesInternal struct {
170 Bounding []string
171 Effective []string
172 Inheritable []string
173 Permitted []string
174 Ambient []string
175 }
176
177 type fragment struct {
178 issuer string
179 feed string
180 minimumSVN string
181 includes []string
182 }
183
184 func (c *Container) toInternal() (*securityPolicyContainer, error) {
185 command, err := c.Command.toInternal()
186 if err != nil {
187 return nil, err
188 }
189
190 envRules, err := c.EnvRules.toInternal()
191 if err != nil {
192 return nil, err
193 }
194
195 layers, err := c.Layers.toInternal()
196 if err != nil {
197 return nil, err
198 }
199
200 mounts, err := c.Mounts.toInternal()
201 if err != nil {
202 return nil, err
203 }
204
205 execProcesses := make([]containerExecProcess, len(c.ExecProcesses))
206 for i, ep := range c.ExecProcesses {
207 execProcesses[i] = containerExecProcess(ep)
208 }
209
210 var capabilities *capabilitiesInternal
211 if c.Capabilities != nil {
212 c := c.Capabilities.toInternal()
213 capabilities = &c
214 }
215
216 return &securityPolicyContainer{
217 Command: command,
218 EnvRules: envRules,
219 Layers: layers,
220
221
222 WorkingDir: c.WorkingDir,
223 Mounts: mounts,
224 AllowElevated: c.AllowElevated,
225 ExecProcesses: execProcesses,
226 Signals: c.Signals,
227 AllowStdioAccess: c.AllowStdioAccess,
228 NoNewPrivileges: c.NoNewPrivileges,
229 User: c.User,
230 Capabilities: capabilities,
231 SeccompProfileSHA256: c.SeccompProfileSHA256,
232 }, nil
233 }
234
235 func (c CommandArgs) toInternal() ([]string, error) {
236 return stringMapToStringArray(c.Elements)
237 }
238
239 func (e EnvRules) toInternal() ([]EnvRuleConfig, error) {
240 envRulesMapLength := len(e.Elements)
241 envRules := make([]EnvRuleConfig, envRulesMapLength)
242 for i := 0; i < envRulesMapLength; i++ {
243 eIndex := strconv.Itoa(i)
244 elem, ok := e.Elements[eIndex]
245 if !ok {
246 return nil, fmt.Errorf("env rule with index %q doesn't exist", eIndex)
247 }
248 envRules[i] = elem
249 }
250
251 return envRules, nil
252 }
253
254 func (l Layers) toInternal() ([]string, error) {
255 return stringMapToStringArray(l.Elements)
256 }
257
258 func (o Options) toInternal() ([]string, error) {
259 return stringMapToStringArray(o.Elements)
260 }
261
262 func (m Mounts) toInternal() ([]mountInternal, error) {
263 mountLength := len(m.Elements)
264 mountConstraints := make([]mountInternal, mountLength)
265 for i := 0; i < mountLength; i++ {
266 mIndex := strconv.Itoa(i)
267 mount, ok := m.Elements[mIndex]
268 if !ok {
269 return nil, fmt.Errorf("mount constraint with index %q not found", mIndex)
270 }
271 opts, err := mount.Options.toInternal()
272 if err != nil {
273 return nil, err
274 }
275 mountConstraints[i] = mountInternal{
276 Source: mount.Source,
277 Destination: mount.Destination,
278 Type: mount.Type,
279 Options: opts,
280 }
281 }
282 return mountConstraints, nil
283 }
284
285 func (p ExternalProcessConfig) toInternal() externalProcess {
286 return externalProcess{
287 command: p.Command,
288 envRules: []EnvRuleConfig{{
289 Strategy: "string",
290 Rule: "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
291 Required: true,
292 }},
293 workingDir: p.WorkingDir,
294 allowStdioAccess: p.AllowStdioAccess,
295 }
296 }
297
298 func (f FragmentConfig) toInternal() fragment {
299 return fragment{
300 issuer: f.Issuer,
301 feed: f.Feed,
302 minimumSVN: f.MinimumSVN,
303 includes: f.Includes,
304 }
305 }
306
307 func (c CapabilitiesConfig) toInternal() capabilitiesInternal {
308 return capabilitiesInternal(c)
309 }
310
311 func stringMapToStringArray(m map[string]string) ([]string, error) {
312 mapSize := len(m)
313 out := make([]string, mapSize)
314
315 for i := 0; i < mapSize; i++ {
316 index := strconv.Itoa(i)
317 value, ok := m[index]
318 if !ok {
319 return nil, fmt.Errorf("element with index %q not found", index)
320 }
321 out[i] = value
322 }
323
324 return out, nil
325 }
326
View as plain text