Merge pull request #7893 from pweil-/security-policy

Auto commit by PR queue bot
pull/6/head
k8s-merge-robot 2016-02-05 07:14:37 -08:00
commit 3cfb090939
30 changed files with 11931 additions and 2158 deletions

View File

@ -2479,6 +2479,548 @@
}
]
},
{
"path": "/apis/extensions/v1beta1/podsecuritypolicies",
"description": "API at /apis/extensions/v1beta1",
"operations": [
{
"type": "v1beta1.PodSecurityPolicyList",
"method": "GET",
"summary": "list or watch objects of kind PodSecurityPolicy",
"nickname": "listNamespacedPodSecurityPolicy",
"parameters": [
{
"type": "string",
"paramType": "query",
"name": "pretty",
"description": "If 'true', then the output is pretty printed.",
"required": false,
"allowMultiple": false
},
{
"type": "string",
"paramType": "query",
"name": "labelSelector",
"description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.",
"required": false,
"allowMultiple": false
},
{
"type": "string",
"paramType": "query",
"name": "fieldSelector",
"description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.",
"required": false,
"allowMultiple": false
},
{
"type": "boolean",
"paramType": "query",
"name": "watch",
"description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.",
"required": false,
"allowMultiple": false
},
{
"type": "string",
"paramType": "query",
"name": "resourceVersion",
"description": "When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history.",
"required": false,
"allowMultiple": false
},
{
"type": "integer",
"paramType": "query",
"name": "timeoutSeconds",
"description": "Timeout for the list/watch call.",
"required": false,
"allowMultiple": false
}
],
"responseMessages": [
{
"code": 200,
"message": "OK",
"responseModel": "v1beta1.PodSecurityPolicyList"
}
],
"produces": [
"application/json",
"application/yaml"
],
"consumes": [
"*/*"
]
},
{
"type": "v1beta1.PodSecurityPolicy",
"method": "POST",
"summary": "create a PodSecurityPolicy",
"nickname": "createNamespacedPodSecurityPolicy",
"parameters": [
{
"type": "string",
"paramType": "query",
"name": "pretty",
"description": "If 'true', then the output is pretty printed.",
"required": false,
"allowMultiple": false
},
{
"type": "v1beta1.PodSecurityPolicy",
"paramType": "body",
"name": "body",
"description": "",
"required": true,
"allowMultiple": false
}
],
"responseMessages": [
{
"code": 200,
"message": "OK",
"responseModel": "v1beta1.PodSecurityPolicy"
}
],
"produces": [
"application/json",
"application/yaml"
],
"consumes": [
"*/*"
]
},
{
"type": "unversioned.Status",
"method": "DELETE",
"summary": "delete collection of PodSecurityPolicy",
"nickname": "deletecollectionNamespacedPodSecurityPolicy",
"parameters": [
{
"type": "string",
"paramType": "query",
"name": "pretty",
"description": "If 'true', then the output is pretty printed.",
"required": false,
"allowMultiple": false
},
{
"type": "string",
"paramType": "query",
"name": "labelSelector",
"description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.",
"required": false,
"allowMultiple": false
},
{
"type": "string",
"paramType": "query",
"name": "fieldSelector",
"description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.",
"required": false,
"allowMultiple": false
},
{
"type": "boolean",
"paramType": "query",
"name": "watch",
"description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.",
"required": false,
"allowMultiple": false
},
{
"type": "string",
"paramType": "query",
"name": "resourceVersion",
"description": "When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history.",
"required": false,
"allowMultiple": false
},
{
"type": "integer",
"paramType": "query",
"name": "timeoutSeconds",
"description": "Timeout for the list/watch call.",
"required": false,
"allowMultiple": false
}
],
"responseMessages": [
{
"code": 200,
"message": "OK",
"responseModel": "unversioned.Status"
}
],
"produces": [
"application/json",
"application/yaml"
],
"consumes": [
"*/*"
]
}
]
},
{
"path": "/apis/extensions/v1beta1/watch/podsecuritypolicies",
"description": "API at /apis/extensions/v1beta1",
"operations": [
{
"type": "json.WatchEvent",
"method": "GET",
"summary": "watch individual changes to a list of PodSecurityPolicy",
"nickname": "watchNamespacedPodSecurityPolicyList",
"parameters": [
{
"type": "string",
"paramType": "query",
"name": "pretty",
"description": "If 'true', then the output is pretty printed.",
"required": false,
"allowMultiple": false
},
{
"type": "string",
"paramType": "query",
"name": "labelSelector",
"description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.",
"required": false,
"allowMultiple": false
},
{
"type": "string",
"paramType": "query",
"name": "fieldSelector",
"description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.",
"required": false,
"allowMultiple": false
},
{
"type": "boolean",
"paramType": "query",
"name": "watch",
"description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.",
"required": false,
"allowMultiple": false
},
{
"type": "string",
"paramType": "query",
"name": "resourceVersion",
"description": "When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history.",
"required": false,
"allowMultiple": false
},
{
"type": "integer",
"paramType": "query",
"name": "timeoutSeconds",
"description": "Timeout for the list/watch call.",
"required": false,
"allowMultiple": false
}
],
"responseMessages": [
{
"code": 200,
"message": "OK",
"responseModel": "json.WatchEvent"
}
],
"produces": [
"application/json"
],
"consumes": [
"*/*"
]
}
]
},
{
"path": "/apis/extensions/v1beta1/podsecuritypolicies/{name}",
"description": "API at /apis/extensions/v1beta1",
"operations": [
{
"type": "v1beta1.PodSecurityPolicy",
"method": "GET",
"summary": "read the specified PodSecurityPolicy",
"nickname": "readNamespacedPodSecurityPolicy",
"parameters": [
{
"type": "string",
"paramType": "query",
"name": "pretty",
"description": "If 'true', then the output is pretty printed.",
"required": false,
"allowMultiple": false
},
{
"type": "boolean",
"paramType": "query",
"name": "export",
"description": "Should this value be exported. Export strips fields that a user can not specify.",
"required": false,
"allowMultiple": false
},
{
"type": "boolean",
"paramType": "query",
"name": "exact",
"description": "Should the export be exact. Exact export maintains cluster-specific fields like 'Namespace'",
"required": false,
"allowMultiple": false
},
{
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the PodSecurityPolicy",
"required": true,
"allowMultiple": false
}
],
"responseMessages": [
{
"code": 200,
"message": "OK",
"responseModel": "v1beta1.PodSecurityPolicy"
}
],
"produces": [
"application/json",
"application/yaml"
],
"consumes": [
"*/*"
]
},
{
"type": "v1beta1.PodSecurityPolicy",
"method": "PUT",
"summary": "replace the specified PodSecurityPolicy",
"nickname": "replaceNamespacedPodSecurityPolicy",
"parameters": [
{
"type": "string",
"paramType": "query",
"name": "pretty",
"description": "If 'true', then the output is pretty printed.",
"required": false,
"allowMultiple": false
},
{
"type": "v1beta1.PodSecurityPolicy",
"paramType": "body",
"name": "body",
"description": "",
"required": true,
"allowMultiple": false
},
{
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the PodSecurityPolicy",
"required": true,
"allowMultiple": false
}
],
"responseMessages": [
{
"code": 200,
"message": "OK",
"responseModel": "v1beta1.PodSecurityPolicy"
}
],
"produces": [
"application/json",
"application/yaml"
],
"consumes": [
"*/*"
]
},
{
"type": "v1beta1.PodSecurityPolicy",
"method": "PATCH",
"summary": "partially update the specified PodSecurityPolicy",
"nickname": "patchNamespacedPodSecurityPolicy",
"parameters": [
{
"type": "string",
"paramType": "query",
"name": "pretty",
"description": "If 'true', then the output is pretty printed.",
"required": false,
"allowMultiple": false
},
{
"type": "unversioned.Patch",
"paramType": "body",
"name": "body",
"description": "",
"required": true,
"allowMultiple": false
},
{
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the PodSecurityPolicy",
"required": true,
"allowMultiple": false
}
],
"responseMessages": [
{
"code": 200,
"message": "OK",
"responseModel": "v1beta1.PodSecurityPolicy"
}
],
"produces": [
"application/json",
"application/yaml"
],
"consumes": [
"application/json-patch+json",
"application/merge-patch+json",
"application/strategic-merge-patch+json"
]
},
{
"type": "unversioned.Status",
"method": "DELETE",
"summary": "delete a PodSecurityPolicy",
"nickname": "deleteNamespacedPodSecurityPolicy",
"parameters": [
{
"type": "string",
"paramType": "query",
"name": "pretty",
"description": "If 'true', then the output is pretty printed.",
"required": false,
"allowMultiple": false
},
{
"type": "v1.DeleteOptions",
"paramType": "body",
"name": "body",
"description": "",
"required": true,
"allowMultiple": false
},
{
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the PodSecurityPolicy",
"required": true,
"allowMultiple": false
}
],
"responseMessages": [
{
"code": 200,
"message": "OK",
"responseModel": "unversioned.Status"
}
],
"produces": [
"application/json",
"application/yaml"
],
"consumes": [
"*/*"
]
}
]
},
{
"path": "/apis/extensions/v1beta1/watch/podsecuritypolicies/{name}",
"description": "API at /apis/extensions/v1beta1",
"operations": [
{
"type": "json.WatchEvent",
"method": "GET",
"summary": "watch changes to an object of kind PodSecurityPolicy",
"nickname": "watchNamespacedPodSecurityPolicy",
"parameters": [
{
"type": "string",
"paramType": "query",
"name": "pretty",
"description": "If 'true', then the output is pretty printed.",
"required": false,
"allowMultiple": false
},
{
"type": "string",
"paramType": "query",
"name": "labelSelector",
"description": "A selector to restrict the list of returned objects by their labels. Defaults to everything.",
"required": false,
"allowMultiple": false
},
{
"type": "string",
"paramType": "query",
"name": "fieldSelector",
"description": "A selector to restrict the list of returned objects by their fields. Defaults to everything.",
"required": false,
"allowMultiple": false
},
{
"type": "boolean",
"paramType": "query",
"name": "watch",
"description": "Watch for changes to the described resources and return them as a stream of add, update, and remove notifications. Specify resourceVersion.",
"required": false,
"allowMultiple": false
},
{
"type": "string",
"paramType": "query",
"name": "resourceVersion",
"description": "When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history.",
"required": false,
"allowMultiple": false
},
{
"type": "integer",
"paramType": "query",
"name": "timeoutSeconds",
"description": "Timeout for the list/watch call.",
"required": false,
"allowMultiple": false
},
{
"type": "string",
"paramType": "path",
"name": "name",
"description": "name of the PodSecurityPolicy",
"required": true,
"allowMultiple": false
}
],
"responseMessages": [
{
"code": 200,
"message": "OK",
"responseModel": "json.WatchEvent"
}
],
"produces": [
"application/json"
],
"consumes": [
"*/*"
]
}
]
},
{
"path": "/apis/extensions/v1beta1/namespaces/{namespace}/replicationcontrollers/{name}/scale",
"description": "API at /apis/extensions/v1beta1",
@ -4470,6 +5012,188 @@
}
}
},
"v1beta1.PodSecurityPolicyList": {
"id": "v1beta1.PodSecurityPolicyList",
"description": "Pod Security Policy List is a list of PodSecurityPolicy objects.",
"required": [
"items"
],
"properties": {
"kind": {
"type": "string",
"description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds"
},
"apiVersion": {
"type": "string",
"description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#resources"
},
"metadata": {
"$ref": "unversioned.ListMeta",
"description": "Standard list metadata. More info: http://docs.k8s.io/api-conventions.md#metadata"
},
"items": {
"type": "array",
"items": {
"$ref": "v1beta1.PodSecurityPolicy"
},
"description": "Items is a list of schema objects."
}
}
},
"v1beta1.PodSecurityPolicy": {
"id": "v1beta1.PodSecurityPolicy",
"description": "Pod Security Policy governs the ability to make requests that affect the Security Context that will be applied to a pod and container.",
"properties": {
"kind": {
"type": "string",
"description": "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds"
},
"apiVersion": {
"type": "string",
"description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#resources"
},
"metadata": {
"$ref": "v1.ObjectMeta",
"description": "Standard object's metadata. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata"
},
"spec": {
"$ref": "v1beta1.PodSecurityPolicySpec",
"description": "Spec defines the policy enforced."
}
}
},
"v1beta1.PodSecurityPolicySpec": {
"id": "v1beta1.PodSecurityPolicySpec",
"description": "Pod Security Policy Spec defines the policy enforced.",
"properties": {
"privileged": {
"type": "boolean",
"description": "privileged determines if a pod can request to be run as privileged."
},
"capabilities": {
"type": "array",
"items": {
"$ref": "v1.Capability"
},
"description": "capabilities is a list of capabilities that can be added."
},
"volumes": {
"type": "array",
"items": {
"$ref": "v1beta1.FSType"
},
"description": "volumes is a white list of allowed volume plugins. Empty indicates that all plugins may be used."
},
"hostNetwork": {
"type": "boolean",
"description": "hostNetwork determines if the policy allows the use of HostNetwork in the pod spec."
},
"hostPorts": {
"type": "array",
"items": {
"$ref": "v1beta1.HostPortRange"
},
"description": "hostPorts determines which host port ranges are allowed to be exposed."
},
"hostPID": {
"type": "boolean",
"description": "hostPID determines if the policy allows the use of HostPID in the pod spec."
},
"hostIPC": {
"type": "boolean",
"description": "hostIPC determines if the policy allows the use of HostIPC in the pod spec."
},
"seLinuxContext": {
"$ref": "v1beta1.SELinuxContextStrategyOptions",
"description": "seLinuxContext is the strategy that will dictate the allowable labels that may be set."
},
"runAsUser": {
"$ref": "v1beta1.RunAsUserStrategyOptions",
"description": "runAsUser is the strategy that will dictate the allowable RunAsUser values that may be set."
}
}
},
"v1beta1.FSType": {
"id": "v1beta1.FSType",
"properties": {}
},
"v1beta1.HostPortRange": {
"id": "v1beta1.HostPortRange",
"description": "Host Port Range defines a range of host ports that will be enabled by a policy for pods to use. It requires both the start and end to be defined.",
"required": [
"min",
"max"
],
"properties": {
"min": {
"type": "integer",
"format": "int32",
"description": "min is the start of the range, inclusive."
},
"max": {
"type": "integer",
"format": "int32",
"description": "max is the end of the range, inclusive."
}
}
},
"v1beta1.SELinuxContextStrategyOptions": {
"id": "v1beta1.SELinuxContextStrategyOptions",
"description": "SELinux Context Strategy Options defines the strategy type and any options used to create the strategy.",
"required": [
"type"
],
"properties": {
"type": {
"type": "string",
"description": "type is the strategy that will dictate the allowable labels that may be set."
},
"seLinuxOptions": {
"$ref": "v1.SELinuxOptions",
"description": "seLinuxOptions required to run as; required for MustRunAs More info: http://releases.k8s.io/HEAD/docs/design/security_context.md#security-context"
}
}
},
"v1beta1.RunAsUserStrategyOptions": {
"id": "v1beta1.RunAsUserStrategyOptions",
"description": "Run A sUser Strategy Options defines the strategy type and any options used to create the strategy.",
"required": [
"type"
],
"properties": {
"type": {
"type": "string",
"description": "type is the strategy that will dictate the allowable RunAsUser values that may be set."
},
"ranges": {
"type": "array",
"items": {
"$ref": "v1beta1.IDRange"
},
"description": "Ranges are the allowed ranges of uids that may be used."
}
}
},
"v1beta1.IDRange": {
"id": "v1beta1.IDRange",
"description": "ID Range provides a min/max of an allowed range of IDs.",
"required": [
"min",
"max"
],
"properties": {
"min": {
"type": "integer",
"format": "int64",
"description": "Min is the start of the range, inclusive."
},
"max": {
"type": "integer",
"format": "int64",
"description": "Max is the end of the range, inclusive."
}
}
},
"v1beta1.Scale": {
"id": "v1beta1.Scale",
"description": "represents a scaling request for a resource.",

View File

@ -330,6 +330,7 @@ _kubectl_get()
must_have_one_noun+=("persistentvolume")
must_have_one_noun+=("persistentvolumeclaim")
must_have_one_noun+=("pod")
must_have_one_noun+=("podsecuritypolicy")
must_have_one_noun+=("podtemplate")
must_have_one_noun+=("replicationcontroller")
must_have_one_noun+=("resourcequota")
@ -827,6 +828,7 @@ _kubectl_delete()
must_have_one_noun+=("persistentvolume")
must_have_one_noun+=("persistentvolumeclaim")
must_have_one_noun+=("pod")
must_have_one_noun+=("podsecuritypolicy")
must_have_one_noun+=("podtemplate")
must_have_one_noun+=("replicationcontroller")
must_have_one_noun+=("resourcequota")
@ -1964,6 +1966,7 @@ _kubectl_label()
must_have_one_noun+=("persistentvolume")
must_have_one_noun+=("persistentvolumeclaim")
must_have_one_noun+=("pod")
must_have_one_noun+=("podsecuritypolicy")
must_have_one_noun+=("podtemplate")
must_have_one_noun+=("replicationcontroller")
must_have_one_noun+=("resourcequota")

View File

@ -458,6 +458,10 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="_v1beta1_fstype">v1beta1.FSType</h3>
</div>
<div class="sect2">
<h3 id="_v1_selinuxoptions">v1.SELinuxOptions</h3>
@ -595,6 +599,47 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="_v1beta1_selinuxcontextstrategyoptions">v1beta1.SELinuxContextStrategyOptions</h3>
<div class="paragraph">
<p>SELinux Context Strategy Options defines the strategy type and any options used to create the strategy.</p>
</div>
<table class="tableblock frame-all grid-all" style="width:100%; ">
<colgroup>
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Name</th>
<th class="tableblock halign-left valign-top">Description</th>
<th class="tableblock halign-left valign-top">Required</th>
<th class="tableblock halign-left valign-top">Schema</th>
<th class="tableblock halign-left valign-top">Default</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">type</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">type is the strategy that will dictate the allowable labels that may be set.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">seLinuxOptions</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">seLinuxOptions required to run as; required for MustRunAs More info: <a href="http://releases.k8s.io/HEAD/docs/design/security_context.md#security-context">http://releases.k8s.io/HEAD/docs/design/security_context.md#security-context</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_selinuxoptions">v1.SELinuxOptions</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="_v1_volumemount">v1.VolumeMount</h3>
@ -1137,6 +1182,61 @@ Examples:<br>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="_v1beta1_podsecuritypolicylist">v1beta1.PodSecurityPolicyList</h3>
<div class="paragraph">
<p>Pod Security Policy List is a list of PodSecurityPolicy objects.</p>
</div>
<table class="tableblock frame-all grid-all" style="width:100%; ">
<colgroup>
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Name</th>
<th class="tableblock halign-left valign-top">Description</th>
<th class="tableblock halign-left valign-top">Required</th>
<th class="tableblock halign-left valign-top">Schema</th>
<th class="tableblock halign-left valign-top">Default</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">kind</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: <a href="http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds">http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">apiVersion</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: <a href="http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#resources">http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#resources</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">metadata</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Standard list metadata. More info: <a href="http://docs.k8s.io/api-conventions.md#metadata">http://docs.k8s.io/api-conventions.md#metadata</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_unversioned_listmeta">unversioned.ListMeta</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">items</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Items is a list of schema objects.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1beta1_podsecuritypolicy">v1beta1.PodSecurityPolicy</a> array</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="_v1_tcpsocketaction">v1.TCPSocketAction</h3>
@ -2706,6 +2806,47 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="_v1beta1_hostportrange">v1beta1.HostPortRange</h3>
<div class="paragraph">
<p>Host Port Range defines a range of host ports that will be enabled by a policy for pods to use. It requires both the start and end to be defined.</p>
</div>
<table class="tableblock frame-all grid-all" style="width:100%; ">
<colgroup>
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Name</th>
<th class="tableblock halign-left valign-top">Description</th>
<th class="tableblock halign-left valign-top">Required</th>
<th class="tableblock halign-left valign-top">Schema</th>
<th class="tableblock halign-left valign-top">Default</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">min</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">min is the start of the range, inclusive.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">integer (int32)</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">max</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">max is the end of the range, inclusive.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">integer (int32)</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="_v1beta1_labelselectorrequirement">v1beta1.LabelSelectorRequirement</h3>
@ -2816,6 +2957,47 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="_v1beta1_runasuserstrategyoptions">v1beta1.RunAsUserStrategyOptions</h3>
<div class="paragraph">
<p>Run A sUser Strategy Options defines the strategy type and any options used to create the strategy.</p>
</div>
<table class="tableblock frame-all grid-all" style="width:100%; ">
<colgroup>
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Name</th>
<th class="tableblock halign-left valign-top">Description</th>
<th class="tableblock halign-left valign-top">Required</th>
<th class="tableblock halign-left valign-top">Schema</th>
<th class="tableblock halign-left valign-top">Default</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">type</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">type is the strategy that will dictate the allowable RunAsUser values that may be set.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">ranges</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Ranges are the allowed ranges of uids that may be used.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1beta1_idrange">v1beta1.IDRange</a> array</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="_v1_envvar">v1.EnvVar</h3>
@ -3251,6 +3433,96 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="_v1beta1_podsecuritypolicyspec">v1beta1.PodSecurityPolicySpec</h3>
<div class="paragraph">
<p>Pod Security Policy Spec defines the policy enforced.</p>
</div>
<table class="tableblock frame-all grid-all" style="width:100%; ">
<colgroup>
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Name</th>
<th class="tableblock halign-left valign-top">Description</th>
<th class="tableblock halign-left valign-top">Required</th>
<th class="tableblock halign-left valign-top">Schema</th>
<th class="tableblock halign-left valign-top">Default</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">privileged</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">privileged determines if a pod can request to be run as privileged.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">capabilities</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">capabilities is a list of capabilities that can be added.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_capability">v1.Capability</a> array</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">volumes</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">volumes is a white list of allowed volume plugins. Empty indicates that all plugins may be used.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1beta1_fstype">v1beta1.FSType</a> array</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">hostNetwork</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">hostNetwork determines if the policy allows the use of HostNetwork in the pod spec.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">hostPorts</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">hostPorts determines which host port ranges are allowed to be exposed.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1beta1_hostportrange">v1beta1.HostPortRange</a> array</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">hostPID</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">hostPID determines if the policy allows the use of HostPID in the pod spec.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">hostIPC</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">hostIPC determines if the policy allows the use of HostIPC in the pod spec.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">boolean</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">seLinuxContext</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">seLinuxContext is the strategy that will dictate the allowable labels that may be set.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1beta1_selinuxcontextstrategyoptions">v1beta1.SELinuxContextStrategyOptions</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">runAsUser</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">runAsUser is the strategy that will dictate the allowable RunAsUser values that may be set.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1beta1_runasuserstrategyoptions">v1beta1.RunAsUserStrategyOptions</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="_v1_volume">v1.Volume</h3>
@ -3594,6 +3866,61 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="_v1beta1_podsecuritypolicy">v1beta1.PodSecurityPolicy</h3>
<div class="paragraph">
<p>Pod Security Policy governs the ability to make requests that affect the Security Context that will be applied to a pod and container.</p>
</div>
<table class="tableblock frame-all grid-all" style="width:100%; ">
<colgroup>
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Name</th>
<th class="tableblock halign-left valign-top">Description</th>
<th class="tableblock halign-left valign-top">Required</th>
<th class="tableblock halign-left valign-top">Schema</th>
<th class="tableblock halign-left valign-top">Default</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">kind</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: <a href="http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds">http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#types-kinds</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">apiVersion</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: <a href="http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#resources">http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#resources</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">string</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">metadata</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Standard object&#8217;s metadata. More info: <a href="http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata">http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata</a></p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1_objectmeta">v1.ObjectMeta</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">spec</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Spec defines the policy enforced.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock"><a href="#_v1beta1_podsecuritypolicyspec">v1beta1.PodSecurityPolicySpec</a></p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="_v1_capability">v1.Capability</h3>
@ -3916,6 +4243,47 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="_v1beta1_idrange">v1beta1.IDRange</h3>
<div class="paragraph">
<p>ID Range provides a min/max of an allowed range of IDs.</p>
</div>
<table class="tableblock frame-all grid-all" style="width:100%; ">
<colgroup>
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
<col style="width:20%;">
</colgroup>
<thead>
<tr>
<th class="tableblock halign-left valign-top">Name</th>
<th class="tableblock halign-left valign-top">Description</th>
<th class="tableblock halign-left valign-top">Required</th>
<th class="tableblock halign-left valign-top">Schema</th>
<th class="tableblock halign-left valign-top">Default</th>
</tr>
</thead>
<tbody>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">min</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Min is the start of the range, inclusive.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">integer (int64)</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
<tr>
<td class="tableblock halign-left valign-top"><p class="tableblock">max</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">Max is the end of the range, inclusive.</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">true</p></td>
<td class="tableblock halign-left valign-top"><p class="tableblock">integer (int64)</p></td>
<td class="tableblock halign-left valign-top"></td>
</tr>
</tbody>
</table>
</div>
<div class="sect2">
<h3 id="_v1beta1_horizontalpodautoscalerlist">v1beta1.HorizontalPodAutoscalerList</h3>
@ -4464,7 +4832,7 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
</div>
<div id="footer">
<div id="footer-text">
Last updated 2016-02-01 21:08:12 UTC
Last updated 2016-02-05 04:29:01 UTC
</div>
</div>
</body>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,377 @@
<!-- BEGIN MUNGE: UNVERSIONED_WARNING -->
<!-- BEGIN STRIP_FOR_RELEASE -->
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<h2>PLEASE NOTE: This document applies to the HEAD of the source tree</h2>
If you are using a released version of Kubernetes, you should
refer to the docs that go with that version.
Documentation for other releases can be found at
[releases.k8s.io](http://releases.k8s.io).
</strong>
--
<!-- END STRIP_FOR_RELEASE -->
<!-- END MUNGE: UNVERSIONED_WARNING -->
## Abstract
PodSecurityPolicy allows cluster administrators to control the creation and validation of a security
context for a pod and containers.
## Motivation
Administration of a multi-tenant cluster requires the ability to provide varying sets of permissions
among the tenants, the infrastructure components, and end users of the system who may themselves be
administrators within their own isolated namespace.
Actors in a cluster may include infrastructure that is managed by administrators, infrastructure
that is exposed to end users (builds, deployments), the isolated end user namespaces in the cluster, and
the individual users inside those namespaces. Infrastructure components that operate on behalf of a
user (builds, deployments) should be allowed to run at an elevated level of permissions without
granting the user themselves an elevated set of permissions.
## Goals
1. Associate [service accounts](http://docs.k8s.io/design/service_accounts.md), groups, and users with
a set of constraints that dictate how a security context is established for a pod and the pod's containers.
1. Provide the ability for users and infrastructure components to run pods with elevated privileges
on behalf of another user or within a namespace where privileges are more restrictive.
1. Secure the ability to reference elevated permissions or to change the constraints under which
a user runs.
## Use Cases
Use case 1:
As an administrator, I can create a namespace for a person that can't create privileged containers
AND enforce that the UID of the containers is set to a certain value
Use case 2:
As a cluster operator, an infrastructure component should be able to create a pod with elevated
privileges in a namespace where regular users cannot create pods with these privileges or execute
commands in that pod.
Use case 3:
As a cluster administrator, I can allow a given namespace (or service account) to create privileged
pods or to run root pods
Use case 4:
As a cluster administrator, I can allow a project administrator to control the security contexts of
pods and service accounts within a project
## Requirements
1. Provide a set of restrictions that controls how a security context is created for pods and containers
as a new cluster-scoped object called `PodSecurityPolicy`.
1. User information in `user.Info` must be available to admission controllers. (Completed in
https://github.com/GoogleCloudPlatform/kubernetes/pull/8203)
1. Some authorizers may restrict a users ability to reference a service account. Systems requiring
the ability to secure service accounts on a user level must be able to add a policy that enables
referencing specific service accounts themselves.
1. Admission control must validate the creation of Pods against the allowed set of constraints.
## Design
### Model
PodSecurityPolicy objects exist in the root scope, outside of a namespace. The
PodSecurityPolicy will reference users and groups that are allowed
to operate under the constraints. In order to support this, `ServiceAccounts` must be mapped
to a user name or group list by the authentication/authorization layers. This allows the security
context to treat users, groups, and service accounts uniformly.
Below is a list of PodSecurityPolicies which will likely serve most use cases:
1. A default policy object. This object is permissioned to something which covers all actors, such
as a `system:authenticated` group, and will likely be the most restrictive set of constraints.
1. A default constraints object for service accounts. This object can be identified as serving
a group identified by `system:service-accounts`, which can be imposed by the service account authenticator / token generator.
1. Cluster admin constraints identified by `system:cluster-admins` group - a set of constraints with elevated privileges that can be used
by an administrative user or group.
1. Infrastructure components constraints which can be identified either by a specific service
account or by a group containing all service accounts.
```go
// PodSecurityPolicy governs the ability to make requests that affect the SecurityContext
// that will be applied to a pod and container.
type PodSecurityPolicy struct {
unversioned.TypeMeta `json:",inline"`
api.ObjectMeta `json:"metadata,omitempty"`
// Spec defines the policy enforced.
Spec PodSecurityPolicySpec `json:"spec,omitempty"`
}
// PodSecurityPolicySpec defines the policy enforced.
type PodSecurityPolicySpec struct {
// Privileged determines if a pod can request to be run as privileged.
Privileged bool `json:"privileged,omitempty"`
// Capabilities is a list of capabilities that can be added.
Capabilities []api.Capability `json:"capabilities,omitempty"`
// Volumes allows and disallows the use of different types of volume plugins.
Volumes VolumeSecurityPolicy `json:"volumes,omitempty"`
// HostNetwork determines if the policy allows the use of HostNetwork in the pod spec.
HostNetwork bool `json:"hostNetwork,omitempty"`
// HostPorts determines which host port ranges are allowed to be exposed.
HostPorts []HostPortRange `json:"hostPorts,omitempty"`
// HostPID determines if the policy allows the use of HostPID in the pod spec.
HostPID bool `json:"hostPID,omitempty"`
// HostIPC determines if the policy allows the use of HostIPC in the pod spec.
HostIPC bool `json:"hostIPC,omitempty"`
// SELinuxContext is the strategy that will dictate the allowable labels that may be set.
SELinuxContext SELinuxContextStrategyOptions `json:"seLinuxContext,omitempty"`
// RunAsUser is the strategy that will dictate the allowable RunAsUser values that may be set.
RunAsUser RunAsUserStrategyOptions `json:"runAsUser,omitempty"`
// The users who have permissions to use this policy
Users []string `json:"users,omitempty"`
// The groups that have permission to use this policy
Groups []string `json:"groups,omitempty"`
}
// HostPortRange defines a range of host ports that will be enabled by a policy
// for pods to use. It requires both the start and end to be defined.
type HostPortRange struct {
// Start is the beginning of the port range which will be allowed.
Start int `json:"start"`
// End is the end of the port range which will be allowed.
End int `json:"end"`
}
// VolumeSecurityPolicy allows and disallows the use of different types of volume plugins.
type VolumeSecurityPolicy struct {
// HostPath allows or disallows the use of the HostPath volume plugin.
// More info: http://releases.k8s.io/HEAD/docs/user-guide/volumes.md#hostpath
HostPath bool `json:"hostPath,omitempty"`
// EmptyDir allows or disallows the use of the EmptyDir volume plugin.
// More info: http://releases.k8s.io/HEAD/docs/user-guide/volumes.md#emptydir
EmptyDir bool `json:"emptyDir,omitempty"`
// GCEPersistentDisk allows or disallows the use of the GCEPersistentDisk volume plugin.
// More info: http://releases.k8s.io/HEAD/docs/user-guide/volumes.md#gcepersistentdisk
GCEPersistentDisk bool `json:"gcePersistentDisk,omitempty"`
// AWSElasticBlockStore allows or disallows the use of the AWSElasticBlockStore volume plugin.
// More info: http://releases.k8s.io/HEAD/docs/user-guide/volumes.md#awselasticblockstore
AWSElasticBlockStore bool `json:"awsElasticBlockStore,omitempty"`
// GitRepo allows or disallows the use of the GitRepo volume plugin.
GitRepo bool `json:"gitRepo,omitempty"`
// Secret allows or disallows the use of the Secret volume plugin.
// More info: http://releases.k8s.io/HEAD/docs/user-guide/volumes.md#secrets
Secret bool `json:"secret,omitempty"`
// NFS allows or disallows the use of the NFS volume plugin.
// More info: http://releases.k8s.io/HEAD/docs/user-guide/volumes.md#nfs
NFS bool `json:"nfs,omitempty"`
// ISCSI allows or disallows the use of the ISCSI volume plugin.
// More info: http://releases.k8s.io/HEAD/examples/iscsi/README.md
ISCSI bool `json:"iscsi,omitempty"`
// Glusterfs allows or disallows the use of the Glusterfs volume plugin.
// More info: http://releases.k8s.io/HEAD/examples/glusterfs/README.md
Glusterfs bool `json:"glusterfs,omitempty"`
// PersistentVolumeClaim allows or disallows the use of the PersistentVolumeClaim volume plugin.
// More info: http://releases.k8s.io/HEAD/docs/user-guide/persistent-volumes.md#persistentvolumeclaims
PersistentVolumeClaim bool `json:"persistentVolumeClaim,omitempty"`
// RBD allows or disallows the use of the RBD volume plugin.
// More info: http://releases.k8s.io/HEAD/examples/rbd/README.md
RBD bool `json:"rbd,omitempty"`
// Cinder allows or disallows the use of the Cinder volume plugin.
// More info: http://releases.k8s.io/HEAD/examples/mysql-cinder-pd/README.md
Cinder bool `json:"cinder,omitempty"`
// CephFS allows or disallows the use of the CephFS volume plugin.
CephFS bool `json:"cephfs,omitempty"`
// DownwardAPI allows or disallows the use of the DownwardAPI volume plugin.
DownwardAPI bool `json:"downwardAPI,omitempty"`
// FC allows or disallows the use of the FC volume plugin.
FC bool `json:"fc,omitempty"`
}
// SELinuxContextStrategyOptions defines the strategy type and any options used to create the strategy.
type SELinuxContextStrategyOptions struct {
// Type is the strategy that will dictate the allowable labels that may be set.
Type SELinuxContextStrategy `json:"type"`
// seLinuxOptions required to run as; required for MustRunAs
// More info: http://releases.k8s.io/HEAD/docs/design/security_context.md#security-context
SELinuxOptions *api.SELinuxOptions `json:"seLinuxOptions,omitempty"`
}
// SELinuxContextStrategyType denotes strategy types for generating SELinux options for a
// SecurityContext.
type SELinuxContextStrategy string
const (
// container must have SELinux labels of X applied.
SELinuxStrategyMustRunAs SELinuxContextStrategy = "MustRunAs"
// container may make requests for any SELinux context labels.
SELinuxStrategyRunAsAny SELinuxContextStrategy = "RunAsAny"
)
// RunAsUserStrategyOptions defines the strategy type and any options used to create the strategy.
type RunAsUserStrategyOptions struct {
// Type is the strategy that will dictate the allowable RunAsUser values that may be set.
Type RunAsUserStrategy `json:"type"`
// UID is the user id that containers must run as. Required for the MustRunAs strategy if not using
// a strategy that supports pre-allocated uids.
UID *int64 `json:"uid,omitempty"`
// UIDRangeMin defines the min value for a strategy that allocates by a range based strategy.
UIDRangeMin *int64 `json:"uidRangeMin,omitempty"`
// UIDRangeMax defines the max value for a strategy that allocates by a range based strategy.
UIDRangeMax *int64 `json:"uidRangeMax,omitempty"`
}
// RunAsUserStrategyType denotes strategy types for generating RunAsUser values for a
// SecurityContext.
type RunAsUserStrategy string
const (
// container must run as a particular uid.
RunAsUserStrategyMustRunAs RunAsUserStrategy = "MustRunAs"
// container must run as a particular uid.
RunAsUserStrategyMustRunAsRange RunAsUserStrategy = "MustRunAsRange"
// container must run as a non-root uid
RunAsUserStrategyMustRunAsNonRoot RunAsUserStrategy = "MustRunAsNonRoot"
// container may make requests for any uid.
RunAsUserStrategyRunAsAny RunAsUserStrategy = "RunAsAny"
)
```
### PodSecurityPolicy Lifecycle
As reusable objects in the root scope, PodSecurityPolicy follows the lifecycle of the
cluster itself. Maintenance of constraints such as adding, assigning, or changing them is the
responsibility of the cluster administrator.
Creating a new user within a namespace should not require the cluster administrator to
define the user's PodSecurityPolicy. They should receive the default set of policies
that the administrator has defined for the groups they are assigned.
## Default PodSecurityPolicy And Overrides
In order to establish policy for service accounts and users, there must be a way
to identify the default set of constraints that is to be used. This is best accomplished by using
groups. As mentioned above, groups may be used by the authentication/authorization layer to ensure
that every user maps to at least one group (with a default example of `system:authenticated`) and it
is up to the cluster administrator to ensure that a `PodSecurityPolicy` object exists that
references the group.
If an administrator would like to provide a user with a changed set of security context permissions,
they may do the following:
1. Create a new `PodSecurityPolicy` object and add a reference to the user or a group
that the user belongs to.
1. Add the user (or group) to an existing `PodSecurityPolicy` object with the proper
elevated privileges.
## Admission
Admission control using an authorizer provides the ability to control the creation of resources
based on capabilities granted to a user. In terms of the `PodSecurityPolicy`, it means
that an admission controller may inspect the user info made available in the context to retrieve
an appropriate set of policies for validation.
The appropriate set of PodSecurityPolicies is defined as all of the policies
available that have reference to the user or groups that the user belongs to.
Admission will use the PodSecurityPolicy to ensure that any requests for a
specific security context setting are valid and to generate settings using the following approach:
1. Determine all the available `PodSecurityPolicy` objects that are allowed to be used
1. Sort the `PodSecurityPolicy` objects in a most restrictive to least restrictive order.
1. For each `PodSecurityPolicy`, generate a `SecurityContext` for each container. The generation phase will not override
any user requested settings in the `SecurityContext`, and will rely on the validation phase to ensure that
the user requests are valid.
1. Validate the generated `SecurityContext` to ensure it falls within the boundaries of the `PodSecurityPolicy`
1. If all containers validate under a single `PodSecurityPolicy` then the pod will be admitted
1. If all containers DO NOT validate under the `PodSecurityPolicy` then try the next `PodSecurityPolicy`
1. If no `PodSecurityPolicy` validates for the pod then the pod will not be admitted
## Creation of a SecurityContext Based on PodSecurityPolicy
The creation of a `SecurityContext` based on a `PodSecurityPolicy` is based upon the configured
settings of the `PodSecurityPolicy`.
There are three scenarios under which a `PodSecurityPolicy` field may fall:
1. Governed by a boolean: fields of this type will be defaulted to the most restrictive value.
For instance, `AllowPrivileged` will always be set to false if unspecified.
1. Governed by an allowable set: fields of this type will be checked against the set to ensure
their value is allowed. For example, `AllowCapabilities` will ensure that only capabilities
that are allowed to be requested are considered valid. `HostNetworkSources` will ensure that
only pods created from source X are allowed to request access to the host network.
1. Governed by a strategy: Items that have a strategy to generate a value will provide a
mechanism to generate the value as well as a mechanism to ensure that a specified value falls into
the set of allowable values. See the Types section for the description of the interfaces that
strategies must implement.
Strategies have the ability to become dynamic. In order to support a dynamic strategy it should be
possible to make a strategy that has the ability to either be pre-populated with dynamic data by
another component (such as an admission controller) or has the ability to retrieve the information
itself based on the data in the pod. An example of this would be a pre-allocated UID for the namespace.
A dynamic `RunAsUser` strategy could inspect the namespace of the pod in order to find the required pre-allocated
UID and generate or validate requests based on that information.
```go
// SELinuxStrategy defines the interface for all SELinux constraint strategies.
type SELinuxStrategy interface {
// Generate creates the SELinuxOptions based on constraint rules.
Generate(pod *api.Pod, container *api.Container) (*api.SELinuxOptions, error)
// Validate ensures that the specified values fall within the range of the strategy.
Validate(pod *api.Pod, container *api.Container) fielderrors.ValidationErrorList
}
// RunAsUserStrategy defines the interface for all uid constraint strategies.
type RunAsUserStrategy interface {
// Generate creates the uid based on policy rules.
Generate(pod *api.Pod, container *api.Container) (*int64, error)
// Validate ensures that the specified values fall within the range of the strategy.
Validate(pod *api.Pod, container *api.Container) fielderrors.ValidationErrorList
}
```
## Escalating Privileges by an Administrator
An administrator may wish to create a resource in a namespace that runs with
escalated privileges. By allowing security context
constraints to operate on both the requesting user and the pod's service account, administrators are able to
create pods in namespaces with elevated privileges based on the administrator's security context
constraints.
This also allows the system to guard commands being executed in the non-conforming container. For
instance, an `exec` command can first check the security context of the pod against the security
context constraints of the user or the user's ability to reference a service account.
If it does not validate then it can block users from executing the command. Since the validation
will be user aware, administrators would still be able to run the commands that are restricted to normal users.
## Interaction with the Kubelet
In certain cases, the Kubelet may need provide information about
the image in order to validate the security context. An example of this is a cluster
that is configured to run with a UID strategy of `MustRunAsNonRoot`.
In this case the admission controller can set the existing `MustRunAsNonRoot` flag on the `SecurityContext`
based on the UID strategy of the `SecurityPolicy`. It should still validate any requests on the pod
for a specific UID and fail early if possible. However, if the `RunAsUser` is not set on the pod
it should still admit the pod and allow the Kubelet to ensure that the image does not run as
`root` with the existing non-root checks.
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/docs/proposals/security-context-constraints.md?pixel)]()
<!-- END MUNGE: GENERATED_ANALYTICS -->

View File

@ -404,6 +404,13 @@ func FuzzerFor(t *testing.T, version unversioned.GroupVersion, src rand.Source)
MaxUnavailable: intstr.FromInt(10),
}
},
func(psp *extensions.PodSecurityPolicySpec, c fuzz.Continue) {
c.FuzzNoCustom(psp) // fuzz self without calling this function again
userTypes := []extensions.RunAsUserStrategy{extensions.RunAsUserStrategyMustRunAsNonRoot, extensions.RunAsUserStrategyMustRunAs, extensions.RunAsUserStrategyRunAsAny}
psp.RunAsUser.Type = userTypes[c.Rand.Intn(len(userTypes))]
seLinuxTypes := []extensions.SELinuxContextStrategy{extensions.SELinuxStrategyRunAsAny, extensions.SELinuxStrategyMustRunAs}
psp.SELinuxContext.Type = seLinuxTypes[c.Rand.Intn(len(seLinuxTypes))]
},
)
return f
}

