From: root Date: Tue, 16 Jun 2020 09:09:49 +0000 (+0000) Subject: Add CRD for IpsecSite X-Git-Tag: v1.0~21^2 X-Git-Url: https://gerrit.akraino.org/r/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F75%2F3575%2F8;p=icn%2Fsdwan.git Add CRD for IpsecSite * Add changes for another IPSec crd: IpsecSite Issue-ID: ICN-289 Change-Id: I9c76c28ec22640b0089e0bc097a316af68b6fd19 Signed-off-by: Ruoyu --- diff --git a/platform/crd-ctrlr/README.md b/platform/crd-ctrlr/README.md index 78267eb..9507b78 100644 --- a/platform/crd-ctrlr/README.md +++ b/platform/crd-ctrlr/README.md @@ -116,11 +116,11 @@ make gen-yaml IMG="integratedcloudnative/sdewan-controller:dev" - FirewallSNAT - IpsecProposal - IpsecHost + - IpsecSite ### What we don't have yet - Add a watch for deployment, so that the controller can get the CNF ready status change. [predicate feature](https://godoc.org/sigs.k8s.io/controller-runtime/pkg/predicate#example-Funcs) should be used to filter no-status event. -- Implemente the ipsec CRDs/controllers - Add validation webhook to validate CR ( as we have the validation in openwrt, so not validate the CR at frontend) ### NOTEs diff --git a/platform/crd-ctrlr/examples/sdewan-controller.yaml b/platform/crd-ctrlr/examples/sdewan-controller.yaml index 98cc9a5..2161930 100644 --- a/platform/crd-ctrlr/examples/sdewan-controller.yaml +++ b/platform/crd-ctrlr/examples/sdewan-controller.yaml @@ -694,6 +694,141 @@ status: --- apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.2.5 + creationTimestamp: null + name: ipsecsites.batch.sdewan.akraino.org +spec: + group: batch.sdewan.akraino.org + names: + kind: IpsecSite + listKind: IpsecSiteList + plural: ipsecsites + singular: ipsecsite + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + description: IpsecSite is the Schema for the ipsecsites 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/sig-architecture/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/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: IpsecSiteSpec defines the desired state of IpsecSite + properties: + authentication_method: + type: string + connections: + items: + properties: + conn_type: + type: string + crypto_proposal: + items: + type: string + type: array + if_id: + type: string + local_firewall: + type: string + local_subnet: + type: string + local_updown: + type: string + mark: + type: string + mode: + type: string + name: + type: string + remote_firewall: + type: string + remote_sourceip: + type: string + remote_subnet: + type: string + remote_updown: + type: string + required: + - conn_type + - local_subnet + - mode + - name + type: object + type: array + crypto_proposal: + items: + type: string + type: array + force_crypto_proposal: + type: string + local_identifier: + type: string + local_private_cert: + type: string + local_public_cert: + type: string + name: + type: string + pre_shared_key: + type: string + remote: + type: string + remote_identifier: + type: string + shared_ca: + type: string + type: + type: string + required: + - authentication_method + - connections + - crypto_proposal + - remote + type: object + status: + description: status subsource used for Sdewan rule CRDs + properties: + appliedGeneration: + format: int64 + type: integer + appliedTime: + format: date-time + type: string + message: + type: string + state: + type: string + required: + - state + type: object + type: object + version: v1alpha1 + versions: + - name: v1alpha1 + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.2.5 @@ -1068,6 +1203,26 @@ rules: - get - patch - update +- apiGroups: + - batch.sdewan.akraino.org + resources: + - ipsecsites + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - batch.sdewan.akraino.org + resources: + - ipsecsites/status + verbs: + - get + - patch + - update - apiGroups: - batch.sdewan.akraino.org resources: @@ -1319,6 +1474,7 @@ webhooks: - firewalldnats - ipsecproposals - ipsechosts + - ipsecsites - clientConfig: caBundle: Cg== service: @@ -1347,3 +1503,4 @@ webhooks: - firewalldnats - ipsecproposals - ipsechosts + - ipsecsites diff --git a/platform/crd-ctrlr/src/PROJECT b/platform/crd-ctrlr/src/PROJECT index e282bff..53eb57c 100644 --- a/platform/crd-ctrlr/src/PROJECT +++ b/platform/crd-ctrlr/src/PROJECT @@ -28,4 +28,7 @@ resources: - group: batch kind: IpsecHost version: v1alpha1 +- group: batch + kind: IpsecSite + version: v1alpha1 version: "2" diff --git a/platform/crd-ctrlr/src/api/v1alpha1/bucket_permission_webhook.go b/platform/crd-ctrlr/src/api/v1alpha1/bucket_permission_webhook.go index adf9c11..0982260 100644 --- a/platform/crd-ctrlr/src/api/v1alpha1/bucket_permission_webhook.go +++ b/platform/crd-ctrlr/src/api/v1alpha1/bucket_permission_webhook.go @@ -45,7 +45,7 @@ func SetupBucketPermissionWebhookWithManager(mgr ctrl.Manager) error { return nil } -// +kubebuilder:webhook:path=/validate-sdewan-bucket-permission,mutating=false,failurePolicy=fail,groups="batch.sdewan.akraino.org",resources=mwan3policies;mwan3rules;firewallzones;firewallforwardings;firewallrules;firewallsnats;firewalldnats;ipsecproposals;ipsechosts,verbs=create;update;delete,versions=v1alpha1,name=validate-sdewan-bucket.akraino.org +// +kubebuilder:webhook:path=/validate-sdewan-bucket-permission,mutating=false,failurePolicy=fail,groups="batch.sdewan.akraino.org",resources=mwan3policies;mwan3rules;firewallzones;firewallforwardings;firewallrules;firewallsnats;firewalldnats;ipsecproposals;ipsechosts;ipsecsites,verbs=create;update;delete,versions=v1alpha1,name=validate-sdewan-bucket.akraino.org // bucketPermissionValidator validates Pods type bucketPermissionValidator struct { @@ -101,6 +101,8 @@ func (v *bucketPermissionValidator) Handle(ctx context.Context, req admission.Re obj = &IpsecProposal{} case "IpsecHost": obj = &IpsecHost{} + case "IpsecSite": + obj = &IpsecSite{} default: return admission.Errored( http.StatusBadRequest, diff --git a/platform/crd-ctrlr/src/api/v1alpha1/ipsecsite_types.go b/platform/crd-ctrlr/src/api/v1alpha1/ipsecsite_types.go new file mode 100644 index 0000000..f0ef2fb --- /dev/null +++ b/platform/crd-ctrlr/src/api/v1alpha1/ipsecsite_types.go @@ -0,0 +1,78 @@ +/* + +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 v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type SiteConnection struct { + Name string `json:"name"` + ConnectionType string `json:"conn_type"` + Mode string `json:"mode"` + LocalSubnet string `json:"local_subnet"` + LocalUpDown string `json:"local_updown,omitempty"` + LocalFirewall string `json:"local_firewall,omitempty"` + RemoteSubnet string `json:"remote_subnet,omitempty"` + RemoteSourceIp string `json:"remote_sourceip,omitempty"` + RemoteUpDown string `json:"remote_updown,omitempty"` + RemoteFirewall string `json:"remote_firewall,omitempty"` + CryptoProposal []string `json:"crypto_proposal,omitempty"` + Mark string `json:"mark,omitempty"` + IfId string `json:"if_id,omitempty"` +} + +// IpsecSiteSpec defines the desired state of IpsecSite +type IpsecSiteSpec struct { + Name string `json:"name,omitempty"` + Type string `json:"type,omitempty"` + Remote string `json:"remote"` + AuthenticationMethod string `json:"authentication_method"` + CryptoProposal []string `json:"crypto_proposal"` + LocalIdentifier string `json:"local_identifier,omitempty"` + RemoteIdentifier string `json:"remote_identifier,omitempty"` + ForceCryptoProposal string `json:"force_crypto_proposal,omitempty"` + PresharedKey string `json:"pre_shared_key,omitempty"` + LocalPublicCert string `json:"local_public_cert,omitempty"` + LocalPrivateCert string `json:"local_private_cert,omitempty"` + SharedCA string `json:"shared_ca,omitempty"` + Connections []SiteConnection `json:"connections"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status + +// IpsecSite is the Schema for the ipsecsites API +type IpsecSite struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec IpsecSiteSpec `json:"spec,omitempty"` + Status SdewanStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// IpsecSiteList contains a list of IpsecSite +type IpsecSiteList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []IpsecSite `json:"items"` +} + +func init() { + SchemeBuilder.Register(&IpsecSite{}, &IpsecSiteList{}) +} diff --git a/platform/crd-ctrlr/src/api/v1alpha1/label_validate_webhook.go b/platform/crd-ctrlr/src/api/v1alpha1/label_validate_webhook.go index 5fe404e..9332c87 100644 --- a/platform/crd-ctrlr/src/api/v1alpha1/label_validate_webhook.go +++ b/platform/crd-ctrlr/src/api/v1alpha1/label_validate_webhook.go @@ -42,7 +42,7 @@ func SetupLabelValidateWebhookWithManager(mgr ctrl.Manager) error { return nil } -// +kubebuilder:webhook:path=/validate-label,mutating=false,failurePolicy=fail,groups=apps;batch.sdewan.akraino.org,resources=deployments;mwan3policies;mwan3rules;firewallzones;firewallforwardings;firewallrules;firewallsnats;firewalldnats;ipsecproposals;ipsechosts,verbs=update,versions=v1;v1alpha1,name=validate-label.akraino.org +// +kubebuilder:webhook:path=/validate-label,mutating=false,failurePolicy=fail,groups=apps;batch.sdewan.akraino.org,resources=deployments;mwan3policies;mwan3rules;firewallzones;firewallforwardings;firewallrules;firewallsnats;firewalldnats;ipsecproposals;ipsechosts;ipsecsites,verbs=update,versions=v1;v1alpha1,name=validate-label.akraino.org type labelValidator struct { Client client.Client @@ -72,6 +72,8 @@ func (v *labelValidator) Handle(ctx context.Context, req admission.Request) admi obj = &IpsecProposal{} case "IpsecHost": obj = &IpsecHost{} + case "IpsecSite": + obj = &IpsecSite{} default: return admission.Errored( http.StatusBadRequest, diff --git a/platform/crd-ctrlr/src/api/v1alpha1/zz_generated.deepcopy.go b/platform/crd-ctrlr/src/api/v1alpha1/zz_generated.deepcopy.go index 29e7f04..07ce857 100644 --- a/platform/crd-ctrlr/src/api/v1alpha1/zz_generated.deepcopy.go +++ b/platform/crd-ctrlr/src/api/v1alpha1/zz_generated.deepcopy.go @@ -627,6 +627,92 @@ func (in *IpsecProposalSpec) DeepCopy() *IpsecProposalSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IpsecSite) DeepCopyInto(out *IpsecSite) { + *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 IpsecSite. +func (in *IpsecSite) DeepCopy() *IpsecSite { + if in == nil { + return nil + } + out := new(IpsecSite) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *IpsecSite) 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 *IpsecSiteList) DeepCopyInto(out *IpsecSiteList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]IpsecSite, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IpsecSiteList. +func (in *IpsecSiteList) DeepCopy() *IpsecSiteList { + if in == nil { + return nil + } + out := new(IpsecSiteList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *IpsecSiteList) 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 *IpsecSiteSpec) DeepCopyInto(out *IpsecSiteSpec) { + *out = *in + if in.CryptoProposal != nil { + in, out := &in.CryptoProposal, &out.CryptoProposal + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Connections != nil { + in, out := &in.Connections, &out.Connections + *out = make([]SiteConnection, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IpsecSiteSpec. +func (in *IpsecSiteSpec) DeepCopy() *IpsecSiteSpec { + if in == nil { + return nil + } + out := new(IpsecSiteSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Mwan3Policy) DeepCopyInto(out *Mwan3Policy) { *out = *in @@ -813,3 +899,23 @@ func (in *SdewanStatus) DeepCopy() *SdewanStatus { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SiteConnection) DeepCopyInto(out *SiteConnection) { + *out = *in + if in.CryptoProposal != nil { + in, out := &in.CryptoProposal, &out.CryptoProposal + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SiteConnection. +func (in *SiteConnection) DeepCopy() *SiteConnection { + if in == nil { + return nil + } + out := new(SiteConnection) + in.DeepCopyInto(out) + return out +} diff --git a/platform/crd-ctrlr/src/config/crd/bases/batch.sdewan.akraino.org_ipsecsites.yaml b/platform/crd-ctrlr/src/config/crd/bases/batch.sdewan.akraino.org_ipsecsites.yaml new file mode 100644 index 0000000..c7bfced --- /dev/null +++ b/platform/crd-ctrlr/src/config/crd/bases/batch.sdewan.akraino.org_ipsecsites.yaml @@ -0,0 +1,136 @@ + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.2.5 + creationTimestamp: null + name: ipsecsites.batch.sdewan.akraino.org +spec: + group: batch.sdewan.akraino.org + names: + kind: IpsecSite + listKind: IpsecSiteList + plural: ipsecsites + singular: ipsecsite + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + description: IpsecSite is the Schema for the ipsecsites 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/sig-architecture/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/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: IpsecSiteSpec defines the desired state of IpsecSite + properties: + authentication_method: + type: string + connections: + items: + properties: + conn_type: + type: string + crypto_proposal: + items: + type: string + type: array + if_id: + type: string + local_firewall: + type: string + local_subnet: + type: string + local_updown: + type: string + mark: + type: string + mode: + type: string + name: + type: string + remote_firewall: + type: string + remote_sourceip: + type: string + remote_subnet: + type: string + remote_updown: + type: string + required: + - conn_type + - local_subnet + - mode + - name + type: object + type: array + crypto_proposal: + items: + type: string + type: array + force_crypto_proposal: + type: string + local_identifier: + type: string + local_private_cert: + type: string + local_public_cert: + type: string + name: + type: string + pre_shared_key: + type: string + remote: + type: string + remote_identifier: + type: string + shared_ca: + type: string + type: + type: string + required: + - authentication_method + - connections + - crypto_proposal + - remote + type: object + status: + description: status subsource used for Sdewan rule CRDs + properties: + appliedGeneration: + format: int64 + type: integer + appliedTime: + format: date-time + type: string + message: + type: string + state: + type: string + required: + - state + type: object + type: object + version: v1alpha1 + versions: + - name: v1alpha1 + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/platform/crd-ctrlr/src/config/crd/kustomization.yaml b/platform/crd-ctrlr/src/config/crd/kustomization.yaml index 1a470d7..915b9c8 100644 --- a/platform/crd-ctrlr/src/config/crd/kustomization.yaml +++ b/platform/crd-ctrlr/src/config/crd/kustomization.yaml @@ -11,6 +11,7 @@ resources: - bases/batch.sdewan.akraino.org_firewallforwardings.yaml - bases/batch.sdewan.akraino.org_ipsecproposals.yaml - bases/batch.sdewan.akraino.org_ipsechosts.yaml +- bases/batch.sdewan.akraino.org_ipsecsites.yaml # +kubebuilder:scaffold:crdkustomizeresource patchesStrategicMerge: @@ -25,6 +26,7 @@ patchesStrategicMerge: #- patches/webhook_in_firewallforwardings.yaml #- patches/webhook_in_ipsecproposals.yaml #- patches/webhook_in_ipsechosts.yaml +#- patches/webhook_in_ipsecsites.yaml # +kubebuilder:scaffold:crdkustomizewebhookpatch # [CERTMANAGER] To enable webhook, uncomment all the sections with [CERTMANAGER] prefix. @@ -38,6 +40,7 @@ patchesStrategicMerge: #- patches/cainjection_in_firewallforwardings.yaml #- patches/cainjection_in_ipsecproposals.yaml #- patches/cainjection_in_ipsechosts.yaml +#- patches/cainjection_in_ipsecsites.yaml # +kubebuilder:scaffold:crdkustomizecainjectionpatch # the following config is for teaching kustomize how to do kustomization for CRDs. diff --git a/platform/crd-ctrlr/src/config/crd/patches/cainjection_in_ipsecsites.yaml b/platform/crd-ctrlr/src/config/crd/patches/cainjection_in_ipsecsites.yaml new file mode 100644 index 0000000..c7633b0 --- /dev/null +++ b/platform/crd-ctrlr/src/config/crd/patches/cainjection_in_ipsecsites.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: + cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) + name: ipsecsites.batch.sdewan.akraino.org diff --git a/platform/crd-ctrlr/src/config/crd/patches/webhook_in_ipsecsites.yaml b/platform/crd-ctrlr/src/config/crd/patches/webhook_in_ipsecsites.yaml new file mode 100644 index 0000000..8eab6c3 --- /dev/null +++ b/platform/crd-ctrlr/src/config/crd/patches/webhook_in_ipsecsites.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: ipsecsites.batch.sdewan.akraino.org +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/platform/crd-ctrlr/src/config/local/webhook_config.yaml b/platform/crd-ctrlr/src/config/local/webhook_config.yaml index d5025a5..d50877b 100644 --- a/platform/crd-ctrlr/src/config/local/webhook_config.yaml +++ b/platform/crd-ctrlr/src/config/local/webhook_config.yaml @@ -30,6 +30,7 @@ webhooks: - firewallzones - ipsechosts - ipsecproposals + - ipsecsites scope: '*' sideEffects: Unknown timeoutSeconds: 30 diff --git a/platform/crd-ctrlr/src/config/rbac/role.yaml b/platform/crd-ctrlr/src/config/rbac/role.yaml index 8248c87..88ddf81 100644 --- a/platform/crd-ctrlr/src/config/rbac/role.yaml +++ b/platform/crd-ctrlr/src/config/rbac/role.yaml @@ -162,6 +162,26 @@ rules: - get - patch - update +- apiGroups: + - batch.sdewan.akraino.org + resources: + - ipsecsites + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - batch.sdewan.akraino.org + resources: + - ipsecsites/status + verbs: + - get + - patch + - update - apiGroups: - batch.sdewan.akraino.org resources: diff --git a/platform/crd-ctrlr/src/config/samples/batch_v1alpha1_ipsecsite.yaml b/platform/crd-ctrlr/src/config/samples/batch_v1alpha1_ipsecsite.yaml new file mode 100644 index 0000000..7205625 --- /dev/null +++ b/platform/crd-ctrlr/src/config/samples/batch_v1alpha1_ipsecsite.yaml @@ -0,0 +1,29 @@ +--- +apiVersion: batch.sdewan.akraino.org/v1alpha1 +kind: IpsecSite +metadata: + name: ipsecsite + namespace: default + labels: + sdewanPurpose: cnf1 +spec: + name: siteA + type: "VTI-based" + remote: "%any" + pre_shared_key: test_key + authentication_method: psk + remote_identifier: host + local_identifier: Hub + crypto_proposal: + - ipsecproposal + force_crypto_proposal: "0" + connections: + - name: connA + conn_type: tunnel + mode: start + mark: "42" + remote_sourceip: "192.168.1.5-192.168.1.6" + local_subnet: 192.168.1.1/24,10.10.10.35/32 + crypto_proposal: + - ipsecproposal +... diff --git a/platform/crd-ctrlr/src/config/webhook/manifests.yaml b/platform/crd-ctrlr/src/config/webhook/manifests.yaml index a22fda8..e45e878 100644 --- a/platform/crd-ctrlr/src/config/webhook/manifests.yaml +++ b/platform/crd-ctrlr/src/config/webhook/manifests.yaml @@ -33,6 +33,7 @@ webhooks: - firewalldnats - ipsecproposals - ipsechosts + - ipsecsites - clientConfig: caBundle: Cg== service: @@ -61,3 +62,4 @@ webhooks: - firewalldnats - ipsecproposals - ipsechosts + - ipsecsites diff --git a/platform/crd-ctrlr/src/controllers/ipsecsite_controller.go b/platform/crd-ctrlr/src/controllers/ipsecsite_controller.go new file mode 100644 index 0000000..64a2b56 --- /dev/null +++ b/platform/crd-ctrlr/src/controllers/ipsecsite_controller.go @@ -0,0 +1,156 @@ +/* + +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 controllers + +import ( + "context" + "reflect" + + "github.com/go-logr/logr" + appsv1 "k8s.io/api/apps/v1" + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/builder" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/predicate" + + batchv1alpha1 "sdewan.akraino.org/sdewan/api/v1alpha1" + "sdewan.akraino.org/sdewan/openwrt" +) + +var ipsecSiteHandler = new(IpsecSiteHandler) + +type IpsecSiteHandler struct { +} + +func (m *IpsecSiteHandler) GetType() string { + return "IpsecSite" +} + +func (m *IpsecSiteHandler) GetName(instance runtime.Object) string { + site := instance.(*batchv1alpha1.IpsecSite) + return site.Name +} + +func (m *IpsecSiteHandler) GetFinalizer() string { + return "ipsec.site.finalizers.sdewan.akraino.org" +} + +func (m *IpsecSiteHandler) GetInstance(r client.Client, ctx context.Context, req ctrl.Request) (runtime.Object, error) { + instance := &batchv1alpha1.IpsecSite{} + err := r.Get(ctx, req.NamespacedName, instance) + return instance, err +} + +func (m *IpsecSiteHandler) Convert(instance runtime.Object, deployment appsv1.Deployment) (openwrt.IOpenWrtObject, error) { + site := instance.(*batchv1alpha1.IpsecSite) + numOfConn := len(site.Spec.Connections) + conn := site.Spec.Connections + openwrtConn := make([]openwrt.SdewanIpsecConnection, numOfConn) + for i := 0; i < numOfConn; i++ { + openwrtConn[i] = openwrt.SdewanIpsecConnection{ + Name: conn[i].Name, + ConnType: conn[i].ConnectionType, + Mode: conn[i].Mode, + LocalSubnet: conn[i].LocalSubnet, + LocalUpdown: conn[i].LocalUpDown, + LocalFirewall: conn[i].LocalFirewall, + RemoteSubnet: conn[i].RemoteSubnet, + RemoteSourceip: conn[i].RemoteSourceIp, + RemoteUpdown: conn[i].RemoteUpDown, + RemoteFirewall: conn[i].RemoteFirewall, + CryptoProposal: conn[i].CryptoProposal, + Mark: conn[i].Mark, + IfId: conn[i].IfId, + } + } + siteObject := openwrt.SdewanIpsecRemote{ + Name: site.Name, + Gateway: site.Spec.Remote, + Type: site.Spec.Type, + AuthenticationMethod: site.Spec.AuthenticationMethod, + PreSharedKey: site.Spec.PresharedKey, + LocalIdentifier: site.Spec.LocalIdentifier, + RemoteIdentifier: site.Spec.RemoteIdentifier, + CryptoProposal: site.Spec.CryptoProposal, + ForceCryptoProposal: site.Spec.ForceCryptoProposal, + LocalPublicCert: site.Spec.LocalPublicCert, + LocalPrivateCert: site.Spec.LocalPrivateCert, + SharedCa: site.Spec.SharedCA, + Connections: openwrtConn, + } + return &siteObject, nil +} + +func (m *IpsecSiteHandler) IsEqual(instance1 openwrt.IOpenWrtObject, instance2 openwrt.IOpenWrtObject) bool { + site1 := instance1.(*openwrt.SdewanIpsecRemote) + site2 := instance2.(*openwrt.SdewanIpsecRemote) + return reflect.DeepEqual(*site1, *site2) +} + +func (m *IpsecSiteHandler) GetObject(clientInfo *openwrt.OpenwrtClientInfo, name string) (openwrt.IOpenWrtObject, error) { + openwrtClient := openwrt.GetOpenwrtClient(*clientInfo) + ipsec := openwrt.IpsecClient{OpenwrtClient: openwrtClient} + ret, err := ipsec.GetRemote(name) + return ret, err +} + +func (m *IpsecSiteHandler) CreateObject(clientInfo *openwrt.OpenwrtClientInfo, instance openwrt.IOpenWrtObject) (openwrt.IOpenWrtObject, error) { + openwrtClient := openwrt.GetOpenwrtClient(*clientInfo) + ipsec := openwrt.IpsecClient{OpenwrtClient: openwrtClient} + site := instance.(*openwrt.SdewanIpsecRemote) + return ipsec.CreateRemote(*site) +} + +func (m *IpsecSiteHandler) UpdateObject(clientInfo *openwrt.OpenwrtClientInfo, instance openwrt.IOpenWrtObject) (openwrt.IOpenWrtObject, error) { + openwrtClient := openwrt.GetOpenwrtClient(*clientInfo) + ipsec := openwrt.IpsecClient{OpenwrtClient: openwrtClient} + site := instance.(*openwrt.SdewanIpsecRemote) + return ipsec.UpdateRemote(*site) +} + +func (m *IpsecSiteHandler) DeleteObject(clientInfo *openwrt.OpenwrtClientInfo, name string) error { + openwrtClient := openwrt.GetOpenwrtClient(*clientInfo) + ipsec := openwrt.IpsecClient{OpenwrtClient: openwrtClient} + return ipsec.DeleteRemote(name) +} + +func (m *IpsecSiteHandler) Restart(clientInfo *openwrt.OpenwrtClientInfo) (bool, error) { + openwrtClient := openwrt.GetOpenwrtClient(*clientInfo) + service := openwrt.ServiceClient{OpenwrtClient: openwrtClient} + return service.ExecuteService("ipsec", "restart") +} + +// IpsecSiteReconciler reconciles a IpsecSite object +type IpsecSiteReconciler struct { + client.Client + Log logr.Logger + Scheme *runtime.Scheme +} + +// +kubebuilder:rbac:groups=batch.sdewan.akraino.org,resources=ipsecsites,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=batch.sdewan.akraino.org,resources=ipsecsites/status,verbs=get;update;patch + +func (r *IpsecSiteReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { + return ProcessReconcile(r, r.Log, req, ipsecSiteHandler) +} + +func (r *IpsecSiteReconciler) SetupWithManager(mgr ctrl.Manager) error { + ps := builder.WithPredicates(predicate.GenerationChangedPredicate{}) + return ctrl.NewControllerManagedBy(mgr). + For(&batchv1alpha1.IpsecSite{}, ps). + Complete(r) +} diff --git a/platform/crd-ctrlr/src/controllers/suite_test.go b/platform/crd-ctrlr/src/controllers/suite_test.go index 500a585..fd96072 100644 --- a/platform/crd-ctrlr/src/controllers/suite_test.go +++ b/platform/crd-ctrlr/src/controllers/suite_test.go @@ -86,6 +86,9 @@ var _ = BeforeSuite(func(done Done) { err = batchv1alpha1.AddToScheme(scheme.Scheme) Expect(err).NotTo(HaveOccurred()) + err = batchv1alpha1.AddToScheme(scheme.Scheme) + Expect(err).NotTo(HaveOccurred()) + // +kubebuilder:scaffold:scheme k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) diff --git a/platform/crd-ctrlr/src/main.go b/platform/crd-ctrlr/src/main.go index 0a5cc24..4709d16 100644 --- a/platform/crd-ctrlr/src/main.go +++ b/platform/crd-ctrlr/src/main.go @@ -201,6 +201,14 @@ func main() { setupLog.Error(err, "unable to create webhook", "webhook", "CNFLabelWebhook") os.Exit(1) } + if err = (&controllers.IpsecSiteReconciler{ + Client: mgr.GetClient(), + Log: ctrl.Log.WithName("controllers").WithName("IpsecSite"), + Scheme: mgr.GetScheme(), + }).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "IpsecSite") + os.Exit(1) + } // +kubebuilder:scaffold:builder setupLog.Info("starting manager")