Skip to content

Commit 048e4c5

Browse files
committed
Add AppArmor GA KEP
Signed-off-by: Sascha Grunert <[email protected]>
1 parent 71a14d8 commit 048e4c5

File tree

1 file changed

+389
-0
lines changed

1 file changed

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

0 commit comments

Comments
 (0)