Skip to content

Commit 296b938

Browse files
committed
Add AppArmor GA KEP
Signed-off-by: Sascha Grunert <[email protected]>
1 parent a8262db commit 296b938

File tree

1 file changed

+387
-0
lines changed

1 file changed

+387
-0
lines changed
Lines changed: 387 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,387 @@
1+
---
2+
title: AppArmor to GA
3+
authors:
4+
- "@saschagrunert"
5+
- "@tallclair"
6+
owning-sig: sig-node
7+
participating-sigs:
8+
- sig-api-machinery
9+
- sig-auth
10+
reviewers:
11+
- TBD
12+
approvers:
13+
- TBD
14+
editor: TBD
15+
creation-date: 2020-01-10
16+
status: provisional
17+
---
18+
19+
# AppArmor to GA
20+
21+
## Table of Contents
22+
23+
<!-- toc -->
24+
25+
- [Release Signoff Checklist](#release-signoff-checklist)
26+
- [Summary](#summary)
27+
- [Motivation](#motivation)
28+
- [Goals](#goals)
29+
- [Non-Goals](#non-goals)
30+
- [Proposal](#proposal)
31+
- [API](#api)
32+
- [Pod API](#pod-api)
33+
- [PodSecurityPolicy API](#podsecuritypolicy-api)
34+
- [Design Details](#design-details)
35+
- [Version Skew Strategy](#version-skew-strategy)
36+
- [Pod Creation](#pod-creation)
37+
- [Pod Update](#pod-update)
38+
- [PodSecurityPolicy Creation](#podsecuritypolicy-creation)
39+
- [PodSecurityPolicy Update](#podsecuritypolicy-update)
40+
- [PodSecurityPolicy Enforcement](#podsecuritypolicy-enforcement)
41+
- [PodTemplates](#podtemplates)
42+
- [Upgrade / Downgrade](#upgrade--downgrade)
43+
- [Test Plan](#test-plan)
44+
- [Graduation Criteria](#graduation-criteria)
45+
- [Upgrade / Downgrade Strategy](#upgrade--downgrade-strategy)
46+
- [Implementation History](#implementation-history)
47+
- [Drawbacks](#drawbacks)
48+
<!-- /toc -->
49+
50+
## Release Signoff Checklist
51+
52+
**ACTION REQUIRED:** In order to merge code into a release, there must be an
53+
issue in [kubernetes/enhancements] referencing this KEP and targeting a release
54+
milestone **before [Enhancement
55+
Freeze](https://github.com/kubernetes/sig-release/tree/master/releases) of the
56+
targeted release**.
57+
58+
For enhancements that make changes to code or processes/procedures in core
59+
Kubernetes i.e., [kubernetes/kubernetes], we require the following Release
60+
Signoff checklist to be completed.
61+
62+
Check these off as they are completed for the Release Team to track. These
63+
checklist items _must_ be updated for the enhancement to be released.
64+
65+
- [ ] kubernetes/enhancements issue in release milestone, which links to KEP
66+
(this should be a link to the KEP location in kubernetes/enhancements, not the
67+
initial KEP PR)
68+
- [ ] KEP approvers have set the KEP status to `implementable`
69+
- [ ] Design details are appropriately documented
70+
- [ ] Test plan is in place, giving consideration to SIG Architecture and SIG
71+
Testing input
72+
- [ ] Graduation criteria is in place
73+
- [ ] "Implementation History" section is up-to-date for milestone
74+
- [ ] User-facing documentation has been created in [kubernetes/website], for
75+
publication to [kubernetes.io]
76+
- [ ] Supporting documentation e.g., additional design documents, links to
77+
mailing list discussions/SIG meetings, relevant PRs/issues, release notes
78+
79+
**Note:** Any PRs to move a KEP to `implementable` or significant changes once
80+
it is marked `implementable` should be approved by each of the KEP approvers. If
81+
any of those approvers is no longer appropriate than changes to that list should
82+
be approved by the remaining approvers and/or the owning SIG (or SIG-arch for
83+
cross cutting KEPs).
84+
85+
**Note:** This checklist is iterative and should be reviewed and updated every
86+
time this enhancement is being considered for a milestone.
87+
88+
[kubernetes.io]: https://kubernetes.io/
89+
[kubernetes/enhancements]: https://github.com/kubernetes/enhancements/issues
90+
[kubernetes/kubernetes]: https://github.com/kubernetes/kubernetes
91+
[kubernetes/website]: https://github.com/kubernetes/website
92+
93+
## Summary
94+
95+
This is a proposal to upgrade the AppArmor annotation on pods & pod security
96+
policies (PSP) to a dedicated field, and mark the feature as GA. This proposal
97+
aims to do the _bare minimum_ to clean up the feature, without blocking future
98+
enhancements.
99+
100+
## Motivation
101+
102+
AppArmor support has been added with Kubernetes v1.14 and is already in beta.
103+
Profiles have to be available on each node whereas the container runtime ensures
104+
that the profile is loaded when specified at pod or PSP level. Profiles
105+
can be specified per-container via the pod’s metadata annotation:
106+
107+
```
108+
container.apparmor.security.beta.kubernetes.io/<container_name>: {unconfined,runtime/default,localhost/<profile>}
109+
```
110+
111+
The feature has been more or less unchanged ever since. Also note that the
112+
addition predates feature gates or our modern concept of feature lifecycle. So,
113+
even though the annotations include `beta` in the key, this is entirely useable
114+
on any production GA cluster.
115+
116+
The main motivation behind this KEP is to promote the AppArmor feature to GA.
117+
118+
_NOTE: Seccomp is in a very similar state, but with some subtle differences.
119+
Promoting Seccomp to GA will be covered by a [separate
120+
KEP][https://github.com/kubernetes/enhancements/pull/1148]._
121+
122+
### Goals
123+
124+
- Declare AppArmor as GA
125+
- Fully document and formally spec the feature support
126+
- Add equivalent API fields to replace AppArmor annotations
127+
- Deprecate the AppArmor annotations
128+
129+
### Non-Goals
130+
131+
This KEP proposes the absolute minimum to get AppArmor to GA, therefore all
132+
functional enhancements are out of scope, including:
133+
134+
- Defining any standard "Kubernetes branded" AppArmor profiles
135+
- Formally specifying the AppArmor profile format in Kubernetes
136+
- Providing mechanisms for loading profiles from outside the of the node
137+
- Changing the semantics around AppArmor support
138+
- Windows support
139+
140+
## Proposal
141+
142+
AppArmor is not available on every Linux distribution. Beside this, container
143+
runtimes have AppArmor as compile-time feature which may be disabled as well.
144+
With the GA API we do not change the error handling and behave exactly the same
145+
as the current error propagation paths.
146+
147+
### API
148+
149+
The AppArmor API will be functionally equivalent to the current beta API. This
150+
includes the Pod API, which specifies what profile the containers run with, and
151+
the `PodSecurityPolicy` API which specifies allowed profiles & a default
152+
profile.
153+
154+
#### Pod API
155+
156+
The Pod AppArmor API is generally immutable, except in `PodTemplates`.
157+
158+
```go
159+
type PodSecurityContext struct {
160+
...
161+
// The AppArmor options to use by the containers in this pod.
162+
// +optional
163+
AppArmor *AppArmorProfile
164+
...
165+
}
166+
167+
type SecurityContext struct {
168+
...
169+
// The AppArmor options to use by this container. If AppArmor options are
170+
// provided at both the pod & container level, the container options
171+
// override the pod options.
172+
// +optional
173+
AppArmor *AppArmorProfile
174+
...
175+
}
176+
177+
type AppArmorProfileType string
178+
179+
const (
180+
AppArmorProfileUnconfined AppArmorProfileType = "Unconfined"
181+
AppArmorProfileDefault AppArmorProfileType = "Default"
182+
AppArmorProfileLocalhost AppArmorProfileType = "Localhost"
183+
)
184+
185+
// Only one profile source may be set.
186+
// +union
187+
type AppArmorProfile struct {
188+
// +unionDescriminator
189+
Type AppArmorProfileType
190+
191+
// Load a profile defined on the node.
192+
// The profile must be available on the node to work.
193+
// The length of the profile is limited to 253 characters.
194+
// The `Type` in this struct has to be set to `AppArmorProfileLocalhost`.
195+
// +optional
196+
LocalhostProfile *string
197+
}
198+
```
199+
200+
This API makes the options more explicit and leaves room for new profile sources
201+
to be added in the future (e.g. Kubernetes predefined profiles or ConfigMap
202+
profiles). The AppArmor options structure leaves room for future extensions,
203+
such as defining the behavior when a profile cannot be set.
204+
205+
#### PodSecurityPolicy API
206+
207+
```go
208+
type PodSecurityPolicySpec struct {
209+
...
210+
// AppArmor is the strategy that will dictate allowable and default AppArmor
211+
// profiles for the container.
212+
// +optional
213+
AppArmor *ApparmorStrategyOptions
214+
...
215+
}
216+
217+
type AppArmorStrategyOptions struct {
218+
// The default profile to set on the pod, if none is specified.
219+
// The default MUST be allowed by the allowedProfiles.
220+
// +optional
221+
DefaultProfile *v1.AppArmorProfile
222+
223+
// The set of profiles that may be set on the pod or containers.
224+
// If unspecified, AppArmor profiles are unrestricted by this policy.
225+
// +optional
226+
AllowedProfiles *AppArmorProfileSet
227+
}
228+
229+
// A set of AppArmor profiles. This struct should be a plural of
230+
// `v1.AppArmorProfile`.
231+
// All values are optional, and an unspecified field excludes all profiles of
232+
// that type from the set.
233+
type AppArmorProfileSet struct {
234+
// The allowed AppArmor profile types.
235+
// +optional
236+
Types []AppArmorProfileType
237+
238+
// The allowed runtimeProfiles. A value of '*' allows all runtimeProfiles.
239+
// +optional
240+
RuntimeProfiles []string
241+
242+
// The allowed localhostProfiles. Values may end in '*' to include all
243+
// localhostProfiles with a prefix.
244+
// +optional
245+
LocalhostProfiles []string
246+
}
247+
```
248+
249+
## Design Details
250+
251+
### Version Skew Strategy
252+
253+
All API skew is resolved in the API server. New Kubelets will only use the
254+
AppArmor values specified in the fields and ignore the annotations therefore.
255+
256+
#### Pod Creation
257+
258+
If no AppArmor annotations or fields are specified, no action is necessary.
259+
260+
If _only_ AppArmor fields are specified, add the corresponding annotations. This
261+
ensures that the fields are enforced even if the node version trails the API
262+
version. Since [we
263+
support](https://kubernetes.io/docs/setup/release/version-skew-policy) up to 2
264+
minor releases of version skew between the master and node, this behavior will
265+
be removed in version N+4 (where N is the release with the upgraded AppArmor
266+
support).
267+
268+
If _only_ AppArmor annotations are specified, copy the values into the
269+
corresponding fields. This ensures that existing applications continue to
270+
enforce AppArmor, and prevents the kubelet from needing to resolve annotations &
271+
fields.
272+
273+
If both AppArmor annotations _and_ fields are specified, the values MUST match.
274+
This will be enforced in API validation.
275+
276+
To raise awareness of annotation usage (in case of old automation), an
277+
additional warning annotation will be added when a pod is created with an
278+
AppArmor annotation:
279+
280+
```
281+
warning.kubernetes.io/apparmor: "AppArmor set through annotations. Support will be dropped in v1.22"
282+
```
283+
284+
#### Pod Update
285+
286+
The AppArmor fields on a pod are immutable.
287+
288+
The behavior on annotation update is currently ill-defined: the annotation
289+
update is allowed, but the new value will not be used until the container is
290+
restarted. There is no way to tell (from the API) what value a container is
291+
using.
292+
293+
Therefore, AppArmor annotation updates will be ignored. This maintains backwards
294+
API compatibility (no tightening validation), and makes a small stabilizing
295+
change to behavior (new Kubelets will ignore the update).
296+
297+
#### PodSecurityPolicy Creation
298+
299+
Unlike with pods, PodSecurityPolicy AppArmor annotations and fields are _not_
300+
synced.
301+
302+
If only AppArmor annotations or fields are specified, no action is necessary.
303+
The set value is used when applying the PodSecurityPolicy.
304+
305+
If both AppArmor annotations _and_ fields are specified, the values MUST match.
306+
This will be enforced in API validation.
307+
308+
#### PodSecurityPolicy Update
309+
310+
PodSecurityPolicy AppArmor fields are mutable. On an update, the same rules are
311+
applied as for creation, ignoring the old values.
312+
313+
If only AppArmor annotations or fields are specified in the updated PSP, no
314+
action is necessary, and the specified values are used.
315+
316+
If both AppArmor annotations _and_ fields are specified in the updated PSP, the
317+
values MUST match.
318+
319+
#### PodSecurityPolicy Enforcement
320+
321+
The PodSecurityPolicy admission controller must continue to check the PSP object
322+
for annotations, as well as for fields.
323+
324+
When setting default profiles, PSP only needs to set the field. The API
325+
machinery will handle setting the annotation as necessary.
326+
327+
When enforcing allowed profiles, the PSP should check BOTH the annotations &
328+
fields. In most cases, they should be consistent. On pod update, the AppArmor
329+
annotations may differ from the fields. In that case, the PSP enforcement should
330+
check both values as the effective value depends on the node version running the
331+
pod.
332+
333+
#### PodTemplates
334+
335+
PodTemplates (e.g. ReplaceSets, Deployments, StatefulSets, etc.) will be
336+
ignored. The field/annotation resolution will happen on template instantiation.
337+
338+
However, to raise awareness of existing controllers using the AppArmor
339+
annotations that need to be migrated, the same warning annotation will be added
340+
to the controller as for pods:
341+
342+
```
343+
warning.kubernetes.io/apparmor: "AppArmor set through annotations. Support will be dropped in v1.22"
344+
```
345+
346+
#### Upgrade / Downgrade
347+
348+
Nodes do not currently support in-place upgrades, so pods will be recreated on
349+
node upgrade and downgrade. No special handling or consideration is needed to
350+
support this.
351+
352+
On the API server side, we've already taken version skew in HA clusters into
353+
account. The same precautions make upgrade & downgrade handling a non-issue.
354+
355+
### Test Plan
356+
357+
AppArmor already has [e2e tests][https://github.com/kubernetes/kubernetes/blob/6596a14/test/e2e_node/apparmor_test.go],
358+
but the tests are guarded by the `[Feature:AppArmor]` tag and not run in the
359+
standard test suites.
360+
361+
Prior to being marked GA, the feature tag will be removed from the AppArmor
362+
tests, and the tests will be migrated to the new fields API. Tests will be
363+
tagged as `[LinuxOnly]`.
364+
365+
New tests will be added covering the annotation/field conflict cases described
366+
under [Version Skew Strategy](#version-skew-strategy).
367+
368+
Test coverage for localhost profiles will be added as well.
369+
370+
### Graduation Criteria
371+
372+
_This section is excluded, as it is the subject of the entire proposal._
373+
374+
### Upgrade / Downgrade Strategy
375+
376+
See [Version Skew Strategy](#version-skew-strategy).
377+
378+
## Implementation History
379+
380+
- 2020-01-10: Initial KEP
381+
382+
## Drawbacks
383+
384+
Promoting AppArmor as-is to GA may be seen as "blessing" the current
385+
functionality, and make it harder to make some of the enhancements listed under
386+
[Non-Goals](#non-goals). Since the current behavior is unguarded, I think we
387+
already need to treat the behavior as GA.

0 commit comments

Comments
 (0)