From bb17d4f2cb08de6f3d82c13bd56c699f389b3c8f Mon Sep 17 00:00:00 2001 From: Mariano Cano <mariano@smallstep.com> Date: Mon, 12 Aug 2019 16:10:32 -0700 Subject: [PATCH] Add StepIssuer spec and generated files. --- api/v1beta1/groupversion_info.go | 35 ++++ api/v1beta1/stepissuer_types.go | 152 +++++++++++++++ api/v1beta1/zz_generated.deepcopy.go | 178 ++++++++++++++++++ .../certmanager.step.sm_stepissuers.yaml | 126 +++++++++++++ config/crd/kustomization.yaml | 21 +++ config/crd/kustomizeconfig.yaml | 17 ++ .../patches/cainjection_in_stepissuers.yaml | 8 + .../crd/patches/webhook_in_stepissuers.yaml | 17 ++ config/rbac/role.yaml | 45 +++++ config/webhook/manifests.yaml | 0 10 files changed, 599 insertions(+) create mode 100644 api/v1beta1/groupversion_info.go create mode 100644 api/v1beta1/stepissuer_types.go create mode 100644 api/v1beta1/zz_generated.deepcopy.go create mode 100644 config/crd/bases/certmanager.step.sm_stepissuers.yaml create mode 100644 config/crd/kustomization.yaml create mode 100644 config/crd/kustomizeconfig.yaml create mode 100644 config/crd/patches/cainjection_in_stepissuers.yaml create mode 100644 config/crd/patches/webhook_in_stepissuers.yaml create mode 100644 config/rbac/role.yaml create mode 100644 config/webhook/manifests.yaml diff --git a/api/v1beta1/groupversion_info.go b/api/v1beta1/groupversion_info.go new file mode 100644 index 0000000..5ac5135 --- /dev/null +++ b/api/v1beta1/groupversion_info.go @@ -0,0 +1,35 @@ +/* + +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 v1beta1 contains API Schema definitions for the certmanager v1beta1 API group +// +kubebuilder:object:generate=true +// +groupName=certmanager.step.sm +package v1beta1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects + GroupVersion = schema.GroupVersion{Group: "certmanager.step.sm", Version: "v1beta1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) diff --git a/api/v1beta1/stepissuer_types.go b/api/v1beta1/stepissuer_types.go new file mode 100644 index 0000000..e85c36c --- /dev/null +++ b/api/v1beta1/stepissuer_types.go @@ -0,0 +1,152 @@ +/* + +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 v1beta1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +func init() { + SchemeBuilder.Register(&StepIssuer{}, &StepIssuerList{}) +} + +// StepIssuerSpec defines the desired state of StepIssuer +type StepIssuerSpec struct { + // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster + // Important: Run "make" to regenerate code after modifying this file + + // URL is the base URL for the step certificates instance. + URL string `json:"url"` + + // Provisioner contains the step certificates provisioner configuration. + Provisioner StepProvisioner `json:"provisioner"` + + // CABundle is a base64 encoded TLS certificate used to verify connections + // to the step certificates server. If not set the system root certificates + // are used to validate the TLS connection. + // +optional + CABundle []byte `json:"caBundle,omitempty"` +} + +// StepIssuerStatus defines the observed state of StepIssuer +type StepIssuerStatus struct { + // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster + // Important: Run "make" to regenerate code after modifying this file + + // +optional + Conditions []StepIssuerCondition `json:"conditions,omitempty"` +} + +// +kubebuilder:object:root=true + +// StepIssuer is the Schema for the stepissuers API +type StepIssuer struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec StepIssuerSpec `json:"spec,omitempty"` + Status StepIssuerStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// StepIssuerList contains a list of StepIssuer +type StepIssuerList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []StepIssuer `json:"items"` +} + +// SecretKeySelector contains the reference to a secret. +type SecretKeySelector struct { + // The name of the secret in the pod's namespace to select from. + Name string `json:"name"` + + // The key of the secret to select from. Must be a valid secret key. + // +optional + Key string `json:"key,omitempty"` +} + +// StepProvisioner contains the configuration used to create step certificate +// tokens used to grant certificates. +type StepProvisioner struct { + // Names is the name of the JWK provisioner. + Name string `json:"name"` + + // KeyID is the kid property of the JWK provisioner. + KeyID string `json:"kid"` + + // PasswordRef is a reference to a Secret containing the provisioner + // password used to decrypt the provisioner private key. + PasswordRef SecretKeySelector `json:"passwordRef"` +} + +// ConditionType represents a StepIssuer condition type. +// +kubebuilder:validation:Enum=Ready +type ConditionType string + +const ( + // ConditionReady indicates that a StepIssuer is ready for use. + ConditionReady ConditionType = "Ready" +) + +// ConditionStatus represents a condition's status. +// +kubebuilder:validation:Enum=True;False;Unknown +type ConditionStatus string + +// These are valid condition statuses. "ConditionTrue" means a resource is in +// the condition; "ConditionFalse" means a resource is not in the condition; +// "ConditionUnknown" means kubernetes can't decide if a resource is in the +// condition or not. In the future, we could add other intermediate +// conditions, e.g. ConditionDegraded. +const ( + // ConditionTrue represents the fact that a given condition is true + ConditionTrue ConditionStatus = "True" + + // ConditionFalse represents the fact that a given condition is false + ConditionFalse ConditionStatus = "False" + + // ConditionUnknown represents the fact that a given condition is unknown + ConditionUnknown ConditionStatus = "Unknown" +) + +// StepIssuerCondition contains condition information for the step issuer. +type StepIssuerCondition struct { + // Type of the condition, currently ('Ready'). + Type ConditionType `json:"type"` + + // Status of the condition, one of ('True', 'False', 'Unknown'). + // +kubebuilder:validation:Enum=True;False;Unknown + Status ConditionStatus `json:"status"` + + // LastTransitionTime is the timestamp corresponding to the last status + // change of this condition. + // +optional + LastTransitionTime *metav1.Time `json:"lastTransitionTime,omitempty"` + + // Reason is a brief machine readable explanation for the condition's last + // transition. + // +optional + Reason string `json:"reason,omitempty"` + + // Message is a human readable description of the details of the last + // transition, complementing reason. + // +optional + Message string `json:"message,omitempty"` +} diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go new file mode 100644 index 0000000..3e78740 --- /dev/null +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -0,0 +1,178 @@ +// +build !ignore_autogenerated + +/* + +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. +*/ + +// autogenerated by controller-gen object, do not modify manually + +package v1beta1 + +import ( + "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SecretKeySelector) DeepCopyInto(out *SecretKeySelector) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretKeySelector. +func (in *SecretKeySelector) DeepCopy() *SecretKeySelector { + if in == nil { + return nil + } + out := new(SecretKeySelector) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StepIssuer) DeepCopyInto(out *StepIssuer) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StepIssuer. +func (in *StepIssuer) DeepCopy() *StepIssuer { + if in == nil { + return nil + } + out := new(StepIssuer) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *StepIssuer) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StepIssuerCondition) DeepCopyInto(out *StepIssuerCondition) { + *out = *in + if in.LastTransitionTime != nil { + in, out := &in.LastTransitionTime, &out.LastTransitionTime + *out = new(v1.Time) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StepIssuerCondition. +func (in *StepIssuerCondition) DeepCopy() *StepIssuerCondition { + if in == nil { + return nil + } + out := new(StepIssuerCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StepIssuerList) DeepCopyInto(out *StepIssuerList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]StepIssuer, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StepIssuerList. +func (in *StepIssuerList) DeepCopy() *StepIssuerList { + if in == nil { + return nil + } + out := new(StepIssuerList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *StepIssuerList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StepIssuerSpec) DeepCopyInto(out *StepIssuerSpec) { + *out = *in + out.Provisioner = in.Provisioner + if in.CABundle != nil { + in, out := &in.CABundle, &out.CABundle + *out = make([]byte, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StepIssuerSpec. +func (in *StepIssuerSpec) DeepCopy() *StepIssuerSpec { + if in == nil { + return nil + } + out := new(StepIssuerSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StepIssuerStatus) DeepCopyInto(out *StepIssuerStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]StepIssuerCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StepIssuerStatus. +func (in *StepIssuerStatus) DeepCopy() *StepIssuerStatus { + if in == nil { + return nil + } + out := new(StepIssuerStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StepProvisioner) DeepCopyInto(out *StepProvisioner) { + *out = *in + out.PasswordRef = in.PasswordRef +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StepProvisioner. +func (in *StepProvisioner) DeepCopy() *StepProvisioner { + if in == nil { + return nil + } + out := new(StepProvisioner) + in.DeepCopyInto(out) + return out +} diff --git a/config/crd/bases/certmanager.step.sm_stepissuers.yaml b/config/crd/bases/certmanager.step.sm_stepissuers.yaml new file mode 100644 index 0000000..5afc93b --- /dev/null +++ b/config/crd/bases/certmanager.step.sm_stepissuers.yaml @@ -0,0 +1,126 @@ + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + creationTimestamp: null + name: stepissuers.certmanager.step.sm +spec: + group: certmanager.step.sm + names: + kind: StepIssuer + plural: stepissuers + scope: "" + validation: + openAPIV3Schema: + description: StepIssuer is the Schema for the stepissuers API + properties: + apiVersion: + 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: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources' + type: string + kind: + 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: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: StepIssuerSpec defines the desired state of StepIssuer + properties: + caBundle: + description: CABundle is a base64 encoded TLS certificate used to verify + connections to the step certificates server. If not set the system + root certificates are used to validate the TLS connection. + format: byte + type: string + provisioner: + description: Provisioner contains the step certificates provisioner + configuration. + properties: + kid: + description: KeyID is the kid property of the JWK provisioner. + type: string + name: + description: Names is the name of the JWK provisioner. + type: string + passwordRef: + description: PasswordRef is a reference to a Secret containing the + provisioner password used to decrypt the provisioner private key. + properties: + key: + description: The key of the secret to select from. Must be a + valid secret key. + type: string + name: + description: The name of the secret in the pod's namespace to + select from. + type: string + required: + - name + type: object + required: + - kid + - name + - passwordRef + type: object + url: + description: URL is the base URL for the step certificates instance. + type: string + required: + - provisioner + - url + type: object + status: + description: StepIssuerStatus defines the observed state of StepIssuer + properties: + conditions: + items: + description: StepIssuerCondition contains condition information for + the step issuer. + properties: + lastTransitionTime: + description: LastTransitionTime is the timestamp corresponding + to the last status change of this condition. + format: date-time + type: string + message: + description: Message is a human readable description of the details + of the last transition, complementing reason. + type: string + reason: + description: Reason is a brief machine readable explanation for + the condition's last transition. + type: string + status: + description: Status of the condition, one of ('True', 'False', + 'Unknown'). + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: Type of the condition, currently ('Ready'). + enum: + - Ready + type: string + required: + - status + - type + type: object + type: array + type: object + type: object + versions: + - name: v1beta1 + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml new file mode 100644 index 0000000..066a1ac --- /dev/null +++ b/config/crd/kustomization.yaml @@ -0,0 +1,21 @@ +# This kustomization.yaml is not intended to be run by itself, +# since it depends on service name and namespace that are out of this kustomize package. +# It should be run by config/default +resources: +- bases/certmanager.step.sm_stepissuers.yaml +# +kubebuilder:scaffold:crdkustomizeresource + +patches: +# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix. +# patches here are for enabling the conversion webhook for each CRD +#- patches/webhook_in_stepissuers.yaml +# +kubebuilder:scaffold:crdkustomizewebhookpatch + +# [CERTMANAGER] To enable webhook, uncomment all the sections with [CERTMANAGER] prefix. +# patches here are for enabling the CA injection for each CRD +#- patches/cainjection_in_stepissuers.yaml +# +kubebuilder:scaffold:crdkustomizecainjectionpatch + +# the following config is for teaching kustomize how to do kustomization for CRDs. +configurations: +- kustomizeconfig.yaml diff --git a/config/crd/kustomizeconfig.yaml b/config/crd/kustomizeconfig.yaml new file mode 100644 index 0000000..6f83d9a --- /dev/null +++ b/config/crd/kustomizeconfig.yaml @@ -0,0 +1,17 @@ +# This file is for teaching kustomize how to substitute name and namespace reference in CRD +nameReference: +- kind: Service + version: v1 + fieldSpecs: + - kind: CustomResourceDefinition + group: apiextensions.k8s.io + path: spec/conversion/webhookClientConfig/service/name + +namespace: +- kind: CustomResourceDefinition + group: apiextensions.k8s.io + path: spec/conversion/webhookClientConfig/service/namespace + create: false + +varReference: +- path: metadata/annotations diff --git a/config/crd/patches/cainjection_in_stepissuers.yaml b/config/crd/patches/cainjection_in_stepissuers.yaml new file mode 100644 index 0000000..9c89961 --- /dev/null +++ b/config/crd/patches/cainjection_in_stepissuers.yaml @@ -0,0 +1,8 @@ +# The following patch adds a directive for certmanager to inject CA into the CRD +# CRD conversion requires k8s 1.13 or later. +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + certmanager.k8s.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) + name: stepissuers.certmanager.step.sm diff --git a/config/crd/patches/webhook_in_stepissuers.yaml b/config/crd/patches/webhook_in_stepissuers.yaml new file mode 100644 index 0000000..745ec1c --- /dev/null +++ b/config/crd/patches/webhook_in_stepissuers.yaml @@ -0,0 +1,17 @@ +# The following patch enables conversion webhook for CRD +# CRD conversion requires k8s 1.13 or later. +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: stepissuers.certmanager.step.sm +spec: + conversion: + strategy: Webhook + webhookClientConfig: + # this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank, + # but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager) + caBundle: Cg== + service: + namespace: system + name: webhook-service + path: /convert diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml new file mode 100644 index 0000000..9cb0d26 --- /dev/null +++ b/config/rbac/role.yaml @@ -0,0 +1,45 @@ + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + creationTimestamp: null + name: manager-role +rules: +- apiGroups: + - certmanager.k8s.io + resources: + - certificaterequests + verbs: + - get + - list + - update + - watch +- apiGroups: + - certmanager.k8s.io + resources: + - certificaterequests/status + verbs: + - get + - patch + - update +- apiGroups: + - certmanager.step.sm + resources: + - stepissuers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - certmanager.step.sm + resources: + - stepissuers/status + verbs: + - get + - patch + - update diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml new file mode 100644 index 0000000..e69de29 -- GitLab