View File

@ -90,7 +90,9 @@ func enableVersions(externalVersions []unversioned.GroupVersion) error {
func newRESTMapper(externalVersions []unversioned.GroupVersion) meta.RESTMapper {
// the list of kinds that are scoped at the root of the api hierarchy
// if a kind is not enumerated here, it is assumed to have a namespace scope
rootScoped := sets.NewString()
rootScoped := sets.NewString(
"PodSecurityPolicy",
)
ignoredKinds := sets.NewString()

View File

@ -70,6 +70,8 @@ func addKnownTypes(scheme *runtime.Scheme) {
&ReplicaSet{},
&ReplicaSetList{},
&api.ExportOptions{},
&PodSecurityPolicy{},
&PodSecurityPolicyList{},
)
}
@ -94,3 +96,5 @@ func (obj *Ingress) GetObjectKind() unversioned.ObjectKind {
func (obj *IngressList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ReplicaSet) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ReplicaSetList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PodSecurityPolicy) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PodSecurityPolicyList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }

File diff suppressed because it is too large Load Diff

View File

@ -842,3 +842,123 @@ type ReplicaSetStatus struct {
// ObservedGeneration is the most recent generation observed by the controller.
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
}
// PodSecurityPolicy governs the ability to make requests that affect the SecurityContext
// that will be applied to a pod and container.
type PodSecurityPolicy struct {
unversioned.TypeMeta `json:",inline"`
api.ObjectMeta `json:"metadata,omitempty"`
// Spec defines the policy enforced.
Spec PodSecurityPolicySpec `json:"spec,omitempty"`
}
// PodSecurityPolicySpec defines the policy enforced.
type PodSecurityPolicySpec struct {
// Privileged determines if a pod can request to be run as privileged.
Privileged bool `json:"privileged,omitempty"`
// Capabilities is a list of capabilities that can be added.
Capabilities []api.Capability `json:"capabilities,omitempty"`
// Volumes is a white list of allowed volume plugins. Empty indicates that all plugins
// may be used.
Volumes []FSType `json:"volumes,omitempty"`
// HostNetwork determines if the policy allows the use of HostNetwork in the pod spec.
HostNetwork bool `json:"hostNetwork,omitempty"`
// HostPorts determines which host port ranges are allowed to be exposed.
HostPorts []HostPortRange `json:"hostPorts,omitempty"`
// HostPID determines if the policy allows the use of HostPID in the pod spec.
HostPID bool `json:"hostPID,omitempty"`
// HostIPC determines if the policy allows the use of HostIPC in the pod spec.
HostIPC bool `json:"hostIPC,omitempty"`
// SELinuxContext is the strategy that will dictate the allowable labels that may be set.
SELinuxContext SELinuxContextStrategyOptions `json:"seLinuxContext,omitempty"`
// RunAsUser is the strategy that will dictate the allowable RunAsUser values that may be set.
RunAsUser RunAsUserStrategyOptions `json:"runAsUser,omitempty"`
}
// HostPortRange defines a range of host ports that will be enabled by a policy
// for pods to use. It requires both the start and end to be defined.
type HostPortRange struct {
// Min is the start of the range, inclusive.
Min int `json:"min"`
// Max is the end of the range, inclusive.
Max int `json:"max"`
}
// FSType gives strong typing to different file systems that are used by volumes.
type FSType string
var (
HostPath FSType = "hostPath"
EmptyDir FSType = "emptyDir"
GCEPersistentDisk FSType = "gcePersistentDisk"
AWSElasticBlockStore FSType = "awsElasticBlockStore"
GitRepo FSType = "gitRepo"
Secret FSType = "secret"
NFS FSType = "nfs"
ISCSI FSType = "iscsi"
Glusterfs FSType = "glusterfs"
PersistentVolumeClaim FSType = "persistentVolumeClaim"
RBD FSType = "rbd"
Cinder FSType = "cinder"
CephFS FSType = "cephFS"
DownwardAPI FSType = "downwardAPI"
FC FSType = "fc"
)
// SELinuxContextStrategyOptions defines the strategy type and any options used to create the strategy.
type SELinuxContextStrategyOptions struct {
// Type is the strategy that will dictate the allowable labels that may be set.
Type SELinuxContextStrategy `json:"type"`
// seLinuxOptions required to run as; required for MustRunAs
// More info: http://releases.k8s.io/HEAD/docs/design/security_context.md#security-context
SELinuxOptions *api.SELinuxOptions `json:"seLinuxOptions,omitempty"`
}
// SELinuxContextStrategyType denotes strategy types for generating SELinux options for a
// SecurityContext.
type SELinuxContextStrategy string
const (
// container must have SELinux labels of X applied.
SELinuxStrategyMustRunAs SELinuxContextStrategy = "MustRunAs"
// container may make requests for any SELinux context labels.
SELinuxStrategyRunAsAny SELinuxContextStrategy = "RunAsAny"
)
// RunAsUserStrategyOptions defines the strategy type and any options used to create the strategy.
type RunAsUserStrategyOptions struct {
// Type is the strategy that will dictate the allowable RunAsUser values that may be set.
Type RunAsUserStrategy `json:"type"`
// Ranges are the allowed ranges of uids that may be used.
Ranges []IDRange `json:"ranges,omitempty"`
}
// IDRange provides a min/max of an allowed range of IDs.
type IDRange struct {
// Min is the start of the range, inclusive.
Min int64 `json:"min"`
// Max is the end of the range, inclusive.
Max int64 `json:"max"`
}
// RunAsUserStrategyType denotes strategy types for generating RunAsUser values for a
// SecurityContext.
type RunAsUserStrategy string
const (
// container must run as a particular uid.
RunAsUserStrategyMustRunAs RunAsUserStrategy = "MustRunAs"
// container must run as a non-root uid
RunAsUserStrategyMustRunAsNonRoot RunAsUserStrategy = "MustRunAsNonRoot"
// container may make requests for any uid.
RunAsUserStrategyRunAsAny RunAsUserStrategy = "RunAsAny"
)
// PodSecurityPolicyList is a list of PodSecurityPolicy objects.
type PodSecurityPolicyList struct {
unversioned.TypeMeta `json:",inline"`
unversioned.ListMeta `json:"metadata,omitempty"`
Items []PodSecurityPolicy `json:"items"`
}

