From e0f5cca41076bf24bdf6519698749f913a085071 Mon Sep 17 00:00:00 2001 From: Jordan Liggitt Date: Mon, 1 Jun 2020 21:26:28 -0400 Subject: [PATCH] Copy CSR v1beta1 to v1 * Remove prerelease tags * Update copyright, package, imports to v1 * Remove signerName, usages, and condition status defaulting --- cmd/kube-apiserver/app/aggregator.go | 1 + hack/lib/init.sh | 1 + pkg/apis/certificates/install/install.go | 5 +- pkg/apis/certificates/v1/conversion.go | 38 ++++ pkg/apis/certificates/v1/defaults.go | 25 +++ pkg/apis/certificates/v1/doc.go | 24 ++ pkg/apis/certificates/v1/helpers.go | 37 ++++ pkg/apis/certificates/v1/register.go | 50 +++++ pkg/master/master.go | 2 + pkg/master/storageversionhashdata/data.go | 1 + .../certificates/rest/storage_certificates.go | 29 ++- staging/src/k8s.io/api/certificates/v1/doc.go | 23 ++ .../k8s.io/api/certificates/v1/register.go | 59 +++++ .../src/k8s.io/api/certificates/v1/types.go | 209 ++++++++++++++++++ staging/src/k8s.io/api/roundtrip_test.go | 2 + .../src/k8s.io/kubectl/pkg/scheme/install.go | 3 +- .../apiserver/apply/status_test.go | 1 + test/integration/etcd/data.go | 8 + 18 files changed, 513 insertions(+), 5 deletions(-) create mode 100644 pkg/apis/certificates/v1/conversion.go create mode 100644 pkg/apis/certificates/v1/defaults.go create mode 100644 pkg/apis/certificates/v1/doc.go create mode 100644 pkg/apis/certificates/v1/helpers.go create mode 100644 pkg/apis/certificates/v1/register.go create mode 100644 staging/src/k8s.io/api/certificates/v1/doc.go create mode 100644 staging/src/k8s.io/api/certificates/v1/register.go create mode 100644 staging/src/k8s.io/api/certificates/v1/types.go diff --git a/cmd/kube-apiserver/app/aggregator.go b/cmd/kube-apiserver/app/aggregator.go index c0f827eb3a6..571c5fd59f7 100644 --- a/cmd/kube-apiserver/app/aggregator.go +++ b/cmd/kube-apiserver/app/aggregator.go @@ -263,6 +263,7 @@ var apiVersionPriorities = map[schema.GroupVersion]priority{ {Group: "batch", Version: "v1"}: {group: 17400, version: 15}, {Group: "batch", Version: "v1beta1"}: {group: 17400, version: 9}, {Group: "batch", Version: "v2alpha1"}: {group: 17400, version: 9}, + {Group: "certificates.k8s.io", Version: "v1"}: {group: 17300, version: 15}, {Group: "certificates.k8s.io", Version: "v1beta1"}: {group: 17300, version: 9}, {Group: "networking.k8s.io", Version: "v1"}: {group: 17200, version: 15}, {Group: "networking.k8s.io", Version: "v1beta1"}: {group: 17200, version: 9}, diff --git a/hack/lib/init.sh b/hack/lib/init.sh index d585403b7ed..b4681778aa3 100755 --- a/hack/lib/init.sh +++ b/hack/lib/init.sh @@ -80,6 +80,7 @@ autoscaling/v2beta2 \ batch/v1 \ batch/v1beta1 \ batch/v2alpha1 \ +certificates.k8s.io/v1 \ certificates.k8s.io/v1beta1 \ coordination.k8s.io/v1beta1 \ coordination.k8s.io/v1 \ diff --git a/pkg/apis/certificates/install/install.go b/pkg/apis/certificates/install/install.go index 8f685da6091..f4e9fcb9ce3 100644 --- a/pkg/apis/certificates/install/install.go +++ b/pkg/apis/certificates/install/install.go @@ -23,6 +23,7 @@ import ( utilruntime "k8s.io/apimachinery/pkg/util/runtime" "k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/apis/certificates" + v1 "k8s.io/kubernetes/pkg/apis/certificates/v1" "k8s.io/kubernetes/pkg/apis/certificates/v1beta1" ) @@ -33,6 +34,8 @@ func init() { // Install registers the API group and adds types to a scheme func Install(scheme *runtime.Scheme) { utilruntime.Must(certificates.AddToScheme(scheme)) + utilruntime.Must(v1.AddToScheme(scheme)) utilruntime.Must(v1beta1.AddToScheme(scheme)) - utilruntime.Must(scheme.SetVersionPriority(v1beta1.SchemeGroupVersion)) + // TODO(liggitt): prefer v1 in 1.20 + utilruntime.Must(scheme.SetVersionPriority(v1beta1.SchemeGroupVersion, v1.SchemeGroupVersion)) } diff --git a/pkg/apis/certificates/v1/conversion.go b/pkg/apis/certificates/v1/conversion.go new file mode 100644 index 00000000000..f6d672b8a02 --- /dev/null +++ b/pkg/apis/certificates/v1/conversion.go @@ -0,0 +1,38 @@ +/* +Copyright 2020 The Kubernetes Authors. + +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 v1 + +import ( + "fmt" + + "k8s.io/apimachinery/pkg/runtime" +) + +func addConversionFuncs(scheme *runtime.Scheme) error { + // Add field conversion funcs. + return scheme.AddFieldLabelConversionFunc(SchemeGroupVersion.WithKind("CertificateSigningRequest"), + func(label, value string) (string, string, error) { + switch label { + case "metadata.name", + "spec.signerName": + return label, value, nil + default: + return "", "", fmt.Errorf("field label not supported: %s", label) + } + }, + ) +} diff --git a/pkg/apis/certificates/v1/defaults.go b/pkg/apis/certificates/v1/defaults.go new file mode 100644 index 00000000000..b1fc88a752a --- /dev/null +++ b/pkg/apis/certificates/v1/defaults.go @@ -0,0 +1,25 @@ +/* +Copyright 2020 The Kubernetes Authors. + +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 v1 + +import ( + "k8s.io/apimachinery/pkg/runtime" +) + +func addDefaultingFuncs(scheme *runtime.Scheme) error { + return RegisterDefaults(scheme) +} diff --git a/pkg/apis/certificates/v1/doc.go b/pkg/apis/certificates/v1/doc.go new file mode 100644 index 00000000000..3f2a7e98c77 --- /dev/null +++ b/pkg/apis/certificates/v1/doc.go @@ -0,0 +1,24 @@ +/* +Copyright 2020 The Kubernetes Authors. + +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. +*/ + +// +k8s:conversion-gen=k8s.io/kubernetes/pkg/apis/certificates +// +k8s:conversion-gen-external-types=k8s.io/api/certificates/v1 +// +k8s:defaulter-gen=TypeMeta +// +k8s:defaulter-gen-input=../../../../vendor/k8s.io/api/certificates/v1 + +// +groupName=certificates.k8s.io + +package v1 // import "k8s.io/kubernetes/pkg/apis/certificates/v1" diff --git a/pkg/apis/certificates/v1/helpers.go b/pkg/apis/certificates/v1/helpers.go new file mode 100644 index 00000000000..94fcddfc3fd --- /dev/null +++ b/pkg/apis/certificates/v1/helpers.go @@ -0,0 +1,37 @@ +/* +Copyright 2020 The Kubernetes Authors. + +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 v1 + +import ( + "crypto/x509" + "encoding/pem" + "errors" +) + +// ParseCSR decodes a PEM encoded CSR +func ParseCSR(pemBytes []byte) (*x509.CertificateRequest, error) { + // extract PEM from request object + block, _ := pem.Decode(pemBytes) + if block == nil || block.Type != "CERTIFICATE REQUEST" { + return nil, errors.New("PEM block type must be CERTIFICATE REQUEST") + } + csr, err := x509.ParseCertificateRequest(block.Bytes) + if err != nil { + return nil, err + } + return csr, nil +} diff --git a/pkg/apis/certificates/v1/register.go b/pkg/apis/certificates/v1/register.go new file mode 100644 index 00000000000..34ae6570437 --- /dev/null +++ b/pkg/apis/certificates/v1/register.go @@ -0,0 +1,50 @@ +/* +Copyright 2020 The Kubernetes Authors. + +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 v1 + +import ( + certificatesv1 "k8s.io/api/certificates/v1" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName is the group name use in this package +const GroupName = "certificates.k8s.io" + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1"} + +// Kind takes an unqualified kind and returns a Group qualified GroupKind +func Kind(kind string) schema.GroupKind { + return SchemeGroupVersion.WithKind(kind).GroupKind() +} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + localSchemeBuilder = &certificatesv1.SchemeBuilder + AddToScheme = localSchemeBuilder.AddToScheme +) + +func init() { + // We only register manually written functions here. The registration of the + // generated functions takes place in the generated files. The separation + // makes the code compile even when the generated files are missing. + localSchemeBuilder.Register(addDefaultingFuncs, addConversionFuncs) +} diff --git a/pkg/master/master.go b/pkg/master/master.go index 232eb736a5f..14e50e06bb5 100644 --- a/pkg/master/master.go +++ b/pkg/master/master.go @@ -38,6 +38,7 @@ import ( batchapiv1 "k8s.io/api/batch/v1" batchapiv1beta1 "k8s.io/api/batch/v1beta1" batchapiv2alpha1 "k8s.io/api/batch/v2alpha1" + certificatesapiv1 "k8s.io/api/certificates/v1" certificatesapiv1beta1 "k8s.io/api/certificates/v1beta1" coordinationapiv1 "k8s.io/api/coordination/v1" coordinationapiv1beta1 "k8s.io/api/coordination/v1beta1" @@ -606,6 +607,7 @@ func DefaultAPIResourceConfigSource() *serverstorage.ResourceConfig { autoscalingapiv2beta2.SchemeGroupVersion, batchapiv1.SchemeGroupVersion, batchapiv1beta1.SchemeGroupVersion, + certificatesapiv1.SchemeGroupVersion, certificatesapiv1beta1.SchemeGroupVersion, coordinationapiv1.SchemeGroupVersion, coordinationapiv1beta1.SchemeGroupVersion, diff --git a/pkg/master/storageversionhashdata/data.go b/pkg/master/storageversionhashdata/data.go index 4e32571c53f..3f35b867791 100644 --- a/pkg/master/storageversionhashdata/data.go +++ b/pkg/master/storageversionhashdata/data.go @@ -62,6 +62,7 @@ var GVRToStorageVersionHash = map[string]string{ "autoscaling/v2beta2/horizontalpodautoscalers": "oQlkt7f5j/A=", "batch/v1/jobs": "mudhfqk/qZY=", "batch/v1beta1/cronjobs": "h/JlFAZkyyY=", + "certificates.k8s.io/v1/certificatesigningrequests": "UQh3YTCDIf0=", "certificates.k8s.io/v1beta1/certificatesigningrequests": "UQh3YTCDIf0=", "coordination.k8s.io/v1beta1/leases": "/sY7hl8ol1U=", "coordination.k8s.io/v1/leases": "/sY7hl8ol1U=", diff --git a/pkg/registry/certificates/rest/storage_certificates.go b/pkg/registry/certificates/rest/storage_certificates.go index 12d1a7a4862..51d4df034f8 100644 --- a/pkg/registry/certificates/rest/storage_certificates.go +++ b/pkg/registry/certificates/rest/storage_certificates.go @@ -17,6 +17,7 @@ limitations under the License. package rest import ( + certificatesapiv1 "k8s.io/api/certificates/v1" certificatesapiv1beta1 "k8s.io/api/certificates/v1beta1" "k8s.io/apiserver/pkg/registry/generic" "k8s.io/apiserver/pkg/registry/rest" @@ -35,11 +36,19 @@ func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource serverstorag // TODO refactor the plumbing to provide the information in the APIGroupInfo if apiResourceConfigSource.VersionEnabled(certificatesapiv1beta1.SchemeGroupVersion) { - if storageMap, err := p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter); err != nil { + storageMap, err := p.v1beta1Storage(apiResourceConfigSource, restOptionsGetter) + if err != nil { return genericapiserver.APIGroupInfo{}, false, err - } else { - apiGroupInfo.VersionedResourcesStorageMap[certificatesapiv1beta1.SchemeGroupVersion.Version] = storageMap } + apiGroupInfo.VersionedResourcesStorageMap[certificatesapiv1beta1.SchemeGroupVersion.Version] = storageMap + } + + if apiResourceConfigSource.VersionEnabled(certificatesapiv1.SchemeGroupVersion) { + storageMap, err := p.v1Storage(apiResourceConfigSource, restOptionsGetter) + if err != nil { + return genericapiserver.APIGroupInfo{}, false, err + } + apiGroupInfo.VersionedResourcesStorageMap[certificatesapiv1.SchemeGroupVersion.Version] = storageMap } return apiGroupInfo, true, nil @@ -59,6 +68,20 @@ func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorag return storage, err } +func (p RESTStorageProvider) v1Storage(apiResourceConfigSource serverstorage.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (map[string]rest.Storage, error) { + storage := map[string]rest.Storage{} + // certificatesigningrequests + csrStorage, csrStatusStorage, csrApprovalStorage, err := certificatestore.NewREST(restOptionsGetter) + if err != nil { + return storage, err + } + storage["certificatesigningrequests"] = csrStorage + storage["certificatesigningrequests/status"] = csrStatusStorage + storage["certificatesigningrequests/approval"] = csrApprovalStorage + + return storage, err +} + func (p RESTStorageProvider) GroupName() string { return certificates.GroupName } diff --git a/staging/src/k8s.io/api/certificates/v1/doc.go b/staging/src/k8s.io/api/certificates/v1/doc.go new file mode 100644 index 00000000000..fe3ea3af87f --- /dev/null +++ b/staging/src/k8s.io/api/certificates/v1/doc.go @@ -0,0 +1,23 @@ +/* +Copyright 2020 The Kubernetes Authors. + +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. +*/ + +// +k8s:deepcopy-gen=package +// +k8s:protobuf-gen=package +// +k8s:openapi-gen=true + +// +groupName=certificates.k8s.io + +package v1 // import "k8s.io/api/certificates/v1" diff --git a/staging/src/k8s.io/api/certificates/v1/register.go b/staging/src/k8s.io/api/certificates/v1/register.go new file mode 100644 index 00000000000..3f2850f486b --- /dev/null +++ b/staging/src/k8s.io/api/certificates/v1/register.go @@ -0,0 +1,59 @@ +/* +Copyright 2020 The Kubernetes Authors. + +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 v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName is the group name use in this package +const GroupName = "certificates.k8s.io" + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1"} + +// Kind takes an unqualified kind and returns a Group qualified GroupKind +func Kind(kind string) schema.GroupKind { + return SchemeGroupVersion.WithKind(kind).GroupKind() +} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + // TODO: move SchemeBuilder with zz_generated.deepcopy.go to k8s.io/api. + // localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes. + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + localSchemeBuilder = &SchemeBuilder + AddToScheme = localSchemeBuilder.AddToScheme +) + +// Adds the list of known types to the given scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &CertificateSigningRequest{}, + &CertificateSigningRequestList{}, + ) + + // Add the watch version that applies + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/staging/src/k8s.io/api/certificates/v1/types.go b/staging/src/k8s.io/api/certificates/v1/types.go new file mode 100644 index 00000000000..edf2a71b6a7 --- /dev/null +++ b/staging/src/k8s.io/api/certificates/v1/types.go @@ -0,0 +1,209 @@ +/* +Copyright 2020 The Kubernetes Authors. + +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 v1 + +import ( + "fmt" + + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// +genclient +// +genclient:nonNamespaced +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// Describes a certificate signing request +type CertificateSigningRequest struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + // The certificate request itself and any additional information. + // +optional + Spec CertificateSigningRequestSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"` + + // Derived information about the request. + // +optional + Status CertificateSigningRequestStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"` +} + +// This information is immutable after the request is created. Only the Request +// and Usages fields can be set on creation, other fields are derived by +// Kubernetes and cannot be modified by users. +type CertificateSigningRequestSpec struct { + // Base64-encoded PKCS#10 CSR data + // +listType=atomic + Request []byte `json:"request" protobuf:"bytes,1,opt,name=request"` + + // Requested signer for the request. It is a qualified name in the form: + // `scope-hostname.io/name`. + // If empty, it will be defaulted: + // 1. If it's a kubelet client certificate, it is assigned + // "kubernetes.io/kube-apiserver-client-kubelet". + // 2. If it's a kubelet serving certificate, it is assigned + // "kubernetes.io/kubelet-serving". + // 3. Otherwise, it is assigned "kubernetes.io/legacy-unknown". + // Distribution of trust for signers happens out of band. + // You can select on this field using `spec.signerName`. + // +optional + SignerName *string `json:"signerName,omitempty" protobuf:"bytes,7,opt,name=signerName"` + + // allowedUsages specifies a set of usage contexts the key will be + // valid for. + // See: https://tools.ietf.org/html/rfc5280#section-4.2.1.3 + // https://tools.ietf.org/html/rfc5280#section-4.2.1.12 + // +listType=atomic + Usages []KeyUsage `json:"usages,omitempty" protobuf:"bytes,5,opt,name=usages"` + + // Information about the requesting user. + // See user.Info interface for details. + // +optional + Username string `json:"username,omitempty" protobuf:"bytes,2,opt,name=username"` + // UID information about the requesting user. + // See user.Info interface for details. + // +optional + UID string `json:"uid,omitempty" protobuf:"bytes,3,opt,name=uid"` + // Group information about the requesting user. + // See user.Info interface for details. + // +listType=atomic + // +optional + Groups []string `json:"groups,omitempty" protobuf:"bytes,4,rep,name=groups"` + // Extra information about the requesting user. + // See user.Info interface for details. + // +optional + Extra map[string]ExtraValue `json:"extra,omitempty" protobuf:"bytes,6,rep,name=extra"` +} + +// Built in signerName values that are honoured by kube-controller-manager. +// None of these usages are related to ServiceAccount token secrets +// `.data[ca.crt]` in any way. +const ( + // Signs certificates that will be honored as client-certs by the + // kube-apiserver. Never auto-approved by kube-controller-manager. + KubeAPIServerClientSignerName = "kubernetes.io/kube-apiserver-client" + + // Signs client certificates that will be honored as client-certs by the + // kube-apiserver for a kubelet. + // May be auto-approved by kube-controller-manager. + KubeAPIServerClientKubeletSignerName = "kubernetes.io/kube-apiserver-client-kubelet" + + // Signs serving certificates that are honored as a valid kubelet serving + // certificate by the kube-apiserver, but has no other guarantees. + KubeletServingSignerName = "kubernetes.io/kubelet-serving" + + // Has no guarantees for trust at all. Some distributions may honor these + // as client certs, but that behavior is not standard kubernetes behavior. + LegacyUnknownSignerName = "kubernetes.io/legacy-unknown" +) + +// ExtraValue masks the value so protobuf can generate +// +protobuf.nullable=true +// +protobuf.options.(gogoproto.goproto_stringer)=false +type ExtraValue []string + +func (t ExtraValue) String() string { + return fmt.Sprintf("%v", []string(t)) +} + +type CertificateSigningRequestStatus struct { + // Conditions applied to the request, such as approval or denial. + // +listType=map + // +listMapKey=type + // +optional + Conditions []CertificateSigningRequestCondition `json:"conditions,omitempty" protobuf:"bytes,1,rep,name=conditions"` + + // If request was approved, the controller will place the issued certificate here. + // +listType=atomic + // +optional + Certificate []byte `json:"certificate,omitempty" protobuf:"bytes,2,opt,name=certificate"` +} + +type RequestConditionType string + +// These are the possible conditions for a certificate request. +const ( + CertificateApproved RequestConditionType = "Approved" + CertificateDenied RequestConditionType = "Denied" + CertificateFailed RequestConditionType = "Failed" +) + +type CertificateSigningRequestCondition struct { + // type of the condition. Known conditions include "Approved", "Denied", and "Failed". + Type RequestConditionType `json:"type" protobuf:"bytes,1,opt,name=type,casttype=RequestConditionType"` + // Status of the condition, one of True, False, Unknown. + // Approved, Denied, and Failed conditions may not be "False" or "Unknown". + // Defaults to "True". + // If unset, should be treated as "True". + // +optional + Status v1.ConditionStatus `json:"status" protobuf:"bytes,6,opt,name=status,casttype=k8s.io/api/core/v1.ConditionStatus"` + // brief reason for the request state + // +optional + Reason string `json:"reason,omitempty" protobuf:"bytes,2,opt,name=reason"` + // human readable message with details about the request state + // +optional + Message string `json:"message,omitempty" protobuf:"bytes,3,opt,name=message"` + // timestamp for the last update to this condition + // +optional + LastUpdateTime metav1.Time `json:"lastUpdateTime,omitempty" protobuf:"bytes,4,opt,name=lastUpdateTime"` + // lastTransitionTime is the time the condition last transitioned from one status to another. + // If unset, when a new condition type is added or an existing condition's status is changed, + // the server defaults this to the current time. + // +optional + LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty" protobuf:"bytes,5,opt,name=lastTransitionTime"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +type CertificateSigningRequestList struct { + metav1.TypeMeta `json:",inline"` + // +optional + metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + + Items []CertificateSigningRequest `json:"items" protobuf:"bytes,2,rep,name=items"` +} + +// KeyUsages specifies valid usage contexts for keys. +// See: https://tools.ietf.org/html/rfc5280#section-4.2.1.3 +// https://tools.ietf.org/html/rfc5280#section-4.2.1.12 +type KeyUsage string + +const ( + UsageSigning KeyUsage = "signing" + UsageDigitalSignature KeyUsage = "digital signature" + UsageContentCommitment KeyUsage = "content commitment" + UsageKeyEncipherment KeyUsage = "key encipherment" + UsageKeyAgreement KeyUsage = "key agreement" + UsageDataEncipherment KeyUsage = "data encipherment" + UsageCertSign KeyUsage = "cert sign" + UsageCRLSign KeyUsage = "crl sign" + UsageEncipherOnly KeyUsage = "encipher only" + UsageDecipherOnly KeyUsage = "decipher only" + UsageAny KeyUsage = "any" + UsageServerAuth KeyUsage = "server auth" + UsageClientAuth KeyUsage = "client auth" + UsageCodeSigning KeyUsage = "code signing" + UsageEmailProtection KeyUsage = "email protection" + UsageSMIME KeyUsage = "s/mime" + UsageIPsecEndSystem KeyUsage = "ipsec end system" + UsageIPsecTunnel KeyUsage = "ipsec tunnel" + UsageIPsecUser KeyUsage = "ipsec user" + UsageTimestamping KeyUsage = "timestamping" + UsageOCSPSigning KeyUsage = "ocsp signing" + UsageMicrosoftSGC KeyUsage = "microsoft sgc" + UsageNetscapeSGC KeyUsage = "netscape sgc" +) diff --git a/staging/src/k8s.io/api/roundtrip_test.go b/staging/src/k8s.io/api/roundtrip_test.go index 321b2dfa3c5..e3c147b7fcc 100644 --- a/staging/src/k8s.io/api/roundtrip_test.go +++ b/staging/src/k8s.io/api/roundtrip_test.go @@ -37,6 +37,7 @@ import ( batchv1 "k8s.io/api/batch/v1" batchv1beta1 "k8s.io/api/batch/v1beta1" batchv2alpha1 "k8s.io/api/batch/v2alpha1" + certificatesv1 "k8s.io/api/certificates/v1" certificatesv1beta1 "k8s.io/api/certificates/v1beta1" coordinationv1 "k8s.io/api/coordination/v1" coordinationv1beta1 "k8s.io/api/coordination/v1beta1" @@ -86,6 +87,7 @@ var groups = []runtime.SchemeBuilder{ batchv2alpha1.SchemeBuilder, batchv1beta1.SchemeBuilder, batchv1.SchemeBuilder, + certificatesv1.SchemeBuilder, certificatesv1beta1.SchemeBuilder, coordinationv1.SchemeBuilder, coordinationv1beta1.SchemeBuilder, diff --git a/staging/src/k8s.io/kubectl/pkg/scheme/install.go b/staging/src/k8s.io/kubectl/pkg/scheme/install.go index ffd15bf1b66..06dc0a2a619 100644 --- a/staging/src/k8s.io/kubectl/pkg/scheme/install.go +++ b/staging/src/k8s.io/kubectl/pkg/scheme/install.go @@ -33,6 +33,7 @@ import ( batchv1 "k8s.io/api/batch/v1" batchv1beta1 "k8s.io/api/batch/v1beta1" batchv2alpha1 "k8s.io/api/batch/v2alpha1" + certificatesv1 "k8s.io/api/certificates/v1" certificatesv1beta1 "k8s.io/api/certificates/v1beta1" corev1 "k8s.io/api/core/v1" extensionsv1beta1 "k8s.io/api/extensions/v1beta1" @@ -71,7 +72,7 @@ func init() { utilruntime.Must(Scheme.SetVersionPriority(authorizationv1.SchemeGroupVersion, authorizationv1beta1.SchemeGroupVersion)) utilruntime.Must(Scheme.SetVersionPriority(autoscalingv1.SchemeGroupVersion, autoscalingv2beta1.SchemeGroupVersion)) utilruntime.Must(Scheme.SetVersionPriority(batchv1.SchemeGroupVersion, batchv1beta1.SchemeGroupVersion, batchv2alpha1.SchemeGroupVersion)) - utilruntime.Must(Scheme.SetVersionPriority(certificatesv1beta1.SchemeGroupVersion)) + utilruntime.Must(Scheme.SetVersionPriority(certificatesv1.SchemeGroupVersion, certificatesv1beta1.SchemeGroupVersion)) utilruntime.Must(Scheme.SetVersionPriority(extensionsv1beta1.SchemeGroupVersion)) utilruntime.Must(Scheme.SetVersionPriority(imagepolicyv1alpha1.SchemeGroupVersion)) utilruntime.Must(Scheme.SetVersionPriority(networkingv1.SchemeGroupVersion)) diff --git a/test/integration/apiserver/apply/status_test.go b/test/integration/apiserver/apply/status_test.go index 2214c72a499..a8c3af1b40e 100644 --- a/test/integration/apiserver/apply/status_test.go +++ b/test/integration/apiserver/apply/status_test.go @@ -55,6 +55,7 @@ var statusData = map[schema.GroupVersionResource]string{ gvr("storage.k8s.io", "v1", "volumeattachments"): `{"status": {"attached": true}}`, gvr("policy", "v1beta1", "poddisruptionbudgets"): `{"status": {"currentHealthy": 5}}`, gvr("certificates.k8s.io", "v1beta1", "certificatesigningrequests"): `{"status": {"conditions": [{"type": "MyStatus"}]}}`, + gvr("certificates.k8s.io", "v1", "certificatesigningrequests"): `{"status": {"conditions": [{"type": "MyStatus", "status": "True"}]}}`, } const statusDefault = `{"status": {"conditions": [{"type": "MyStatus", "status":"true"}]}}` diff --git a/test/integration/etcd/data.go b/test/integration/etcd/data.go index 8d17cfa99ff..bed992e57e1 100644 --- a/test/integration/etcd/data.go +++ b/test/integration/etcd/data.go @@ -176,6 +176,14 @@ func GetEtcdStorageDataForNamespace(namespace string) map[schema.GroupVersionRes }, // -- + // k8s.io/kubernetes/pkg/apis/certificates/v1 + gvr("certificates.k8s.io", "v1", "certificatesigningrequests"): { + Stub: `{"metadata": {"name": "csr2"}, "spec": {"signerName":"example.com/signer", "usages":["any"], "request": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQnlqQ0NBVE1DQVFBd2dZa3hDekFKQmdOVkJBWVRBbFZUTVJNd0VRWURWUVFJRXdwRFlXeHBabTl5Ym1saApNUll3RkFZRFZRUUhFdzFOYjNWdWRHRnBiaUJXYVdWM01STXdFUVlEVlFRS0V3cEhiMjluYkdVZ1NXNWpNUjh3CkhRWURWUVFMRXhaSmJtWnZjbTFoZEdsdmJpQlVaV05vYm05c2IyZDVNUmN3RlFZRFZRUURFdzUzZDNjdVoyOXYKWjJ4bExtTnZiVENCbnpBTkJna3Foa2lHOXcwQkFRRUZBQU9CalFBd2dZa0NnWUVBcFp0WUpDSEo0VnBWWEhmVgpJbHN0UVRsTzRxQzAzaGpYK1prUHl2ZFlkMVE0K3FiQWVUd1htQ1VLWUhUaFZSZDVhWFNxbFB6eUlCd2llTVpyCldGbFJRZGRaMUl6WEFsVlJEV3dBbzYwS2VjcWVBWG5uVUsrNWZYb1RJL1VnV3NocmU4dEoreC9UTUhhUUtSL0oKY0lXUGhxYVFoc0p1elpidkFkR0E4MEJMeGRNQ0F3RUFBYUFBTUEwR0NTcUdTSWIzRFFFQkJRVUFBNEdCQUlobAo0UHZGcStlN2lwQVJnSTVaTStHWng2bXBDejQ0RFRvMEprd2ZSRGYrQnRyc2FDMHE2OGVUZjJYaFlPc3E0ZmtIClEwdUEwYVZvZzNmNWlKeENhM0hwNWd4YkpRNnpWNmtKMFRFc3VhYU9oRWtvOXNkcENvUE9uUkJtMmkvWFJEMkQKNmlOaDhmOHowU2hHc0ZxakRnRkh5RjNvK2xVeWorVUM2SDFRVzdibgotLS0tLUVORCBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0="}}`, + ExpectedEtcdPath: "/registry/certificatesigningrequests/csr2", + ExpectedGVK: gvkP("certificates.k8s.io", "v1beta1", "CertificateSigningRequest"), + }, + // -- + // k8s.io/kubernetes/pkg/apis/coordination/v1 gvr("coordination.k8s.io", "v1", "leases"): { Stub: `{"metadata": {"name": "leasev1"}, "spec": {"holderIdentity": "holder", "leaseDurationSeconds": 5}}`,