Skip to content

Commit 04c95de

Browse files
Enable a simple image policy admission controller
Start adding policy and rules
1 parent df90cb2 commit 04c95de

File tree

17 files changed

+2057
-0
lines changed

17 files changed

+2057
-0
lines changed

pkg/cmd/server/api/install/install.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313

1414
_ "github.com/openshift/origin/pkg/build/admission/defaults/api/install"
1515
_ "github.com/openshift/origin/pkg/build/admission/overrides/api/install"
16+
_ "github.com/openshift/origin/pkg/image/admission/imagepolicy/api/install"
1617
_ "github.com/openshift/origin/pkg/project/admission/requestlimit/api/install"
1718
_ "github.com/openshift/origin/pkg/quota/admission/clusterresourceoverride/api/install"
1819
_ "github.com/openshift/origin/pkg/quota/admission/runonceduration/api/install"

pkg/cmd/server/origin/master_config.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,7 @@ var (
324324
overrideapi.PluginName,
325325
serviceadmit.ExternalIPPluginName,
326326
serviceadmit.RestrictedEndpointsPluginName,
327+
imagepolicy.PluginName,
327328
"LimitRanger",
328329
"ServiceAccount",
329330
"SecurityContextConstraint",
@@ -356,6 +357,7 @@ var (
356357
overrideapi.PluginName,
357358
serviceadmit.ExternalIPPluginName,
358359
serviceadmit.RestrictedEndpointsPluginName,
360+
imagepolicy.PluginName,
359361
"LimitRanger",
360362
"ServiceAccount",
361363
"SecurityContextConstraint",

pkg/cmd/server/start/admission.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
_ "github.com/openshift/origin/pkg/build/admission/overrides"
1313
_ "github.com/openshift/origin/pkg/build/admission/strategyrestrictions"
1414
_ "github.com/openshift/origin/pkg/image/admission"
15+
_ "github.com/openshift/origin/pkg/image/admission/imagepolicy"
1516
_ "github.com/openshift/origin/pkg/project/admission/lifecycle"
1617
_ "github.com/openshift/origin/pkg/project/admission/nodeenv"
1718
_ "github.com/openshift/origin/pkg/project/admission/requestlimit"
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package install
2+
3+
import (
4+
"github.com/golang/glog"
5+
6+
"k8s.io/kubernetes/pkg/api/unversioned"
7+
8+
configapi "github.com/openshift/origin/pkg/cmd/server/api"
9+
"github.com/openshift/origin/pkg/image/admission/imagepolicy/api"
10+
"github.com/openshift/origin/pkg/image/admission/imagepolicy/api/v1"
11+
)
12+
13+
// availableVersions lists all known external versions for this group from most preferred to least preferred
14+
var availableVersions = []unversioned.GroupVersion{v1.SchemeGroupVersion}
15+
16+
func init() {
17+
if err := enableVersions(availableVersions); err != nil {
18+
panic(err)
19+
}
20+
}
21+
22+
// TODO: enableVersions should be centralized rather than spread in each API group.
23+
func enableVersions(externalVersions []unversioned.GroupVersion) error {
24+
addVersionsToScheme(externalVersions...)
25+
return nil
26+
}
27+
28+
func addVersionsToScheme(externalVersions ...unversioned.GroupVersion) {
29+
// add the internal version to Scheme
30+
api.AddToScheme(configapi.Scheme)
31+
// add the enabled external versions to Scheme
32+
for _, v := range externalVersions {
33+
switch v {
34+
case v1.SchemeGroupVersion:
35+
v1.AddToScheme(configapi.Scheme)
36+
default:
37+
glog.Errorf("Version %s is not known, so it will not be added to the Scheme.", v)
38+
continue
39+
}
40+
}
41+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package api
2+
3+
const PluginName = "ImagePolicy"
4+
const ConfigKind = "ImagePolicyConfig"
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package api
2+
3+
import (
4+
"k8s.io/kubernetes/pkg/api/unversioned"
5+
"k8s.io/kubernetes/pkg/runtime"
6+
)
7+
8+
var SchemeGroupVersion = unversioned.GroupVersion{Group: "", Version: runtime.APIVersionInternal}
9+
10+
// Adds the list of known types to api.Scheme.
11+
func AddToScheme(scheme *runtime.Scheme) {
12+
scheme.AddKnownTypes(SchemeGroupVersion,
13+
&ImagePolicyConfig{},
14+
)
15+
}
16+
17+
func (obj *ImagePolicyConfig) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
package api
2+
3+
import (
4+
"k8s.io/kubernetes/pkg/api"
5+
"k8s.io/kubernetes/pkg/api/unversioned"
6+
)
7+
8+
// ImagePolicyConfig is the configuration for controlling how images are used in the cluster.
9+
type ImagePolicyConfig struct {
10+
unversioned.TypeMeta
11+
12+
// ExecutionRules determine whether the use of an image is allowed in an object with a pod spec.
13+
// By default, these rules only apply to pods, but may be extended to other resource types.
14+
ExecutionRules []ImageExecutionPolicyRule
15+
// ConsumptionRules are applied when creating resources with pod specs.
16+
ConsumptionRules []ImageConsumptionPolicyRule
17+
// PlacementRules are applied when creating resources with pod specs.
18+
PlacementRules []ImagePlacementPolicyRule
19+
20+
// Everyone except cluster admins or platform infra must use an image from the registry
21+
// Content in this namespace must use an image from the registry
22+
// Images with a certain annotation/label must be run on these nodes
23+
// Using this image consumes a certain amount of resource
24+
// Images cannot be run or imported unless they come from these registries (unless the user is an admin)
25+
// Images with/without these annotations/labels cannot be run (except in certain namespaces)
26+
// Image cannot be tagged with/without these labels
27+
// Images that are not signed by the listed authorities cannot be run (cert not expired)
28+
// Unsigned images may not be run on the following nodes
29+
30+
// Enforce/Relax by namespace, labels, user permission
31+
// Actions: Create pod, Tag image, Import image (ISM), Mutate pod (node selector, resources)
32+
// Add a resource to pod / container (for the image, this is not resource auto-sizing)
33+
// Add a node selector constraint
34+
// Require a permission check on the service account / current user to tag / create an image
35+
36+
// Pods with this annotation / label should consume one resource increment (per container / per pod)
37+
//
38+
}
39+
40+
// ImagePlacementPolicyRule, when matching an image, applies the provided tolerations or taints.
41+
type ImagePlacementPolicyRule struct {
42+
ImageSourceRule
43+
44+
Constrain []ConstrainPodNodeSelectorEffect
45+
Tolerate []TolerateNodeSelectorEffect
46+
}
47+
48+
type ConstrainPodNodeSelectorEffect struct {
49+
Add map[string]string
50+
}
51+
52+
type TolerateNodeSelectorEffect struct {
53+
Add api.Toleration
54+
}
55+
56+
// ImageConsumptionPolicyRule, when matching an image, adds a counted resource to the object.
57+
type ImageConsumptionPolicyRule struct {
58+
ImageSourceRule
59+
60+
Add []ConsumeResourceEffect
61+
}
62+
63+
type ConsumeResourceEffect struct {
64+
// Name is the name of a quantity to set on each matching container.
65+
// May not be specified if NameFromImageAnnotation or NameFromDockerImageLabel is set.
66+
Name string
67+
// NameFromImageAnnotation is the name of an image annotation to use to set the name of the resource
68+
// quantity on each matching container.
69+
// May not be specified if Name or NameFromDockerImageLabel is set.
70+
NameFromImageAnnotation string
71+
// NameFromDockerImageLabel is the name of a docker image label to use to set the name of the resource
72+
// quantity on each matching container.
73+
// May not be specified if Name or NameFromImageAnnotation is set.
74+
NameFromDockerImageLabel string
75+
76+
// Quantity is the amount of quantity to set
77+
Quantity string
78+
// QuantityFromImageAnnotation is the key on an image annotation to use for the value of this resource.
79+
// If this value is specified and no annotation is found, the value of Quantity is used instead.
80+
QuantityFromImageAnnotation string
81+
// QuantityFromDockerImageLabel is the key on a docker image label to use for the value of this resource.
82+
// If this value is specified and no annotation is found, the value of Quantity is used instead.
83+
QuantityFromDockerImageLabel string
84+
}
85+
86+
type ImageExecutionPolicyRule struct {
87+
ImageSourceRule
88+
89+
// Deny indicates this rule is inverted and a match results in a rejection
90+
Deny bool
91+
92+
// Resolve indicates that images referenced by this resource must be resolved
93+
Resolve bool
94+
}
95+
96+
// ImageSourceRule defines the conditions for matching a particular image source. The conditions below
97+
// are all required (logical AND)
98+
type ImageSourceRule struct {
99+
// Name is the name of this policy rule for reference. It must be unique across all rules.
100+
Name string
101+
// OnResources determines which resources this applies to. Defaults to 'pods' for RuntimeSourceRules.
102+
OnResources []string
103+
// IgnoreNamespaceOverride prevents this rule from being overriden when the
104+
// `alpha.image.policy.openshift.io/ignore-rules` is set on a namespace and contains this rule name.
105+
IgnoreNamespaceOverride bool
106+
107+
MatchIntegratedRegistry bool
108+
MatchRegistries []string
109+
110+
// AllowResolutionFailure allows the subsequent rules to be bypassed if the integrated registry does
111+
// not have access to image metadata (no image exists matching the image digest).
112+
AllowResolutionFailure bool
113+
114+
MatchDockerImageLabels []ValueMatch
115+
MatchImageLabels []ValueMatch
116+
MatchImageAnnotations []ValueMatch
117+
MatchSignatures []SignatureMatch
118+
}
119+
120+
type ValueMatch struct {
121+
Key string
122+
123+
// One of the following conditions must apply
124+
Set bool
125+
Value string
126+
}
127+
128+
type SignatureMatch struct {
129+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package v1
2+
3+
import (
4+
"k8s.io/kubernetes/pkg/api/unversioned"
5+
"k8s.io/kubernetes/pkg/runtime"
6+
)
7+
8+
// SchemeGroupVersion is group version used to register these objects
9+
var SchemeGroupVersion = unversioned.GroupVersion{Group: "", Version: "v1"}
10+
11+
// Adds the list of known types to api.Scheme.
12+
func AddToScheme(scheme *runtime.Scheme) {
13+
scheme.AddKnownTypes(SchemeGroupVersion,
14+
&ImagePolicyConfig{},
15+
)
16+
scheme.AddDefaultingFuncs(
17+
func(c *ImagePolicyConfig) {
18+
for i := range c.ExecutionRules {
19+
if len(c.ExecutionRules[i].OnResources) == 0 {
20+
c.ExecutionRules[i].OnResources = []string{"pods"}
21+
}
22+
}
23+
},
24+
)
25+
}
26+
27+
func (obj *ImagePolicyConfig) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
package v1
2+
3+
import (
4+
"k8s.io/kubernetes/pkg/api/unversioned"
5+
"k8s.io/kubernetes/pkg/api/v1"
6+
)
7+
8+
// ImagePolicyConfig is the configuration for control of images running on the platform.
9+
type ImagePolicyConfig struct {
10+
unversioned.TypeMeta `json:",inline"`
11+
12+
// ExecutionRules determine whether the use of an image is allowed in an object with a pod spec.
13+
// By default, these rules only apply to pods, but may be extended to other resource types.
14+
ExecutionRules []ImageExecutionPolicyRule `json:"executionRules"`
15+
// ConsumptionRules are applied when creating resources with pod specs.
16+
ConsumptionRules []ImageConsumptionPolicyRule `json:"consumptionRules"`
17+
// PlacementRules are applied when creating resources with pod specs.
18+
PlacementRules []ImagePlacementPolicyRule `json:"placementRules"`
19+
20+
// Everyone except cluster admins or platform infra must use an image from the registry
21+
// Content in this namespace must use an image from the registry
22+
// Images with a certain annotation/label must be run on these nodes
23+
// Using this image consumes a certain amount of resource
24+
// Images cannot be run or imported unless they come from these registries (unless the user is an admin)
25+
// Images with/without these annotations/labels cannot be run (except in certain namespaces)
26+
// Image cannot be tagged with/without these labels
27+
// Images that are not signed by the listed authorities cannot be run (cert not expired)
28+
// Unsigned images may not be run on the following nodes
29+
30+
// Enforce/Relax by namespace, labels, user permission
31+
// Actions: Create pod, Tag image, Import image (ISM), Mutate pod (node selector, resources)
32+
// Add a resource to pod / container (for the image, this is not resource auto-sizing)
33+
// Add a node selector constraint
34+
// Require a permission check on the service account / current user to tag / create an image
35+
36+
// Pods with this annotation / label should consume one resource increment (per container / per pod)
37+
//
38+
}
39+
40+
// ImagePlacementPolicyRule, when matching an image, applies the provided tolerations or taints.
41+
type ImagePlacementPolicyRule struct {
42+
ImageSourceRule `json:",inline"`
43+
44+
Constrain []ConstrainPodNodeSelectorEffect `json:"constrain"`
45+
Tolerate []TolerateNodeSelectorEffect `json:"tolerate"`
46+
}
47+
48+
type ConstrainPodNodeSelectorEffect struct {
49+
Add map[string]string `json:"add"`
50+
}
51+
52+
type TolerateNodeSelectorEffect struct {
53+
Add v1.Toleration `json:"add"`
54+
}
55+
56+
// ImageConsumptionPolicyRule, when matching an image, adds a counted resource to the object.
57+
type ImageConsumptionPolicyRule struct {
58+
ImageSourceRule `json:",inline"`
59+
60+
Add []ConsumeResourceEffect `json:"add"`
61+
}
62+
63+
type ConsumeResourceEffect struct {
64+
// Name is the name of a quantity to set on each matching container.
65+
// May not be specified if NameFromImageAnnotation or NameFromDockerImageLabel is set.
66+
Name string `json:"name"`
67+
// NameFromImageAnnotation is the name of an image annotation to use to set the name of the resource
68+
// quantity on each matching container.
69+
// May not be specified if Name or NameFromDockerImageLabel is set.
70+
NameFromImageAnnotation string `json:"nameFromImageAnnotation"`
71+
// NameFromDockerImageLabel is the name of a docker image label to use to set the name of the resource
72+
// quantity on each matching container.
73+
// May not be specified if Name or NameFromImageAnnotation is set.
74+
NameFromDockerImageLabel string `json:"nameFromDockerImageLabel"`
75+
76+
// Quantity is the amount of quantity to set
77+
Quantity string `json:"quantity"`
78+
// QuantityFromImageAnnotation is the key on an image annotation to use for the value of this resource.
79+
// If this value is specified and no annotation is found, the value of Quantity is used instead.
80+
QuantityFromImageAnnotation string `json:"quantityFromImageAnnotation"`
81+
// QuantityFromDockerImageLabel is the key on a docker image label to use for the value of this resource.
82+
// If this value is specified and no annotation is found, the value of Quantity is used instead.
83+
QuantityFromDockerImageLabel string `json:"quantityFromDockerImageLabel"`
84+
}
85+
86+
type ImageExecutionPolicyRule struct {
87+
ImageSourceRule `json:",inline"`
88+
89+
// Deny indicates this rule is inverted and a match results in a rejection
90+
Deny bool `json:"deny"`
91+
92+
// Resolve indicates that images referenced by this resource must be resolved
93+
Resolve bool `json:"resolve"`
94+
}
95+
96+
// ImageSourceRule defines the conditions for matching a particular image source. The conditions below
97+
// are all required (logical AND)
98+
type ImageSourceRule struct {
99+
// Name is the name of this policy rule for reference. It must be unique across all rules.
100+
Name string `json:"name"`
101+
// OnResources determines which resources this applies to. Defaults to 'pods' for RuntimeSourceRules.
102+
OnResources []string `json:"onResources"`
103+
// IgnoreNamespaceOverride prevents this rule from being overriden when the
104+
// `alpha.image.policy.openshift.io/ignore-rules` is set on a namespace and contains this rule name.
105+
IgnoreNamespaceOverride bool `json:"ignoreNamespaceOverride"`
106+
107+
MatchIntegratedRegistry bool `json:"matchIntegratedRegistry"`
108+
MatchRegistries []string `json:"matchRegistries"`
109+
110+
// AllowResolutionFailure allows the subsequent rules to be bypassed if the integrated registry does
111+
// not have access to image metadata (no image exists matching the image digest).
112+
AllowResolutionFailure bool `json:"allowResolutionFailure"`
113+
114+
MatchDockerImageLabels []ValueMatch `json:"matchDockerImageLabels"`
115+
MatchImageLabels []ValueMatch `json:"matchImageLabels"`
116+
MatchImageAnnotations []ValueMatch `json:"matchImageAnnotations"`
117+
MatchSignatures []SignatureMatch `json:"matchSignatures"`
118+
}
119+
120+
type ValueMatch struct {
121+
Key string `json:"key"`
122+
123+
// One of the following conditions must apply
124+
Set bool `json:"set"`
125+
Value string `json:"value"`
126+
}
127+
128+
type SignatureMatch struct {
129+
}

0 commit comments

Comments
 (0)