View File

@ -2982,6 +2982,32 @@ func Convert_extensions_HorizontalPodAutoscalerStatus_To_v1beta1_HorizontalPodAu
return autoConvert_extensions_HorizontalPodAutoscalerStatus_To_v1beta1_HorizontalPodAutoscalerStatus(in, out, s)
}
func autoConvert_extensions_HostPortRange_To_v1beta1_HostPortRange(in *extensions.HostPortRange, out *HostPortRange, s conversion.Scope) error {
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
defaulting.(func(*extensions.HostPortRange))(in)
}
out.Min = int32(in.Min)
out.Max = int32(in.Max)
return nil
}
func Convert_extensions_HostPortRange_To_v1beta1_HostPortRange(in *extensions.HostPortRange, out *HostPortRange, s conversion.Scope) error {
return autoConvert_extensions_HostPortRange_To_v1beta1_HostPortRange(in, out, s)
}
func autoConvert_extensions_IDRange_To_v1beta1_IDRange(in *extensions.IDRange, out *IDRange, s conversion.Scope) error {
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
defaulting.(func(*extensions.IDRange))(in)
}
out.Min = in.Min
out.Max = in.Max
return nil
}
func Convert_extensions_IDRange_To_v1beta1_IDRange(in *extensions.IDRange, out *IDRange, s conversion.Scope) error {
return autoConvert_extensions_IDRange_To_v1beta1_IDRange(in, out, s)
}
func autoConvert_extensions_Ingress_To_v1beta1_Ingress(in *extensions.Ingress, out *Ingress, s conversion.Scope) error {
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
defaulting.(func(*extensions.Ingress))(in)
@ -3293,6 +3319,100 @@ func Convert_extensions_NodeUtilization_To_v1beta1_NodeUtilization(in *extension
return autoConvert_extensions_NodeUtilization_To_v1beta1_NodeUtilization(in, out, s)
}
func autoConvert_extensions_PodSecurityPolicy_To_v1beta1_PodSecurityPolicy(in *extensions.PodSecurityPolicy, out *PodSecurityPolicy, s conversion.Scope) error {
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
defaulting.(func(*extensions.PodSecurityPolicy))(in)
}
if err := api.Convert_unversioned_TypeMeta_To_unversioned_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {
return err
}
if err := Convert_api_ObjectMeta_To_v1_ObjectMeta(&in.ObjectMeta, &out.ObjectMeta, s); err != nil {
return err
}
if err := Convert_extensions_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec(&in.Spec, &out.Spec, s); err != nil {
return err
}
return nil
}
func Convert_extensions_PodSecurityPolicy_To_v1beta1_PodSecurityPolicy(in *extensions.PodSecurityPolicy, out *PodSecurityPolicy, s conversion.Scope) error {
return autoConvert_extensions_PodSecurityPolicy_To_v1beta1_PodSecurityPolicy(in, out, s)
}
func autoConvert_extensions_PodSecurityPolicyList_To_v1beta1_PodSecurityPolicyList(in *extensions.PodSecurityPolicyList, out *PodSecurityPolicyList, s conversion.Scope) error {
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
defaulting.(func(*extensions.PodSecurityPolicyList))(in)
}
if err := api.Convert_unversioned_TypeMeta_To_unversioned_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {
return err
}
if err := api.Convert_unversioned_ListMeta_To_unversioned_ListMeta(&in.ListMeta, &out.ListMeta, s); err != nil {
return err
}
if in.Items != nil {
out.Items = make([]PodSecurityPolicy, len(in.Items))
for i := range in.Items {
if err := Convert_extensions_PodSecurityPolicy_To_v1beta1_PodSecurityPolicy(&in.Items[i], &out.Items[i], s); err != nil {
return err
}
}
} else {
out.Items = nil
}
return nil
}
func Convert_extensions_PodSecurityPolicyList_To_v1beta1_PodSecurityPolicyList(in *extensions.PodSecurityPolicyList, out *PodSecurityPolicyList, s conversion.Scope) error {
return autoConvert_extensions_PodSecurityPolicyList_To_v1beta1_PodSecurityPolicyList(in, out, s)
}
func autoConvert_extensions_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec(in *extensions.PodSecurityPolicySpec, out *PodSecurityPolicySpec, s conversion.Scope) error {
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
defaulting.(func(*extensions.PodSecurityPolicySpec))(in)
}
out.Privileged = in.Privileged
if in.Capabilities != nil {
out.Capabilities = make([]v1.Capability, len(in.Capabilities))
for i := range in.Capabilities {
out.Capabilities[i] = v1.Capability(in.Capabilities[i])
}
} else {
out.Capabilities = nil
}
if in.Volumes != nil {
out.Volumes = make([]FSType, len(in.Volumes))
for i := range in.Volumes {
out.Volumes[i] = FSType(in.Volumes[i])
}
} else {
out.Volumes = nil
}
out.HostNetwork = in.HostNetwork
if in.HostPorts != nil {
out.HostPorts = make([]HostPortRange, len(in.HostPorts))
for i := range in.HostPorts {
if err := Convert_extensions_HostPortRange_To_v1beta1_HostPortRange(&in.HostPorts[i], &out.HostPorts[i], s); err != nil {
return err
}
}
} else {
out.HostPorts = nil
}
out.HostPID = in.HostPID
out.HostIPC = in.HostIPC
if err := Convert_extensions_SELinuxContextStrategyOptions_To_v1beta1_SELinuxContextStrategyOptions(&in.SELinuxContext, &out.SELinuxContext, s); err != nil {
return err
}
if err := Convert_extensions_RunAsUserStrategyOptions_To_v1beta1_RunAsUserStrategyOptions(&in.RunAsUser, &out.RunAsUser, s); err != nil {
return err
}
return nil
}
func Convert_extensions_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec(in *extensions.PodSecurityPolicySpec, out *PodSecurityPolicySpec, s conversion.Scope) error {
return autoConvert_extensions_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec(in, out, s)
}
func autoConvert_extensions_ReplicaSet_To_v1beta1_ReplicaSet(in *extensions.ReplicaSet, out *ReplicaSet, s conversion.Scope) error {
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
defaulting.(func(*extensions.ReplicaSet))(in)
@ -3434,6 +3554,49 @@ func autoConvert_extensions_RollingUpdateDeployment_To_v1beta1_RollingUpdateDepl
return nil
}
func autoConvert_extensions_RunAsUserStrategyOptions_To_v1beta1_RunAsUserStrategyOptions(in *extensions.RunAsUserStrategyOptions, out *RunAsUserStrategyOptions, s conversion.Scope) error {
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
defaulting.(func(*extensions.RunAsUserStrategyOptions))(in)
}
out.Type = RunAsUserStrategy(in.Type)
if in.Ranges != nil {
out.Ranges = make([]IDRange, len(in.Ranges))
for i := range in.Ranges {
if err := Convert_extensions_IDRange_To_v1beta1_IDRange(&in.Ranges[i], &out.Ranges[i], s); err != nil {
return err
}
}
} else {
out.Ranges = nil
}
return nil
}
func Convert_extensions_RunAsUserStrategyOptions_To_v1beta1_RunAsUserStrategyOptions(in *extensions.RunAsUserStrategyOptions, out *RunAsUserStrategyOptions, s conversion.Scope) error {
return autoConvert_extensions_RunAsUserStrategyOptions_To_v1beta1_RunAsUserStrategyOptions(in, out, s)
}
func autoConvert_extensions_SELinuxContextStrategyOptions_To_v1beta1_SELinuxContextStrategyOptions(in *extensions.SELinuxContextStrategyOptions, out *SELinuxContextStrategyOptions, s conversion.Scope) error {
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
defaulting.(func(*extensions.SELinuxContextStrategyOptions))(in)
}
out.Type = SELinuxContextStrategy(in.Type)
// unable to generate simple pointer conversion for api.SELinuxOptions -> v1.SELinuxOptions
if in.SELinuxOptions != nil {
out.SELinuxOptions = new(v1.SELinuxOptions)
if err := Convert_api_SELinuxOptions_To_v1_SELinuxOptions(in.SELinuxOptions, out.SELinuxOptions, s); err != nil {
return err
}
} else {
out.SELinuxOptions = nil
}
return nil
}
func Convert_extensions_SELinuxContextStrategyOptions_To_v1beta1_SELinuxContextStrategyOptions(in *extensions.SELinuxContextStrategyOptions, out *SELinuxContextStrategyOptions, s conversion.Scope) error {
return autoConvert_extensions_SELinuxContextStrategyOptions_To_v1beta1_SELinuxContextStrategyOptions(in, out, s)
}
func autoConvert_extensions_Scale_To_v1beta1_Scale(in *extensions.Scale, out *Scale, s conversion.Scope) error {
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
defaulting.(func(*extensions.Scale))(in)
@ -4090,6 +4253,32 @@ func Convert_v1beta1_HorizontalPodAutoscalerStatus_To_extensions_HorizontalPodAu
return autoConvert_v1beta1_HorizontalPodAutoscalerStatus_To_extensions_HorizontalPodAutoscalerStatus(in, out, s)
}
func autoConvert_v1beta1_HostPortRange_To_extensions_HostPortRange(in *HostPortRange, out *extensions.HostPortRange, s conversion.Scope) error {
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
defaulting.(func(*HostPortRange))(in)
}
out.Min = int(in.Min)
out.Max = int(in.Max)
return nil
}
func Convert_v1beta1_HostPortRange_To_extensions_HostPortRange(in *HostPortRange, out *extensions.HostPortRange, s conversion.Scope) error {
return autoConvert_v1beta1_HostPortRange_To_extensions_HostPortRange(in, out, s)
}
func autoConvert_v1beta1_IDRange_To_extensions_IDRange(in *IDRange, out *extensions.IDRange, s conversion.Scope) error {
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
defaulting.(func(*IDRange))(in)
}
out.Min = in.Min
out.Max = in.Max
return nil
}
func Convert_v1beta1_IDRange_To_extensions_IDRange(in *IDRange, out *extensions.IDRange, s conversion.Scope) error {
return autoConvert_v1beta1_IDRange_To_extensions_IDRange(in, out, s)
}
func autoConvert_v1beta1_Ingress_To_extensions_Ingress(in *Ingress, out *extensions.Ingress, s conversion.Scope) error {
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
defaulting.(func(*Ingress))(in)
@ -4479,6 +4668,100 @@ func Convert_v1beta1_NodeUtilization_To_extensions_NodeUtilization(in *NodeUtili
return autoConvert_v1beta1_NodeUtilization_To_extensions_NodeUtilization(in, out, s)
}
func autoConvert_v1beta1_PodSecurityPolicy_To_extensions_PodSecurityPolicy(in *PodSecurityPolicy, out *extensions.PodSecurityPolicy, s conversion.Scope) error {
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
defaulting.(func(*PodSecurityPolicy))(in)
}
if err := api.Convert_unversioned_TypeMeta_To_unversioned_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {
return err
}
if err := Convert_v1_ObjectMeta_To_api_ObjectMeta(&in.ObjectMeta, &out.ObjectMeta, s); err != nil {
return err
}
if err := Convert_v1beta1_PodSecurityPolicySpec_To_extensions_PodSecurityPolicySpec(&in.Spec, &out.Spec, s); err != nil {
return err
}
return nil
}
func Convert_v1beta1_PodSecurityPolicy_To_extensions_PodSecurityPolicy(in *PodSecurityPolicy, out *extensions.PodSecurityPolicy, s conversion.Scope) error {
return autoConvert_v1beta1_PodSecurityPolicy_To_extensions_PodSecurityPolicy(in, out, s)
}
func autoConvert_v1beta1_PodSecurityPolicyList_To_extensions_PodSecurityPolicyList(in *PodSecurityPolicyList, out *extensions.PodSecurityPolicyList, s conversion.Scope) error {
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
defaulting.(func(*PodSecurityPolicyList))(in)
}
if err := api.Convert_unversioned_TypeMeta_To_unversioned_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {
return err
}
if err := api.Convert_unversioned_ListMeta_To_unversioned_ListMeta(&in.ListMeta, &out.ListMeta, s); err != nil {
return err
}
if in.Items != nil {
out.Items = make([]extensions.PodSecurityPolicy, len(in.Items))
for i := range in.Items {
if err := Convert_v1beta1_PodSecurityPolicy_To_extensions_PodSecurityPolicy(&in.Items[i], &out.Items[i], s); err != nil {
return err
}
}
} else {
out.Items = nil
}
return nil
}
func Convert_v1beta1_PodSecurityPolicyList_To_extensions_PodSecurityPolicyList(in *PodSecurityPolicyList, out *extensions.PodSecurityPolicyList, s conversion.Scope) error {
return autoConvert_v1beta1_PodSecurityPolicyList_To_extensions_PodSecurityPolicyList(in, out, s)
}
func autoConvert_v1beta1_PodSecurityPolicySpec_To_extensions_PodSecurityPolicySpec(in *PodSecurityPolicySpec, out *extensions.PodSecurityPolicySpec, s conversion.Scope) error {
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
defaulting.(func(*PodSecurityPolicySpec))(in)
}
out.Privileged = in.Privileged
if in.Capabilities != nil {
out.Capabilities = make([]api.Capability, len(in.Capabilities))
for i := range in.Capabilities {
out.Capabilities[i] = api.Capability(in.Capabilities[i])
}
} else {
out.Capabilities = nil
}
if in.Volumes != nil {
out.Volumes = make([]extensions.FSType, len(in.Volumes))
for i := range in.Volumes {
out.Volumes[i] = extensions.FSType(in.Volumes[i])
}
} else {
out.Volumes = nil
}
out.HostNetwork = in.HostNetwork
if in.HostPorts != nil {
out.HostPorts = make([]extensions.HostPortRange, len(in.HostPorts))
for i := range in.HostPorts {
if err := Convert_v1beta1_HostPortRange_To_extensions_HostPortRange(&in.HostPorts[i], &out.HostPorts[i], s); err != nil {
return err
}
}
} else {
out.HostPorts = nil
}
out.HostPID = in.HostPID
out.HostIPC = in.HostIPC
if err := Convert_v1beta1_SELinuxContextStrategyOptions_To_extensions_SELinuxContextStrategyOptions(&in.SELinuxContext, &out.SELinuxContext, s); err != nil {
return err
}
if err := Convert_v1beta1_RunAsUserStrategyOptions_To_extensions_RunAsUserStrategyOptions(&in.RunAsUser, &out.RunAsUser, s); err != nil {
return err
}
return nil
}
func Convert_v1beta1_PodSecurityPolicySpec_To_extensions_PodSecurityPolicySpec(in *PodSecurityPolicySpec, out *extensions.PodSecurityPolicySpec, s conversion.Scope) error {
return autoConvert_v1beta1_PodSecurityPolicySpec_To_extensions_PodSecurityPolicySpec(in, out, s)
}
func autoConvert_v1beta1_ReplicaSet_To_extensions_ReplicaSet(in *ReplicaSet, out *extensions.ReplicaSet, s conversion.Scope) error {
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
defaulting.(func(*ReplicaSet))(in)
@ -4612,6 +4895,49 @@ func autoConvert_v1beta1_RollingUpdateDeployment_To_extensions_RollingUpdateDepl
return nil
}
func autoConvert_v1beta1_RunAsUserStrategyOptions_To_extensions_RunAsUserStrategyOptions(in *RunAsUserStrategyOptions, out *extensions.RunAsUserStrategyOptions, s conversion.Scope) error {
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
defaulting.(func(*RunAsUserStrategyOptions))(in)
}
out.Type = extensions.RunAsUserStrategy(in.Type)
if in.Ranges != nil {
out.Ranges = make([]extensions.IDRange, len(in.Ranges))
for i := range in.Ranges {
if err := Convert_v1beta1_IDRange_To_extensions_IDRange(&in.Ranges[i], &out.Ranges[i], s); err != nil {
return err
}
}
} else {
out.Ranges = nil
}
return nil
}
func Convert_v1beta1_RunAsUserStrategyOptions_To_extensions_RunAsUserStrategyOptions(in *RunAsUserStrategyOptions, out *extensions.RunAsUserStrategyOptions, s conversion.Scope) error {
return autoConvert_v1beta1_RunAsUserStrategyOptions_To_extensions_RunAsUserStrategyOptions(in, out, s)
}
func autoConvert_v1beta1_SELinuxContextStrategyOptions_To_extensions_SELinuxContextStrategyOptions(in *SELinuxContextStrategyOptions, out *extensions.SELinuxContextStrategyOptions, s conversion.Scope) error {
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
defaulting.(func(*SELinuxContextStrategyOptions))(in)
}
out.Type = extensions.SELinuxContextStrategy(in.Type)
// unable to generate simple pointer conversion for v1.SELinuxOptions -> api.SELinuxOptions
if in.SELinuxOptions != nil {
out.SELinuxOptions = new(api.SELinuxOptions)
if err := Convert_v1_SELinuxOptions_To_api_SELinuxOptions(in.SELinuxOptions, out.SELinuxOptions, s); err != nil {
return err
}
} else {
out.SELinuxOptions = nil
}
return nil
}
func Convert_v1beta1_SELinuxContextStrategyOptions_To_extensions_SELinuxContextStrategyOptions(in *SELinuxContextStrategyOptions, out *extensions.SELinuxContextStrategyOptions, s conversion.Scope) error {
return autoConvert_v1beta1_SELinuxContextStrategyOptions_To_extensions_SELinuxContextStrategyOptions(in, out, s)
}
func autoConvert_v1beta1_Scale_To_extensions_Scale(in *Scale, out *extensions.Scale, s conversion.Scope) error {
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
defaulting.(func(*Scale))(in)
@ -4853,6 +5179,8 @@ func init() {
autoConvert_extensions_HorizontalPodAutoscalerSpec_To_v1beta1_HorizontalPodAutoscalerSpec,
autoConvert_extensions_HorizontalPodAutoscalerStatus_To_v1beta1_HorizontalPodAutoscalerStatus,
autoConvert_extensions_HorizontalPodAutoscaler_To_v1beta1_HorizontalPodAutoscaler,
autoConvert_extensions_HostPortRange_To_v1beta1_HostPortRange,
autoConvert_extensions_IDRange_To_v1beta1_IDRange,
autoConvert_extensions_IngressBackend_To_v1beta1_IngressBackend,
autoConvert_extensions_IngressList_To_v1beta1_IngressList,
autoConvert_extensions_IngressRuleValue_To_v1beta1_IngressRuleValue,
@ -4866,6 +5194,9 @@ func init() {
autoConvert_extensions_JobStatus_To_v1beta1_JobStatus,
autoConvert_extensions_Job_To_v1beta1_Job,
autoConvert_extensions_NodeUtilization_To_v1beta1_NodeUtilization,
autoConvert_extensions_PodSecurityPolicyList_To_v1beta1_PodSecurityPolicyList,
autoConvert_extensions_PodSecurityPolicySpec_To_v1beta1_PodSecurityPolicySpec,
autoConvert_extensions_PodSecurityPolicy_To_v1beta1_PodSecurityPolicy,
autoConvert_extensions_ReplicaSetList_To_v1beta1_ReplicaSetList,
autoConvert_extensions_ReplicaSetSpec_To_v1beta1_ReplicaSetSpec,
autoConvert_extensions_ReplicaSetStatus_To_v1beta1_ReplicaSetStatus,
@ -4874,6 +5205,8 @@ func init() {
autoConvert_extensions_RollbackConfig_To_v1beta1_RollbackConfig,
autoConvert_extensions_RollingUpdateDaemonSet_To_v1beta1_RollingUpdateDaemonSet,
autoConvert_extensions_RollingUpdateDeployment_To_v1beta1_RollingUpdateDeployment,
autoConvert_extensions_RunAsUserStrategyOptions_To_v1beta1_RunAsUserStrategyOptions,
autoConvert_extensions_SELinuxContextStrategyOptions_To_v1beta1_SELinuxContextStrategyOptions,
autoConvert_extensions_ScaleSpec_To_v1beta1_ScaleSpec,
autoConvert_extensions_ScaleStatus_To_v1beta1_ScaleStatus,
autoConvert_extensions_Scale_To_v1beta1_Scale,
@ -4949,6 +5282,8 @@ func init() {
autoConvert_v1beta1_HorizontalPodAutoscalerSpec_To_extensions_HorizontalPodAutoscalerSpec,
autoConvert_v1beta1_HorizontalPodAutoscalerStatus_To_extensions_HorizontalPodAutoscalerStatus,
autoConvert_v1beta1_HorizontalPodAutoscaler_To_extensions_HorizontalPodAutoscaler,
autoConvert_v1beta1_HostPortRange_To_extensions_HostPortRange,
autoConvert_v1beta1_IDRange_To_extensions_IDRange,
autoConvert_v1beta1_IngressBackend_To_extensions_IngressBackend,
autoConvert_v1beta1_IngressList_To_extensions_IngressList,
autoConvert_v1beta1_IngressRuleValue_To_extensions_IngressRuleValue,
@ -4965,6 +5300,9 @@ func init() {
autoConvert_v1beta1_LabelSelector_To_unversioned_LabelSelector,
autoConvert_v1beta1_ListOptions_To_api_ListOptions,
autoConvert_v1beta1_NodeUtilization_To_extensions_NodeUtilization,
autoConvert_v1beta1_PodSecurityPolicyList_To_extensions_PodSecurityPolicyList,
autoConvert_v1beta1_PodSecurityPolicySpec_To_extensions_PodSecurityPolicySpec,
autoConvert_v1beta1_PodSecurityPolicy_To_extensions_PodSecurityPolicy,
autoConvert_v1beta1_ReplicaSetList_To_extensions_ReplicaSetList,
autoConvert_v1beta1_ReplicaSetSpec_To_extensions_ReplicaSetSpec,
autoConvert_v1beta1_ReplicaSetStatus_To_extensions_ReplicaSetStatus,
@ -4973,6 +5311,8 @@ func init() {
autoConvert_v1beta1_RollbackConfig_To_extensions_RollbackConfig,
autoConvert_v1beta1_RollingUpdateDaemonSet_To_extensions_RollingUpdateDaemonSet,
autoConvert_v1beta1_RollingUpdateDeployment_To_extensions_RollingUpdateDeployment,
autoConvert_v1beta1_RunAsUserStrategyOptions_To_extensions_RunAsUserStrategyOptions,
autoConvert_v1beta1_SELinuxContextStrategyOptions_To_extensions_SELinuxContextStrategyOptions,
autoConvert_v1beta1_ScaleSpec_To_extensions_ScaleSpec,
autoConvert_v1beta1_ScaleStatus_To_extensions_ScaleStatus,
autoConvert_v1beta1_Scale_To_extensions_Scale,

View File

@ -1319,6 +1319,18 @@ func deepCopy_v1beta1_HorizontalPodAutoscalerStatus(in HorizontalPodAutoscalerSt
return nil
}
func deepCopy_v1beta1_HostPortRange(in HostPortRange, out *HostPortRange, c *conversion.Cloner) error {
out.Min = in.Min
out.Max = in.Max
return nil
}
func deepCopy_v1beta1_IDRange(in IDRange, out *IDRange, c *conversion.Cloner) error {
out.Min = in.Min
out.Max = in.Max
return nil
}
func deepCopy_v1beta1_Ingress(in Ingress, out *Ingress, c *conversion.Cloner) error {
if err := deepCopy_unversioned_TypeMeta(in.TypeMeta, &out.TypeMeta, c); err != nil {
return err
@ -1587,6 +1599,79 @@ func deepCopy_v1beta1_NodeUtilization(in NodeUtilization, out *NodeUtilization,
return nil
}
func deepCopy_v1beta1_PodSecurityPolicy(in PodSecurityPolicy, out *PodSecurityPolicy, c *conversion.Cloner) error {
if err := deepCopy_unversioned_TypeMeta(in.TypeMeta, &out.TypeMeta, c); err != nil {
return err
}
if err := deepCopy_v1_ObjectMeta(in.ObjectMeta, &out.ObjectMeta, c); err != nil {
return err
}
if err := deepCopy_v1beta1_PodSecurityPolicySpec(in.Spec, &out.Spec, c); err != nil {
return err
}
return nil
}
func deepCopy_v1beta1_PodSecurityPolicyList(in PodSecurityPolicyList, out *PodSecurityPolicyList, c *conversion.Cloner) error {
if err := deepCopy_unversioned_TypeMeta(in.TypeMeta, &out.TypeMeta, c); err != nil {
return err
}
if err := deepCopy_unversioned_ListMeta(in.ListMeta, &out.ListMeta, c); err != nil {
return err
}
if in.Items != nil {
out.Items = make([]PodSecurityPolicy, len(in.Items))
for i := range in.Items {
if err := deepCopy_v1beta1_PodSecurityPolicy(in.Items[i], &out.Items[i], c); err != nil {
return err
}
}
} else {
out.Items = nil
}
return nil
}
func deepCopy_v1beta1_PodSecurityPolicySpec(in PodSecurityPolicySpec, out *PodSecurityPolicySpec, c *conversion.Cloner) error {
out.Privileged = in.Privileged
if in.Capabilities != nil {
out.Capabilities = make([]v1.Capability, len(in.Capabilities))
for i := range in.Capabilities {
out.Capabilities[i] = in.Capabilities[i]
}
} else {
out.Capabilities = nil
}
if in.Volumes != nil {
out.Volumes = make([]FSType, len(in.Volumes))
for i := range in.Volumes {
out.Volumes[i] = in.Volumes[i]
}
} else {
out.Volumes = nil
}
out.HostNetwork = in.HostNetwork
if in.HostPorts != nil {
out.HostPorts = make([]HostPortRange, len(in.HostPorts))
for i := range in.HostPorts {
if err := deepCopy_v1beta1_HostPortRange(in.HostPorts[i], &out.HostPorts[i], c); err != nil {
return err
}
}
} else {
out.HostPorts = nil
}
out.HostPID = in.HostPID
out.HostIPC = in.HostIPC
if err := deepCopy_v1beta1_SELinuxContextStrategyOptions(in.SELinuxContext, &out.SELinuxContext, c); err != nil {
return err
}
if err := deepCopy_v1beta1_RunAsUserStrategyOptions(in.RunAsUser, &out.RunAsUser, c); err != nil {
return err
}
return nil
}
func deepCopy_v1beta1_ReplicaSet(in ReplicaSet, out *ReplicaSet, c *conversion.Cloner) error {
if err := deepCopy_unversioned_TypeMeta(in.TypeMeta, &out.TypeMeta, c); err != nil {
return err
@ -1700,6 +1785,34 @@ func deepCopy_v1beta1_RollingUpdateDeployment(in RollingUpdateDeployment, out *R
return nil
}
func deepCopy_v1beta1_RunAsUserStrategyOptions(in RunAsUserStrategyOptions, out *RunAsUserStrategyOptions, c *conversion.Cloner) error {
out.Type = in.Type
if in.Ranges != nil {
out.Ranges = make([]IDRange, len(in.Ranges))
for i := range in.Ranges {
if err := deepCopy_v1beta1_IDRange(in.Ranges[i], &out.Ranges[i], c); err != nil {
return err
}
}
} else {
out.Ranges = nil
}
return nil
}
func deepCopy_v1beta1_SELinuxContextStrategyOptions(in SELinuxContextStrategyOptions, out *SELinuxContextStrategyOptions, c *conversion.Cloner) error {
out.Type = in.Type
if in.SELinuxOptions != nil {
out.SELinuxOptions = new(v1.SELinuxOptions)
if err := deepCopy_v1_SELinuxOptions(*in.SELinuxOptions, out.SELinuxOptions, c); err != nil {
return err
}
} else {
out.SELinuxOptions = nil
}
return nil
}
func deepCopy_v1beta1_Scale(in Scale, out *Scale, c *conversion.Cloner) error {
if err := deepCopy_unversioned_TypeMeta(in.TypeMeta, &out.TypeMeta, c); err != nil {
return err
@ -1901,6 +2014,8 @@ func init() {
deepCopy_v1beta1_HorizontalPodAutoscalerList,
deepCopy_v1beta1_HorizontalPodAutoscalerSpec,
deepCopy_v1beta1_HorizontalPodAutoscalerStatus,
deepCopy_v1beta1_HostPortRange,
deepCopy_v1beta1_IDRange,
deepCopy_v1beta1_Ingress,
deepCopy_v1beta1_IngressBackend,
deepCopy_v1beta1_IngressList,
@ -1917,6 +2032,9 @@ func init() {
deepCopy_v1beta1_LabelSelectorRequirement,
deepCopy_v1beta1_ListOptions,
deepCopy_v1beta1_NodeUtilization,
deepCopy_v1beta1_PodSecurityPolicy,
deepCopy_v1beta1_PodSecurityPolicyList,
deepCopy_v1beta1_PodSecurityPolicySpec,
deepCopy_v1beta1_ReplicaSet,
deepCopy_v1beta1_ReplicaSetList,
deepCopy_v1beta1_ReplicaSetSpec,
@ -1925,6 +2043,8 @@ func init() {
deepCopy_v1beta1_RollbackConfig,
deepCopy_v1beta1_RollingUpdateDaemonSet,
deepCopy_v1beta1_RollingUpdateDeployment,
deepCopy_v1beta1_RunAsUserStrategyOptions,
deepCopy_v1beta1_SELinuxContextStrategyOptions,
deepCopy_v1beta1_Scale,
deepCopy_v1beta1_ScaleSpec,
deepCopy_v1beta1_ScaleStatus,

View File

@ -60,6 +60,8 @@ func addKnownTypes(scheme *runtime.Scheme) {
&v1.DeleteOptions{},
&ReplicaSet{},
&ReplicaSetList{},
&PodSecurityPolicy{},
&PodSecurityPolicyList{},
)
}
@ -85,3 +87,5 @@ func (obj *IngressList) GetObjectKind() unversioned.ObjectKind {
func (obj *ListOptions) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ReplicaSet) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *ReplicaSetList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PodSecurityPolicy) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *PodSecurityPolicyList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }

File diff suppressed because it is too large Load Diff

View File

@ -917,3 +917,128 @@ type ReplicaSetStatus struct {
// ObservedGeneration reflects the generation of the most recently observed ReplicaSet.
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
}
// Pod Security Policy governs the ability to make requests that affect the Security Context
// that will be applied to a pod and container.
type PodSecurityPolicy struct {
unversioned.TypeMeta `json:",inline"`
// Standard object's metadata.
// More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata
v1.ObjectMeta `json:"metadata,omitempty"`
// Spec defines the policy enforced.
Spec PodSecurityPolicySpec `json:"spec,omitempty"`
}
// Pod Security Policy Spec defines the policy enforced.
type PodSecurityPolicySpec struct {
// privileged determines if a pod can request to be run as privileged.
Privileged bool `json:"privileged,omitempty"`
// capabilities is a list of capabilities that can be added.
Capabilities []v1.Capability `json:"capabilities,omitempty"`
// volumes is a white list of allowed volume plugins. Empty indicates that all plugins
// may be used.
Volumes []FSType `json:"volumes,omitempty"`
// hostNetwork determines if the policy allows the use of HostNetwork in the pod spec.
HostNetwork bool `json:"hostNetwork,omitempty"`
// hostPorts determines which host port ranges are allowed to be exposed.
HostPorts []HostPortRange `json:"hostPorts,omitempty"`
// hostPID determines if the policy allows the use of HostPID in the pod spec.
HostPID bool `json:"hostPID,omitempty"`
// hostIPC determines if the policy allows the use of HostIPC in the pod spec.
HostIPC bool `json:"hostIPC,omitempty"`
// seLinuxContext is the strategy that will dictate the allowable labels that may be set.
SELinuxContext SELinuxContextStrategyOptions `json:"seLinuxContext,omitempty"`
// runAsUser is the strategy that will dictate the allowable RunAsUser values that may be set.
RunAsUser RunAsUserStrategyOptions `json:"runAsUser,omitempty"`
}
// FS Type gives strong typing to different file systems that are used by volumes.
type FSType string
var (
HostPath FSType = "hostPath"
EmptyDir FSType = "emptyDir"
GCEPersistentDisk FSType = "gcePersistentDisk"
AWSElasticBlockStore FSType = "awsElasticBlockStore"
GitRepo FSType = "gitRepo"
Secret FSType = "secret"
NFS FSType = "nfs"
ISCSI FSType = "iscsi"
Glusterfs FSType = "glusterfs"
PersistentVolumeClaim FSType = "persistentVolumeClaim"
RBD FSType = "rbd"
Cinder FSType = "cinder"
CephFS FSType = "cephFS"
DownwardAPI FSType = "downwardAPI"
FC FSType = "fc"
)
// Host Port Range defines a range of host ports that will be enabled by a policy
// for pods to use. It requires both the start and end to be defined.
type HostPortRange struct {
// min is the start of the range, inclusive.
Min int32 `json:"min"`
// max is the end of the range, inclusive.
Max int32 `json:"max"`
}
// SELinux Context Strategy Options defines the strategy type and any options used to create the strategy.
type SELinuxContextStrategyOptions struct {
// type is the strategy that will dictate the allowable labels that may be set.
Type SELinuxContextStrategy `json:"type"`
// seLinuxOptions required to run as; required for MustRunAs
// More info: http://releases.k8s.io/HEAD/docs/design/security_context.md#security-context
SELinuxOptions *v1.SELinuxOptions `json:"seLinuxOptions,omitempty"`
}
// SELinux Context Strategy Type denotes strategy types for generating SELinux options for a
// Security Context.
type SELinuxContextStrategy string
const (
// container must have SELinux labels of X applied.
SELinuxStrategyMustRunAs SELinuxContextStrategy = "MustRunAs"
// container may make requests for any SELinux context labels.
SELinuxStrategyRunAsAny SELinuxContextStrategy = "RunAsAny"
)
// Run A sUser Strategy Options defines the strategy type and any options used to create the strategy.
type RunAsUserStrategyOptions struct {
// type is the strategy that will dictate the allowable RunAsUser values that may be set.
Type RunAsUserStrategy `json:"type"`
// Ranges are the allowed ranges of uids that may be used.
Ranges []IDRange `json:"ranges,omitempty"`
}
// ID Range provides a min/max of an allowed range of IDs.
type IDRange struct {
// Min is the start of the range, inclusive.
Min int64 `json:"min"`
// Max is the end of the range, inclusive.
Max int64 `json:"max"`
}
// Run As User Strategy Type denotes strategy types for generating RunAsUser values for a
// Security Context.
type RunAsUserStrategy string
const (
// container must run as a particular uid.
RunAsUserStrategyMustRunAs RunAsUserStrategy = "MustRunAs"
// container must run as a non-root uid
RunAsUserStrategyMustRunAsNonRoot RunAsUserStrategy = "MustRunAsNonRoot"
// container may make requests for any uid.
RunAsUserStrategyRunAsAny RunAsUserStrategy = "RunAsAny"
)
// Pod Security Policy List is a list of PodSecurityPolicy objects.
type PodSecurityPolicyList struct {
unversioned.TypeMeta `json:",inline"`
// Standard list metadata.
// More info: http://docs.k8s.io/api-conventions.md#metadata
unversioned.ListMeta `json:"metadata,omitempty"`
// Items is a list of schema objects.
Items []PodSecurityPolicy `json:"items"`
}

View File

@ -292,6 +292,26 @@ func (HorizontalPodAutoscalerStatus) SwaggerDoc() map[string]string {
return map_HorizontalPodAutoscalerStatus
}
var map_HostPortRange = map[string]string{
"": "Host Port Range defines a range of host ports that will be enabled by a policy for pods to use. It requires both the start and end to be defined.",
"min": "min is the start of the range, inclusive.",
"max": "max is the end of the range, inclusive.",
}
func (HostPortRange) SwaggerDoc() map[string]string {
return map_HostPortRange
}
var map_IDRange = map[string]string{
"": "ID Range provides a min/max of an allowed range of IDs.",
"min": "Min is the start of the range, inclusive.",
"max": "Max is the end of the range, inclusive.",
}
func (IDRange) SwaggerDoc() map[string]string {
return map_IDRange
}
var map_Ingress = map[string]string{
"": "Ingress is a collection of rules that allow inbound connections to reach the endpoints defined by a backend. An Ingress can be configured to give services externally-reachable urls, load balance traffic, terminate SSL, offer name based virtual hosting etc.",
"metadata": "Standard object's metadata. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata",
@ -464,6 +484,43 @@ func (NodeUtilization) SwaggerDoc() map[string]string {
return map_NodeUtilization
}
var map_PodSecurityPolicy = map[string]string{
"": "Pod Security Policy governs the ability to make requests that affect the Security Context that will be applied to a pod and container.",
"metadata": "Standard object's metadata. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata",
"spec": "Spec defines the policy enforced.",
}
func (PodSecurityPolicy) SwaggerDoc() map[string]string {
return map_PodSecurityPolicy
}
var map_PodSecurityPolicyList = map[string]string{
"": "Pod Security Policy List is a list of PodSecurityPolicy objects.",
"metadata": "Standard list metadata. More info: http://docs.k8s.io/api-conventions.md#metadata",
"items": "Items is a list of schema objects.",
}
func (PodSecurityPolicyList) SwaggerDoc() map[string]string {
return map_PodSecurityPolicyList
}
var map_PodSecurityPolicySpec = map[string]string{
"": "Pod Security Policy Spec defines the policy enforced.",
"privileged": "privileged determines if a pod can request to be run as privileged.",
"capabilities": "capabilities is a list of capabilities that can be added.",
"volumes": "volumes is a white list of allowed volume plugins. Empty indicates that all plugins may be used.",
"hostNetwork": "hostNetwork determines if the policy allows the use of HostNetwork in the pod spec.",
"hostPorts": "hostPorts determines which host port ranges are allowed to be exposed.",
"hostPID": "hostPID determines if the policy allows the use of HostPID in the pod spec.",
"hostIPC": "hostIPC determines if the policy allows the use of HostIPC in the pod spec.",
"seLinuxContext": "seLinuxContext is the strategy that will dictate the allowable labels that may be set.",
"runAsUser": "runAsUser is the strategy that will dictate the allowable RunAsUser values that may be set.",
}
func (PodSecurityPolicySpec) SwaggerDoc() map[string]string {
return map_PodSecurityPolicySpec
}
var map_ReplicaSet = map[string]string{
"": "ReplicaSet represents the configuration of a ReplicaSet.",
"metadata": "If the Labels of a ReplicaSet are empty, they are defaulted to be the same as the Pod(s) that the ReplicaSet manages. Standard object's metadata. More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata",
@ -542,6 +599,26 @@ func (RollingUpdateDeployment) SwaggerDoc() map[string]string {
return map_RollingUpdateDeployment
}
var map_RunAsUserStrategyOptions = map[string]string{
"": "Run A sUser Strategy Options defines the strategy type and any options used to create the strategy.",
"type": "type is the strategy that will dictate the allowable RunAsUser values that may be set.",
"ranges": "Ranges are the allowed ranges of uids that may be used.",
}
func (RunAsUserStrategyOptions) SwaggerDoc() map[string]string {
return map_RunAsUserStrategyOptions
}
var map_SELinuxContextStrategyOptions = map[string]string{
"": "SELinux Context Strategy Options defines the strategy type and any options used to create the strategy.",
"type": "type is the strategy that will dictate the allowable labels that may be set.",
"seLinuxOptions": "seLinuxOptions required to run as; required for MustRunAs More info: http://releases.k8s.io/HEAD/docs/design/security_context.md#security-context",
}
func (SELinuxContextStrategyOptions) SwaggerDoc() map[string]string {
return map_SELinuxContextStrategyOptions
}
var map_Scale = map[string]string{
"": "represents a scaling request for a resource.",
"metadata": "Standard object metadata; More info: http://releases.k8s.io/HEAD/docs/devel/api-conventions.md#metadata.",

View File

@ -697,3 +697,116 @@ func ValidatePodTemplateSpecForReplicaSet(template *api.PodTemplateSpec, selecto
}
return allErrs
}
// ValidatePodSecurityPolicyName can be used to check whether the given
// pod security policy name is valid.
// Prefix indicates this name will be used as part of generation, in which case
// trailing dashes are allowed.
func ValidatePodSecurityPolicyName(name string, prefix bool) (bool, string) {
return apivalidation.NameIsDNSSubdomain(name, prefix)
}
func ValidatePodSecurityPolicy(psp *extensions.PodSecurityPolicy) field.ErrorList {
allErrs := field.ErrorList{}
allErrs = append(allErrs, apivalidation.ValidateObjectMeta(&psp.ObjectMeta, false, ValidatePodSecurityPolicyName, field.NewPath("metadata"))...)
allErrs = append(allErrs, ValidatePodSecurityPolicySpec(&psp.Spec, field.NewPath("spec"))...)
return allErrs
}
func ValidatePodSecurityPolicySpec(spec *extensions.PodSecurityPolicySpec, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
allErrs = append(allErrs, validatePSPRunAsUser(fldPath.Child("runAsUser"), &spec.RunAsUser)...)
allErrs = append(allErrs, validatePSPSELinuxContext(fldPath.Child("seLinuxContext"), &spec.SELinuxContext)...)
allErrs = append(allErrs, validatePodSecurityPolicyVolumes(fldPath, spec.Volumes)...)
return allErrs
}
// validatePSPSELinuxContext validates the SELinuxContext fields of PodSecurityPolicy.
func validatePSPSELinuxContext(fldPath *field.Path, seLinuxContext *extensions.SELinuxContextStrategyOptions) field.ErrorList {
allErrs := field.ErrorList{}
// ensure the selinux strategy has a valid type
supportedSELinuxContextTypes := sets.NewString(string(extensions.SELinuxStrategyMustRunAs),
string(extensions.SELinuxStrategyRunAsAny))
if !supportedSELinuxContextTypes.Has(string(seLinuxContext.Type)) {
allErrs = append(allErrs, field.NotSupported(fldPath.Child("type"), seLinuxContext.Type, supportedSELinuxContextTypes.List()))
}
return allErrs
}
// validatePSPRunAsUser validates the RunAsUser fields of PodSecurityPolicy.
func validatePSPRunAsUser(fldPath *field.Path, runAsUser *extensions.RunAsUserStrategyOptions) field.ErrorList {
allErrs := field.ErrorList{}
// ensure the user strategy has a valid type
supportedRunAsUserTypes := sets.NewString(string(extensions.RunAsUserStrategyMustRunAs),
string(extensions.RunAsUserStrategyMustRunAsNonRoot),
string(extensions.RunAsUserStrategyRunAsAny))
if !supportedRunAsUserTypes.Has(string(runAsUser.Type)) {
allErrs = append(allErrs, field.NotSupported(fldPath.Child("type"), runAsUser.Type, supportedRunAsUserTypes.List()))
}
// validate range settings
for idx, rng := range runAsUser.Ranges {
allErrs = append(allErrs, validateIDRanges(fldPath.Child("ranges").Index(idx), rng)...)
}
return allErrs
}
// validatePodSecurityPolicyVolumes validates the volume fields of PodSecurityPolicy.
func validatePodSecurityPolicyVolumes(fldPath *field.Path, volumes []extensions.FSType) field.ErrorList {
allErrs := field.ErrorList{}
allowed := sets.NewString(string(extensions.HostPath),
string(extensions.EmptyDir),
string(extensions.GCEPersistentDisk),
string(extensions.AWSElasticBlockStore),
string(extensions.GitRepo),
string(extensions.Secret),
string(extensions.NFS),
string(extensions.ISCSI),
string(extensions.Glusterfs),
string(extensions.PersistentVolumeClaim),
string(extensions.RBD),
string(extensions.Cinder),
string(extensions.CephFS),
string(extensions.DownwardAPI),
string(extensions.FC))
for _, v := range volumes {
if !allowed.Has(string(v)) {
allErrs = append(allErrs, field.NotSupported(fldPath.Child("volumes"), v, allowed.List()))
}
}
return allErrs
}
// validateIDRanges ensures the range is valid.
func validateIDRanges(fldPath *field.Path, rng extensions.IDRange) field.ErrorList {
allErrs := field.ErrorList{}
// if 0 <= Min <= Max then we do not need to validate max. It is always greater than or
// equal to 0 and Min.
if rng.Min < 0 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("min"), rng.Min, "min cannot be negative"))
}
if rng.Max < 0 {
allErrs = append(allErrs, field.Invalid(fldPath.Child("max"), rng.Max, "max cannot be negative"))
}
if rng.Min > rng.Max {
allErrs = append(allErrs, field.Invalid(fldPath.Child("min"), rng.Min, "min cannot be greater than max"))
}
return allErrs
}
// ValidatePodSecurityPolicyUpdate validates a PSP for updates.
func ValidatePodSecurityPolicyUpdate(old *extensions.PodSecurityPolicy, new *extensions.PodSecurityPolicy) field.ErrorList {
allErrs := field.ErrorList{}
allErrs = append(allErrs, apivalidation.ValidateObjectMetaUpdate(&old.ObjectMeta, &new.ObjectMeta, field.NewPath("metadata"))...)
allErrs = append(allErrs, ValidatePodSecurityPolicySpec(&new.Spec, field.NewPath("spec"))...)
return allErrs
}

View File

@ -1977,3 +1977,126 @@ func newInt(val int) *int {
*p = val
return p
}
func TestValidatePodSecurityPolicy(t *testing.T) {
validSCC := func() *extensions.PodSecurityPolicy {
return &extensions.PodSecurityPolicy{
ObjectMeta: api.ObjectMeta{Name: "foo"},
Spec: extensions.PodSecurityPolicySpec{
SELinuxContext: extensions.SELinuxContextStrategyOptions{
Type: extensions.SELinuxStrategyRunAsAny,
},
RunAsUser: extensions.RunAsUserStrategyOptions{
Type: extensions.RunAsUserStrategyRunAsAny,
},
},
}
}
noUserOptions := validSCC()
noUserOptions.Spec.RunAsUser.Type = ""
noSELinuxOptions := validSCC()
noSELinuxOptions.Spec.SELinuxContext.Type = ""
invalidUserStratType := validSCC()
invalidUserStratType.Spec.RunAsUser.Type = "invalid"
invalidSELinuxStratType := validSCC()
invalidSELinuxStratType.Spec.SELinuxContext.Type = "invalid"
missingObjectMetaName := validSCC()
missingObjectMetaName.ObjectMeta.Name = ""
invalidRangeMinGreaterThanMax := validSCC()
invalidRangeMinGreaterThanMax.Spec.RunAsUser.Ranges = []extensions.IDRange{
{Min: 2, Max: 1},
}
invalidRangeNegativeMin := validSCC()
invalidRangeNegativeMin.Spec.RunAsUser.Ranges = []extensions.IDRange{
{Min: -1, Max: 10},
}
invalidRangeNegativeMax := validSCC()
invalidRangeNegativeMax.Spec.RunAsUser.Ranges = []extensions.IDRange{
{Min: 1, Max: -10},
}
errorCases := map[string]struct {
scc *extensions.PodSecurityPolicy
errorDetail string
}{
"no user options": {
scc: noUserOptions,
errorDetail: "supported values: MustRunAs, MustRunAsNonRoot, RunAsAny",
},
"no selinux options": {
scc: noSELinuxOptions,
errorDetail: "supported values: MustRunAs, RunAsAny",
},
"invalid user strategy type": {
scc: invalidUserStratType,
errorDetail: "supported values: MustRunAs, MustRunAsNonRoot, RunAsAny",
},
"invalid selinux strategy type": {
scc: invalidSELinuxStratType,
errorDetail: "supported values: MustRunAs, RunAsAny",
},
"missing object meta name": {
scc: missingObjectMetaName,
errorDetail: "name or generateName is required",
},
"invalid range min greater than max": {
scc: invalidRangeMinGreaterThanMax,
errorDetail: "min cannot be greater than max",
},
"invalid range negative min": {
scc: invalidRangeNegativeMin,
errorDetail: "min cannot be negative",
},
"invalid range negative max": {
scc: invalidRangeNegativeMax,
errorDetail: "max cannot be negative",
},
}
for k, v := range errorCases {
if errs := ValidatePodSecurityPolicy(v.scc); len(errs) == 0 || errs[0].Detail != v.errorDetail {
t.Errorf("Expected error with detail %s for %s, got %v", v.errorDetail, k, errs[0].Detail)
}
}
mustRunAs := validSCC()
mustRunAs.Spec.RunAsUser.Type = extensions.RunAsUserStrategyMustRunAs
mustRunAs.Spec.RunAsUser.Ranges = []extensions.IDRange{
{
Min: 1,
Max: 1,
},
}
mustRunAs.Spec.SELinuxContext.Type = extensions.SELinuxStrategyMustRunAs
runAsNonRoot := validSCC()
runAsNonRoot.Spec.RunAsUser.Type = extensions.RunAsUserStrategyMustRunAsNonRoot
successCases := map[string]struct {
scc *extensions.PodSecurityPolicy
}{
"must run as": {
scc: mustRunAs,
},
"run as any": {
scc: validSCC(),
},
"run as non-root (user only)": {
scc: runAsNonRoot,
},
}
for k, v := range successCases {
if errs := ValidatePodSecurityPolicy(v.scc); len(errs) != 0 {
t.Errorf("Expected success for %s, got %v", k, errs)
}
}
}

View File

@ -35,6 +35,7 @@ type ExtensionsInterface interface {
IngressNamespacer
ThirdPartyResourceNamespacer
ReplicaSetsNamespacer
PodSecurityPoliciesInterface
}
// ExtensionsClient is used to interact with experimental Kubernetes features.
@ -44,6 +45,10 @@ type ExtensionsClient struct {
*RESTClient
}
func (c *ExtensionsClient) PodSecurityPolicies() PodSecurityPolicyInterface {
return newPodSecurityPolicy(c)
}
func (c *ExtensionsClient) HorizontalPodAutoscalers(namespace string) HorizontalPodAutoscalerInterface {
return newHorizontalPodAutoscalers(c, namespace)
}

View File

@ -0,0 +1,111 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package unversioned
import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/watch"
)
type PodSecurityPoliciesInterface interface {
PodSecurityPolicies() PodSecurityPolicyInterface
}
type PodSecurityPolicyInterface interface {
Get(name string) (result *extensions.PodSecurityPolicy, err error)
Create(scc *extensions.PodSecurityPolicy) (*extensions.PodSecurityPolicy, error)
List(opts api.ListOptions) (*extensions.PodSecurityPolicyList, error)
Delete(name string) error
Update(*extensions.PodSecurityPolicy) (*extensions.PodSecurityPolicy, error)
Watch(opts api.ListOptions) (watch.Interface, error)
}
// podSecurityPolicy implements PodSecurityPolicyInterface
type podSecurityPolicy struct {
client *ExtensionsClient
}
// newPodSecurityPolicy returns a podSecurityPolicy object.
func newPodSecurityPolicy(c *ExtensionsClient) *podSecurityPolicy {
return &podSecurityPolicy{c}
}
func (s *podSecurityPolicy) Create(scc *extensions.PodSecurityPolicy) (*extensions.PodSecurityPolicy, error) {
result := &extensions.PodSecurityPolicy{}
err := s.client.Post().
Resource("podsecuritypolicies").
Body(scc).
Do().
Into(result)
return result, err
}
// List returns a list of PodSecurityPolicies matching the selectors.
func (s *podSecurityPolicy) List(opts api.ListOptions) (*extensions.PodSecurityPolicyList, error) {
result := &extensions.PodSecurityPolicyList{}
err := s.client.Get().
Resource("podsecuritypolicies").
VersionedParams(&opts, api.ParameterCodec).
Do().
Into(result)
return result, err
}
// Get returns the given PodSecurityPolicy, or an error.
func (s *podSecurityPolicy) Get(name string) (*extensions.PodSecurityPolicy, error) {
result := &extensions.PodSecurityPolicy{}
err := s.client.Get().
Resource("podsecuritypolicies").
Name(name).
Do().
Into(result)
return result, err
}
// Watch starts watching for PodSecurityPolicies matching the given selectors.
func (s *podSecurityPolicy) Watch(opts api.ListOptions) (watch.Interface, error) {
return s.client.Get().
Prefix("watch").
Resource("podsecuritypolicies").
VersionedParams(&opts, api.ParameterCodec).
Watch()
}
func (s *podSecurityPolicy) Delete(name string) error {
return s.client.Delete().
Resource("podsecuritypolicies").
Name(name).
Do().
Error()
}
func (s *podSecurityPolicy) Update(psp *extensions.PodSecurityPolicy) (result *extensions.PodSecurityPolicy, err error) {
result = &extensions.PodSecurityPolicy{}
err = s.client.Put().
Resource("podsecuritypolicies").
Name(psp.Name).
Body(psp).
Do().
Into(result)
return
}

View File

@ -0,0 +1,138 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package unversioned_test
import (
"fmt"
"net/url"
"testing"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/testapi"
"k8s.io/kubernetes/pkg/apis/extensions"
. "k8s.io/kubernetes/pkg/client/unversioned"
"k8s.io/kubernetes/pkg/client/unversioned/testclient/simple"
)
func TestPodSecurityPolicyCreate(t *testing.T) {
ns := api.NamespaceNone
scc := &extensions.PodSecurityPolicy{
ObjectMeta: api.ObjectMeta{
Name: "abc",
},
}
c := &simple.Client{
Request: simple.Request{
Method: "POST",
Path: testapi.Extensions.ResourcePath(getPSPResourcename(), ns, ""),
Query: simple.BuildQueryValues(nil),
Body: scc,
},
Response: simple.Response{StatusCode: 200, Body: scc},
}
response, err := c.Setup(t).PodSecurityPolicies().Create(scc)
c.Validate(t, response, err)
}
func TestPodSecurityPolicyGet(t *testing.T) {
ns := api.NamespaceNone
scc := &extensions.PodSecurityPolicy{
ObjectMeta: api.ObjectMeta{
Name: "abc",
},
}
c := &simple.Client{
Request: simple.Request{
Method: "GET",
Path: testapi.Extensions.ResourcePath(getPSPResourcename(), ns, "abc"),
Query: simple.BuildQueryValues(nil),
Body: nil,
},
Response: simple.Response{StatusCode: 200, Body: scc},
}
response, err := c.Setup(t).PodSecurityPolicies().Get("abc")
c.Validate(t, response, err)
}
func TestPodSecurityPolicyList(t *testing.T) {
ns := api.NamespaceNone
sccList := &extensions.PodSecurityPolicyList{
Items: []extensions.PodSecurityPolicy{
{
ObjectMeta: api.ObjectMeta{
Name: "abc",
},
},
},
}
c := &simple.Client{
Request: simple.Request{
Method: "GET",
Path: testapi.Extensions.ResourcePath(getPSPResourcename(), ns, ""),
Query: simple.BuildQueryValues(nil),
Body: nil,
},
Response: simple.Response{StatusCode: 200, Body: sccList},
}
response, err := c.Setup(t).PodSecurityPolicies().List(api.ListOptions{})
c.Validate(t, response, err)
}
func TestPodSecurityPolicyUpdate(t *testing.T) {
ns := api.NamespaceNone
scc := &extensions.PodSecurityPolicy{
ObjectMeta: api.ObjectMeta{
Name: "abc",
ResourceVersion: "1",
},
}
c := &simple.Client{
Request: simple.Request{Method: "PUT", Path: testapi.Extensions.ResourcePath(getPSPResourcename(), ns, "abc"), Query: simple.BuildQueryValues(nil)},
Response: simple.Response{StatusCode: 200, Body: scc},
}
response, err := c.Setup(t).PodSecurityPolicies().Update(scc)
c.Validate(t, response, err)
}
func TestPodSecurityPolicyDelete(t *testing.T) {
ns := api.NamespaceNone
c := &simple.Client{
Request: simple.Request{Method: "DELETE", Path: testapi.Extensions.ResourcePath(getPSPResourcename(), ns, "foo"), Query: simple.BuildQueryValues(nil)},
Response: simple.Response{StatusCode: 200},
}
err := c.Setup(t).PodSecurityPolicies().Delete("foo")
c.Validate(t, nil, err)
}
func TestPodSecurityPolicyWatch(t *testing.T) {
c := &simple.Client{
Request: simple.Request{
Method: "GET",
Path: fmt.Sprintf("%s/watch/%s", testapi.Extensions.ResourcePath("", "", ""), getPSPResourcename()),
Query: url.Values{"resourceVersion": []string{}}},
Response: simple.Response{StatusCode: 200},
}
_, err := c.Setup(t).PodSecurityPolicies().Watch(api.ListOptions{})
c.Validate(t, nil, err)
}
func getPSPResourcename() string {
return "podsecuritypolicies"
}

View File

@ -0,0 +1,73 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package testclient
import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/watch"
)
// FakePodSecurityPolicy implements PodSecurityPolicyInterface. Meant to be
// embedded into a struct to get a default implementation. This makes faking out just
// the method you want to test easier.
type FakePodSecurityPolicy struct {
Fake *Fake
Namespace string
}
func (c *FakePodSecurityPolicy) List(opts api.ListOptions) (*extensions.PodSecurityPolicyList, error) {
obj, err := c.Fake.Invokes(NewListAction("podsecuritypolicies", c.Namespace, opts), &extensions.PodSecurityPolicyList{})
if obj == nil {
return nil, err
}
return obj.(*extensions.PodSecurityPolicyList), err
}
func (c *FakePodSecurityPolicy) Get(name string) (*extensions.PodSecurityPolicy, error) {
obj, err := c.Fake.Invokes(NewGetAction("podsecuritypolicies", c.Namespace, name), &extensions.PodSecurityPolicy{})
if obj == nil {
return nil, err
}
return obj.(*extensions.PodSecurityPolicy), err
}
func (c *FakePodSecurityPolicy) Create(scc *extensions.PodSecurityPolicy) (*extensions.PodSecurityPolicy, error) {
obj, err := c.Fake.Invokes(NewCreateAction("podsecuritypolicies", c.Namespace, scc), &extensions.PodSecurityPolicy{})
if obj == nil {
return nil, err
}
return obj.(*extensions.PodSecurityPolicy), err
}
func (c *FakePodSecurityPolicy) Update(scc *extensions.PodSecurityPolicy) (*extensions.PodSecurityPolicy, error) {
obj, err := c.Fake.Invokes(NewUpdateAction("podsecuritypolicies", c.Namespace, scc), &extensions.PodSecurityPolicy{})
if obj == nil {
return nil, err
}
return obj.(*extensions.PodSecurityPolicy), err
}
func (c *FakePodSecurityPolicy) Delete(name string) error {
_, err := c.Fake.Invokes(NewDeleteAction("podsecuritypolicies", c.Namespace, name), &extensions.PodSecurityPolicy{})
return err
}
func (c *FakePodSecurityPolicy) Watch(opts api.ListOptions) (watch.Interface, error) {
return c.Fake.InvokesWatch(NewWatchAction("podsecuritypolicies", c.Namespace, opts))
}

View File

@ -230,6 +230,10 @@ func (c *Fake) Nodes() client.NodeInterface {
return &FakeNodes{Fake: c}
}
func (c *Fake) PodSecurityPolicies() client.PodSecurityPolicyInterface {
return &FakePodSecurityPolicy{Fake: c}
}
func (c *Fake) Events(namespace string) client.EventInterface {
return &FakeEvents{Fake: c, Namespace: namespace}
}

View File

@ -113,6 +113,7 @@ func expandResourceShortcut(resource unversioned.GroupVersionResource) unversion
"no": api.SchemeGroupVersion.WithResource("nodes"),
"ns": api.SchemeGroupVersion.WithResource("namespaces"),
"po": api.SchemeGroupVersion.WithResource("pods"),
"psp": api.SchemeGroupVersion.WithResource("podSecurityPolicies"),
"pvc": api.SchemeGroupVersion.WithResource("persistentvolumeclaims"),
"pv": api.SchemeGroupVersion.WithResource("persistentvolumes"),
"quota": api.SchemeGroupVersion.WithResource("resourcequotas"),

View File

@ -415,6 +415,7 @@ var horizontalPodAutoscalerColumns = []string{"NAME", "REFERENCE", "TARGET", "CU
var withNamespacePrefixColumns = []string{"NAMESPACE"} // TODO(erictune): print cluster name too.
var deploymentColumns = []string{"NAME", "DESIRED", "CURRENT", "UP-TO-DATE", "AVAILABLE", "AGE"}
var configMapColumns = []string{"NAME", "DATA", "AGE"}
var podSecurityPolicyColumns = []string{"NAME", "PRIV", "CAPS", "VOLUMEPLUGINS", "SELINUX", "RUNASUSER"}
// addDefaultHandlers adds print handlers for default Kubernetes types.
func (h *HumanReadablePrinter) addDefaultHandlers() {
@ -462,6 +463,8 @@ func (h *HumanReadablePrinter) addDefaultHandlers() {
h.Handler(horizontalPodAutoscalerColumns, printHorizontalPodAutoscalerList)
h.Handler(configMapColumns, printConfigMap)
h.Handler(configMapColumns, printConfigMapList)
h.Handler(podSecurityPolicyColumns, printPodSecurityPolicy)
h.Handler(podSecurityPolicyColumns, printPodSecurityPolicyList)
}
func (h *HumanReadablePrinter) unknown(data []byte, w io.Writer) error {
@ -1478,6 +1481,23 @@ func printConfigMapList(list *api.ConfigMapList, w io.Writer, options PrintOptio
return nil
}
func printPodSecurityPolicy(item *extensions.PodSecurityPolicy, w io.Writer, options PrintOptions) error {
_, err := fmt.Fprintf(w, "%s\t%t\t%v\t%t\t%s\t%s\n", item.Name, item.Spec.Privileged,
item.Spec.Capabilities, item.Spec.Volumes, item.Spec.SELinuxContext.Type,
item.Spec.RunAsUser.Type)
return err
}
func printPodSecurityPolicyList(list *extensions.PodSecurityPolicyList, w io.Writer, options PrintOptions) error {
for _, item := range list.Items {
if err := printPodSecurityPolicy(&item, w, options); err != nil {
return err
}
}
return nil
}
func appendLabels(itemLabels map[string]string, columnLabels []string) string {
var buffer bytes.Buffer

View File

@ -57,6 +57,7 @@ import (
pvetcd "k8s.io/kubernetes/pkg/registry/persistentvolume/etcd"
pvcetcd "k8s.io/kubernetes/pkg/registry/persistentvolumeclaim/etcd"
podetcd "k8s.io/kubernetes/pkg/registry/pod/etcd"
pspetcd "k8s.io/kubernetes/pkg/registry/podsecuritypolicy/etcd"
podtemplateetcd "k8s.io/kubernetes/pkg/registry/podtemplate/etcd"
resourcequotaetcd "k8s.io/kubernetes/pkg/registry/resourcequota/etcd"
secretetcd "k8s.io/kubernetes/pkg/registry/secret/etcd"
@ -587,7 +588,7 @@ func (m *Master) thirdpartyapi(group, kind, version string) *apiserver.APIGroupV
// getExperimentalResources returns the resources for extenstions api
func (m *Master) getExtensionResources(c *Config) map[string]rest.Storage {
// All resources except these are disabled by default.
enabledResources := sets.NewString("jobs", "horizontalpodautoscalers", "ingresses")
enabledResources := sets.NewString("jobs", "horizontalpodautoscalers", "ingresses", "podsecuritypolicy")
resourceOverrides := m.ApiGroupVersionOverrides["extensions/v1beta1"].ResourceOverrides
isEnabled := func(resource string) bool {
// Check if the resource has been overriden.
@ -650,6 +651,10 @@ func (m *Master) getExtensionResources(c *Config) map[string]rest.Storage {
storage["ingresses"] = ingressStorage
storage["ingresses/status"] = ingressStatusStorage
}
if isEnabled("podsecuritypolicy") {
podSecurityPolicyStorage := pspetcd.NewREST(dbClient("podsecuritypolicy"), storageDecorator)
storage["podSecurityPolicies"] = podSecurityPolicyStorage
}
return storage
}

View File

@ -0,0 +1,19 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package podsecuritypolicy provides Registry interface and its REST
// implementation for storing PodSecurityPolicy api objects.
package podsecuritypolicy

View File

@ -0,0 +1,67 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package etcd
import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/generic"
etcdgeneric "k8s.io/kubernetes/pkg/registry/generic/etcd"
"k8s.io/kubernetes/pkg/registry/podsecuritypolicy"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/storage"
)
// REST implements a RESTStorage for PodSecurityPolicies against etcd.
type REST struct {
*etcdgeneric.Etcd
}
const Prefix = "/podsecuritypolicies"
// NewREST returns a RESTStorage object that will work against PodSecurityPolicy objects.
func NewREST(s storage.Interface, storageDecorator generic.StorageDecorator) *REST {
newListFunc := func() runtime.Object { return &extensions.PodSecurityPolicyList{} }
storageInterface := storageDecorator(
s, 100, &extensions.PodSecurityPolicy{}, Prefix, podsecuritypolicy.Strategy, newListFunc)
store := &etcdgeneric.Etcd{
NewFunc: func() runtime.Object { return &extensions.PodSecurityPolicy{} },
NewListFunc: newListFunc,
KeyRootFunc: func(ctx api.Context) string {
return Prefix
},
KeyFunc: func(ctx api.Context, name string) (string, error) {
return etcdgeneric.NoNamespaceKeyFunc(ctx, Prefix, name)
},
ObjectNameFunc: func(obj runtime.Object) (string, error) {
return obj.(*extensions.PodSecurityPolicy).Name, nil
},
PredicateFunc: func(label labels.Selector, field fields.Selector) generic.Matcher {
return podsecuritypolicy.MatchPodSecurityPolicy(label, field)
},
QualifiedResource: extensions.Resource("podsecuritypolicies"),
CreateStrategy: podsecuritypolicy.Strategy,
UpdateStrategy: podsecuritypolicy.Strategy,
ReturnDeletedObject: true,
Storage: storageInterface,
}
return &REST{store}
}

View File

@ -0,0 +1,130 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package etcd
import (
"testing"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apis/extensions"
// Ensure that extensions/v1beta1 package is initialized.
_ "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/registry/registrytest"
"k8s.io/kubernetes/pkg/runtime"
etcdtesting "k8s.io/kubernetes/pkg/storage/etcd/testing"
)
func newStorage(t *testing.T) (*REST, *etcdtesting.EtcdTestServer) {
etcdStorage, server := registrytest.NewEtcdStorage(t, "extensions")
return NewREST(etcdStorage, generic.UndecoratedStorage), server
}
func validNewPodSecurityPolicy() *extensions.PodSecurityPolicy {
return &extensions.PodSecurityPolicy{
ObjectMeta: api.ObjectMeta{
Name: "foo",
},
Spec: extensions.PodSecurityPolicySpec{
SELinuxContext: extensions.SELinuxContextStrategyOptions{
Type: extensions.SELinuxStrategyRunAsAny,
},
RunAsUser: extensions.RunAsUserStrategyOptions{
Type: extensions.RunAsUserStrategyRunAsAny,
},
},
}
}
func TestCreate(t *testing.T) {
storage, server := newStorage(t)
defer server.Terminate(t)
test := registrytest.New(t, storage.Etcd).ClusterScope()
scc := validNewPodSecurityPolicy()
scc.ObjectMeta = api.ObjectMeta{GenerateName: "foo-"}
test.TestCreate(
// valid
scc,
// invalid
&extensions.PodSecurityPolicy{
ObjectMeta: api.ObjectMeta{Name: "name with spaces"},
},
)
}
func TestUpdate(t *testing.T) {
storage, server := newStorage(t)
defer server.Terminate(t)
test := registrytest.New(t, storage.Etcd).ClusterScope()
test.TestUpdate(
// valid
validNewPodSecurityPolicy(),
// updateFunc
func(obj runtime.Object) runtime.Object {
object := obj.(*extensions.PodSecurityPolicy)
object.Labels = map[string]string{"a": "b"}
return object
},
)
}
func TestDelete(t *testing.T) {
storage, server := newStorage(t)
defer server.Terminate(t)
test := registrytest.New(t, storage.Etcd).ClusterScope().ReturnDeletedObject()
test.TestDelete(validNewPodSecurityPolicy())
}
func TestGet(t *testing.T) {
storage, server := newStorage(t)
defer server.Terminate(t)
test := registrytest.New(t, storage.Etcd).ClusterScope()
test.TestGet(validNewPodSecurityPolicy())
}
func TestList(t *testing.T) {
storage, server := newStorage(t)
defer server.Terminate(t)
test := registrytest.New(t, storage.Etcd).ClusterScope()
test.TestList(validNewPodSecurityPolicy())
}
func TestWatch(t *testing.T) {
storage, server := newStorage(t)
defer server.Terminate(t)
test := registrytest.New(t, storage.Etcd).ClusterScope()
test.TestWatch(
validNewPodSecurityPolicy(),
// matching labels
[]labels.Set{},
// not matching labels
[]labels.Set{
{"foo": "bar"},
},
// matching fields
[]fields.Set{
{"metadata.name": "foo"},
},
// not matching fields
[]fields.Set{
{"metadata.name": "bar"},
{"name": "foo"},
},
)
}

View File

@ -0,0 +1,93 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package podsecuritypolicy
import (
"fmt"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/rest"
"k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/apis/extensions/validation"
"k8s.io/kubernetes/pkg/fields"
"k8s.io/kubernetes/pkg/labels"
"k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/validation/field"
)
// strategy implements behavior for PodSecurityPolicy objects
type strategy struct {
runtime.ObjectTyper
api.NameGenerator
}
// Strategy is the default logic that applies when creating and updating PodSecurityPolicy
// objects via the REST API.
var Strategy = strategy{api.Scheme, api.SimpleNameGenerator}
var _ = rest.RESTCreateStrategy(Strategy)
var _ = rest.RESTUpdateStrategy(Strategy)
func (strategy) NamespaceScoped() bool {
return false
}
func (strategy) AllowCreateOnUpdate() bool {
return false
}
func (strategy) AllowUnconditionalUpdate() bool {
return true
}
func (strategy) PrepareForCreate(obj runtime.Object) {
}
func (strategy) PrepareForUpdate(obj, old runtime.Object) {
}
func (strategy) Canonicalize(obj runtime.Object) {
}
func (strategy) Validate(ctx api.Context, obj runtime.Object) field.ErrorList {
return validation.ValidatePodSecurityPolicy(obj.(*extensions.PodSecurityPolicy))
}
func (strategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) field.ErrorList {
return validation.ValidatePodSecurityPolicyUpdate(old.(*extensions.PodSecurityPolicy), obj.(*extensions.PodSecurityPolicy))
}
// Matcher returns a generic matcher for a given label and field selector.
func MatchPodSecurityPolicy(label labels.Selector, field fields.Selector) generic.Matcher {
return &generic.SelectionPredicate{
Label: label,
Field: field,
GetAttrs: func(obj runtime.Object) (labels.Set, fields.Set, error) {
psp, ok := obj.(*extensions.PodSecurityPolicy)
if !ok {
return nil, nil, fmt.Errorf("given object is not a pod security policy.")
}
return labels.Set(psp.ObjectMeta.Labels), PodSecurityPolicyToSelectableFields(psp), nil
},
}
}
// PodSecurityPolicyToSelectableFields returns a label set that represents the object
func PodSecurityPolicyToSelectableFields(obj *extensions.PodSecurityPolicy) fields.Set {
return generic.ObjectMetaFieldsSet(obj.ObjectMeta, false)
}