From e109a80f986f9e5aa9a7ce8fdc76075388fd5b8a Mon Sep 17 00:00:00 2001 From: vaspahomov Date: Wed, 29 Sep 2021 17:55:23 +0500 Subject: [PATCH] Add Application, Role, Group, RoleAssignment support --- apis/azure.go | 2 + apis/rbac/rbac.go | 18 + apis/rbac/v1alpha1/doc.go | 21 + apis/rbac/v1alpha1/referencers.go | 127 ++++ apis/rbac/v1alpha1/register.go | 74 +++ apis/rbac/v1alpha1/types.go | 302 ++++++++++ apis/rbac/v1alpha1/zz_generated.deepcopy.go | 566 ++++++++++++++++++ apis/rbac/v1alpha1/zz_generated.managed.go | 301 ++++++++++ .../rbac/v1alpha1/zz_generated.managedlist.go | 66 ++ examples/rbac/application.yaml | 10 + examples/rbac/group.yaml | 6 + examples/rbac/role.yaml | 6 + examples/rbac/roleassignment.yaml | 25 + examples/rbac/serviceprincipal.yaml | 8 + .../rbac.azure.crossplane.io_adgroups.yaml | 131 ++++ ...rbac.azure.crossplane.io_applications.yaml | 149 +++++ ...c.azure.crossplane.io_roleassignments.yaml | 212 +++++++ .../crds/rbac.azure.crossplane.io_roles.yaml | 131 ++++ ...azure.crossplane.io_serviceprincipals.yaml | 159 +++++ pkg/clients/azure.go | 15 + pkg/controller/azure.go | 6 + pkg/controller/rbac/application/managed.go | 195 ++++++ pkg/controller/rbac/roleassignment/managed.go | 153 +++++ .../rbac/serviceprincipal/managed.go | 158 +++++ 24 files changed, 2841 insertions(+) create mode 100644 apis/rbac/rbac.go create mode 100644 apis/rbac/v1alpha1/doc.go create mode 100644 apis/rbac/v1alpha1/referencers.go create mode 100644 apis/rbac/v1alpha1/register.go create mode 100644 apis/rbac/v1alpha1/types.go create mode 100644 apis/rbac/v1alpha1/zz_generated.deepcopy.go create mode 100644 apis/rbac/v1alpha1/zz_generated.managed.go create mode 100644 apis/rbac/v1alpha1/zz_generated.managedlist.go create mode 100644 examples/rbac/application.yaml create mode 100644 examples/rbac/group.yaml create mode 100644 examples/rbac/role.yaml create mode 100644 examples/rbac/roleassignment.yaml create mode 100644 examples/rbac/serviceprincipal.yaml create mode 100644 package/crds/rbac.azure.crossplane.io_adgroups.yaml create mode 100644 package/crds/rbac.azure.crossplane.io_applications.yaml create mode 100644 package/crds/rbac.azure.crossplane.io_roleassignments.yaml create mode 100644 package/crds/rbac.azure.crossplane.io_roles.yaml create mode 100644 package/crds/rbac.azure.crossplane.io_serviceprincipals.yaml create mode 100644 pkg/controller/rbac/application/managed.go create mode 100644 pkg/controller/rbac/roleassignment/managed.go create mode 100644 pkg/controller/rbac/serviceprincipal/managed.go diff --git a/apis/azure.go b/apis/azure.go index f6372398..2134ab2b 100644 --- a/apis/azure.go +++ b/apis/azure.go @@ -25,6 +25,7 @@ import ( databasev1alpha3 "github.com/crossplane/provider-azure/apis/database/v1alpha3" databasev1beta1 "github.com/crossplane/provider-azure/apis/database/v1beta1" networkv1alpha3 "github.com/crossplane/provider-azure/apis/network/v1alpha3" + rbacv1alpha1 "github.com/crossplane/provider-azure/apis/rbac/v1alpha1" storagev1alpha3 "github.com/crossplane/provider-azure/apis/storage/v1alpha3" azurev1alpha3 "github.com/crossplane/provider-azure/apis/v1alpha3" azurev1beta1 "github.com/crossplane/provider-azure/apis/v1beta1" @@ -40,6 +41,7 @@ func init() { databasev1alpha3.SchemeBuilder.AddToScheme, databasev1beta1.SchemeBuilder.AddToScheme, networkv1alpha3.SchemeBuilder.AddToScheme, + rbacv1alpha1.SchemeBuilder.AddToScheme, storagev1alpha3.SchemeBuilder.AddToScheme, ) } diff --git a/apis/rbac/rbac.go b/apis/rbac/rbac.go new file mode 100644 index 00000000..c113ae50 --- /dev/null +++ b/apis/rbac/rbac.go @@ -0,0 +1,18 @@ +/* +Copyright 2021 The Crossplane 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 rbac contains Azure rbac API versions +package rbac diff --git a/apis/rbac/v1alpha1/doc.go b/apis/rbac/v1alpha1/doc.go new file mode 100644 index 00000000..72bea8ff --- /dev/null +++ b/apis/rbac/v1alpha1/doc.go @@ -0,0 +1,21 @@ +/* +Copyright 2019 The Crossplane 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 v1alpha1 contains managed resources for Azure rbac. +// +kubebuilder:object:generate=true +// +groupName=rbac.azure.crossplane.io +// +versionName=v1alpha1 +package v1alpha1 diff --git a/apis/rbac/v1alpha1/referencers.go b/apis/rbac/v1alpha1/referencers.go new file mode 100644 index 00000000..d987b830 --- /dev/null +++ b/apis/rbac/v1alpha1/referencers.go @@ -0,0 +1,127 @@ +/* +Copyright 2019 The Crossplane 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 v1alpha1 + +import ( + "context" + + "github.com/pkg/errors" + + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/crossplane/crossplane-runtime/pkg/reference" + "github.com/crossplane/crossplane-runtime/pkg/resource" +) + +// RoleID - reference to id of role +func RoleID() reference.ExtractValueFn { + return func(mg resource.Managed) string { + s, ok := mg.(*Role) + if !ok { + return "" + } + return s.Spec.RoleID + } +} + +// ADGroupID - reference to id of ad group +func ADGroupID() reference.ExtractValueFn { + return func(mg resource.Managed) string { + s, ok := mg.(*ADGroup) + if !ok { + return "" + } + return s.Spec.GroupID + } +} + +// ResolveReferences of this ServicePrincipal +func (mg *ServicePrincipal) ResolveReferences(ctx context.Context, c client.Reader) error { + r := reference.NewAPIResolver(c, mg) + + // Resolve spec.applicationID + rsp, err := r.Resolve(ctx, reference.ResolutionRequest{ + CurrentValue: mg.Spec.ApplicationID, + Reference: mg.Spec.ApplicationIDRef, + Selector: mg.Spec.ApplicationIDSelector, + To: reference.To{Managed: &Application{}, List: &ApplicationList{}}, + Extract: reference.ExternalName(), + }) + if err != nil { + return errors.Wrap(err, "spec.applicationID") + } + mg.Spec.ApplicationID = rsp.ResolvedValue + mg.Spec.ApplicationIDRef = rsp.ResolvedReference + + return nil +} + +// ResolveReferences of this ServicePrincipal +func (mg *RoleAssignment) ResolveReferences(ctx context.Context, c client.Reader) error { + r := reference.NewAPIResolver(c, mg) + + switch mg.Spec.PrincipalType { + case "": + fallthrough + case "service-principal": + // Resolve spec.principalID + rsp, err := r.Resolve(ctx, reference.ResolutionRequest{ + CurrentValue: mg.Spec.PrincipalID, + Reference: mg.Spec.GroupIDRef, + Selector: mg.Spec.GroupIDSelector, + To: reference.To{Managed: &ServicePrincipal{}, List: &ServicePrincipalList{}}, + Extract: reference.ExternalName(), + }) + if err != nil { + return errors.Wrap(err, "spec.principalID") + } + mg.Spec.PrincipalID = rsp.ResolvedValue + mg.Spec.PrincipalIDRef = rsp.ResolvedReference + case "group": + // Resolve spec.principalID + rsp, err := r.Resolve(ctx, reference.ResolutionRequest{ + CurrentValue: mg.Spec.PrincipalID, + Reference: mg.Spec.GroupIDRef, + Selector: mg.Spec.GroupIDSelector, + To: reference.To{Managed: &ADGroup{}, List: &ADGroupList{}}, + Extract: ADGroupID(), + }) + if err != nil { + return errors.Wrap(err, "spec.principalID") + } + mg.Spec.PrincipalID = rsp.ResolvedValue + mg.Spec.GroupIDRef = rsp.ResolvedReference + default: + return errors.New("invalid spec.principalType should be one of: ['group', 'service-principal']") + } + + // Resolve spec.roleID + rsp, err := r.Resolve(ctx, reference.ResolutionRequest{ + CurrentValue: mg.Spec.RoleID, + Reference: mg.Spec.RoleIDRef, + Selector: mg.Spec.RoleIDSelector, + To: reference.To{Managed: &Role{}, List: &RoleList{}}, + Extract: RoleID(), + }) + if err != nil { + return errors.Wrap(err, "spec.roleID") + } + mg.Spec.RoleID = rsp.ResolvedValue + mg.Spec.RoleIDRef = rsp.ResolvedReference + + return nil +} diff --git a/apis/rbac/v1alpha1/register.go b/apis/rbac/v1alpha1/register.go new file mode 100644 index 00000000..af89d01f --- /dev/null +++ b/apis/rbac/v1alpha1/register.go @@ -0,0 +1,74 @@ +/* +Copyright 2019 The Crossplane 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 v1alpha1 + +import ( + "reflect" + + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +// Package type metadata. +const ( + Group = "rbac.azure.crossplane.io" + Version = "v1alpha1" +) + +var ( + // SchemeGroupVersion is group version used to register these objects + SchemeGroupVersion = schema.GroupVersion{Group: Group, Version: Version} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion} +) + +// Application type metadata. +var ( + ApplicationKind = reflect.TypeOf(Application{}).Name() + ApplicationGroupKind = schema.GroupKind{Group: Group, Kind: ApplicationKind}.String() + ApplicationKindAPIVersion = ApplicationKind + "." + SchemeGroupVersion.String() + ApplicationGroupVersionKind = SchemeGroupVersion.WithKind(ApplicationKind) + + ServicePrincipalKind = reflect.TypeOf(ServicePrincipal{}).Name() + ServicePrincipalGroupKind = schema.GroupKind{Group: Group, Kind: ServicePrincipalKind}.String() + ServicePrincipalKindAPIVersion = ServicePrincipalKind + "." + SchemeGroupVersion.String() + ServicePrincipalGroupVersionKind = SchemeGroupVersion.WithKind(ServicePrincipalKind) + + RoleAssignmentKind = reflect.TypeOf(RoleAssignment{}).Name() + RoleAssignmentGroupKind = schema.GroupKind{Group: Group, Kind: RoleAssignmentKind}.String() + RoleAssignmentKindAPIVersion = RoleAssignmentKind + "." + SchemeGroupVersion.String() + RoleAssignmentGroupVersionKind = SchemeGroupVersion.WithKind(RoleAssignmentKind) + + RoleKind = reflect.TypeOf(Role{}).Name() + RoleGroupKind = schema.GroupKind{Group: Group, Kind: RoleKind}.String() + RoleKindAPIVersion = RoleKind + "." + SchemeGroupVersion.String() + RoleGroupVersionKind = SchemeGroupVersion.WithKind(RoleKind) + + ADGroupKind = reflect.TypeOf(ADGroup{}).Name() + ADGroupGroupKind = schema.GroupKind{Group: Group, Kind: ADGroupKind}.String() + ADGroupKindAPIVersion = ADGroupKind + "." + SchemeGroupVersion.String() + ADGroupGroupVersionKind = SchemeGroupVersion.WithKind(ADGroupKind) +) + +func init() { + SchemeBuilder.Register(&Application{}, &ApplicationList{}) + SchemeBuilder.Register(&ServicePrincipal{}, &ServicePrincipalList{}) + SchemeBuilder.Register(&RoleAssignment{}, &RoleAssignmentList{}) + SchemeBuilder.Register(&Role{}, &RoleList{}) + SchemeBuilder.Register(&ADGroup{}, &ADGroupList{}) +} diff --git a/apis/rbac/v1alpha1/types.go b/apis/rbac/v1alpha1/types.go new file mode 100644 index 00000000..80df30bc --- /dev/null +++ b/apis/rbac/v1alpha1/types.go @@ -0,0 +1,302 @@ +/* +Copyright 2019 The Crossplane 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 v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1" +) + +// ApplicationParameters parameters for an application. +type ApplicationParameters struct { + // AvailableToOtherTenants - Whether the application is available to other tenants. + // +optional + // +immutable + AvailableToOtherTenants *bool `json:"availableToOtherTenants,omitempty"` + + // DisplayName - The display name of the application. + // +optional + // +immutable + DisplayName *string `json:"displayName,omitempty"` + + // Homepage - The home page of the application. + // +optional + // +immutable + Homepage *string `json:"homepage,omitempty"` + + // IdentifierUris - A collection of URIs for the application. + // +optional + // +immutable + IdentifierUris *[]string `json:"identifierUris,omitempty"` +} + +// An ApplicationSpec defines the desired state of an Application. +type ApplicationSpec struct { + xpv1.ResourceSpec `json:",inline"` + + // ApplicationParameters parameters for an application. + ApplicationParameters `json:",inline"` +} + +// An ApplicationStatus represents the observed state of an Application. +type ApplicationStatus struct { + xpv1.ResourceStatus `json:",inline"` + + // ApplicationID - The application ID. + ApplicationID string `json:"applicationID,omitempty"` +} + +// +kubebuilder:object:root=true + +// A Application is a managed resource that represents an Application. +// +kubebuilder:printcolumn:name="READY",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].status" +// +kubebuilder:printcolumn:name="SYNCED",type="string",JSONPath=".status.conditions[?(@.type=='Synced')].status" +// +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp" +// +kubebuilder:subresource:status +// +kubebuilder:resource:scope=Cluster,categories={crossplane,managed,azure} +type Application struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec ApplicationSpec `json:"spec"` + Status ApplicationStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// ApplicationList contains a list of Application items +type ApplicationList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Application `json:"items"` +} + +// An ServicePrincipalSpec defines the desired state of an ServicePrincipal. +type ServicePrincipalSpec struct { + xpv1.ResourceSpec `json:",inline"` + + // ApplicationID - The application ID. + // +optional + ApplicationID string `json:"applicationID,omitempty"` + + // ApplicationIDRef - A reference to the Application id. + // +optional + // +immutable + ApplicationIDRef *xpv1.Reference `json:"applicationIDRef,omitempty"` + + // ApplicationIDSelector - Select a reference to the Application id. + // +immutable + ApplicationIDSelector *xpv1.Selector `json:"applicationIDSelector,omitempty"` + + // AccountEnabled - whether or not the service principal account is enabled + // +optional + // +immutable + AccountEnabled *bool `json:"accountEnabled,omitempty"` +} + +// An ServicePrincipalStatus represents the observed state of an ServicePrincipal. +type ServicePrincipalStatus struct { + xpv1.ResourceStatus `json:",inline"` +} + +// +kubebuilder:object:root=true + +// A ServicePrincipal is a managed resource that represents an ServicePrincipal. +// +kubebuilder:printcolumn:name="READY",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].status" +// +kubebuilder:printcolumn:name="SYNCED",type="string",JSONPath=".status.conditions[?(@.type=='Synced')].status" +// +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp" +// +kubebuilder:subresource:status +// +kubebuilder:resource:scope=Cluster,categories={crossplane,managed,azure} +type ServicePrincipal struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec ServicePrincipalSpec `json:"spec"` + Status ServicePrincipalStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// ServicePrincipalList contains a list of ServicePrincipal items +type ServicePrincipalList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ServicePrincipal `json:"items"` +} + +// An RoleAssignmentSpec defines the desired state of an RoleAssignment. +type RoleAssignmentSpec struct { + xpv1.ResourceSpec `json:",inline"` + + // PrincipalType - type of principal oneof: ['group', 'service-principal'] + // +immutable + // +kubebuilder:validation:Enum=group;service-principal + // +kubebuilder:validation:Required + PrincipalType string `json:"principalType,omitempty"` + + // PrincipalID - The principal ID assigned to the role. + // This maps to the ID inside the Active Directory. + // It can point to a user, service principal, or security group. + // +optional + PrincipalID string `json:"principalID,omitempty"` + + // PrincipalIDRef - A reference to the Principal id. + // +optional + // +immutable + PrincipalIDRef *xpv1.Reference `json:"principalIDRef,omitempty"` + + // PrincipalIDRef - Select a reference to the Principal id. + // +immutable + PrincipalIDSelector *xpv1.Selector `json:"principalIDSelector,omitempty"` + + // GroupIDRef - A reference to the Group id. + // +optional + // +immutable + GroupIDRef *xpv1.Reference `json:"groupIDRef,omitempty"` + + // GroupIDSelector - Select a reference to the Group id. + // +immutable + GroupIDSelector *xpv1.Selector `json:"groupIDSelector,omitempty"` + + // RoleID - The role definition ID. + // +optional + // +kubebuilder:validation:Required + RoleID string `json:"roleID,omitempty"` + + // RoleIDRef - A reference to the Role id. + // +optional + // +immutable + RoleIDRef *xpv1.Reference `json:"roleIDRef,omitempty"` + + // RoleIDSelector - Select a reference to the Role id. + // +immutable + RoleIDSelector *xpv1.Selector `json:"roleIDSelector,omitempty"` + + // Scope - The role assignment scope. + // +immutable + // +kubebuilder:validation:Required + Scope string `json:"scope"` +} + +// An RoleAssignmentStatus represents the observed state of an RoleAssignment. +type RoleAssignmentStatus struct { + xpv1.ResourceStatus `json:",inline"` +} + +// +kubebuilder:object:root=true + +// A RoleAssignment is a managed resource that represents an RoleAssignment. +// +kubebuilder:printcolumn:name="READY",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].status" +// +kubebuilder:printcolumn:name="SYNCED",type="string",JSONPath=".status.conditions[?(@.type=='Synced')].status" +// +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp" +// +kubebuilder:subresource:status +// +kubebuilder:resource:scope=Cluster,categories={crossplane,managed,azure} +type RoleAssignment struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec RoleAssignmentSpec `json:"spec"` + Status RoleAssignmentStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// RoleAssignmentList contains a list of RoleAssignment items +type RoleAssignmentList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []RoleAssignment `json:"items"` +} + +// Role and ADGroup are only CRDs and has no reconcile controller + +// An RoleSpec defines the desired state of an Role. +type RoleSpec struct { + xpv1.ResourceSpec `json:",inline"` + + // RoleID - The role definition ID. + // +kubebuilder:validation:Required + RoleID string `json:"roleID"` +} + +// An RoleStatus represents the observed state of an Role. +type RoleStatus struct { + xpv1.ResourceStatus `json:",inline"` +} + +// +kubebuilder:object:root=true + +// A Role is a resource that represents an Role. +// +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp" +// +kubebuilder:subresource:status +// +kubebuilder:resource:scope=Cluster,categories={crossplane,managed,azure} +type Role struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec RoleSpec `json:"spec"` + Status RoleStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// RoleList contains a list of Role items +type RoleList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Role `json:"items"` +} + +// An ADGroupSpec defines the desired state of an ADGroup. +type ADGroupSpec struct { + xpv1.ResourceSpec `json:",inline"` + + // GroupID - ID of ActiveDirectory group. + // +kubebuilder:validation:Required + GroupID string `json:"groupID"` +} + +// An ADGroupStatus represents the observed state of an ADGroup. +type ADGroupStatus struct { + xpv1.ResourceStatus `json:",inline"` +} + +// Role is only CRD and have no reconcile controller + +// +kubebuilder:object:root=true + +// A ADGroup is a resource that represents an ADGroup. +// +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp" +// +kubebuilder:subresource:status +// +kubebuilder:resource:scope=Cluster,categories={crossplane,managed,azure} +type ADGroup struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec ADGroupSpec `json:"spec"` + Status ADGroupStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// ADGroupList contains a list of ADGroup items +type ADGroupList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ADGroup `json:"items"` +} diff --git a/apis/rbac/v1alpha1/zz_generated.deepcopy.go b/apis/rbac/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 00000000..660a9548 --- /dev/null +++ b/apis/rbac/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,566 @@ +// +build !ignore_autogenerated + +/* +Copyright 2019 The Crossplane 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. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "github.com/crossplane/crossplane-runtime/apis/common/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 *ADGroup) DeepCopyInto(out *ADGroup) { + *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 ADGroup. +func (in *ADGroup) DeepCopy() *ADGroup { + if in == nil { + return nil + } + out := new(ADGroup) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ADGroup) 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 *ADGroupList) DeepCopyInto(out *ADGroupList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ADGroup, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ADGroupList. +func (in *ADGroupList) DeepCopy() *ADGroupList { + if in == nil { + return nil + } + out := new(ADGroupList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ADGroupList) 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 *ADGroupSpec) DeepCopyInto(out *ADGroupSpec) { + *out = *in + in.ResourceSpec.DeepCopyInto(&out.ResourceSpec) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ADGroupSpec. +func (in *ADGroupSpec) DeepCopy() *ADGroupSpec { + if in == nil { + return nil + } + out := new(ADGroupSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ADGroupStatus) DeepCopyInto(out *ADGroupStatus) { + *out = *in + in.ResourceStatus.DeepCopyInto(&out.ResourceStatus) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ADGroupStatus. +func (in *ADGroupStatus) DeepCopy() *ADGroupStatus { + if in == nil { + return nil + } + out := new(ADGroupStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Application) DeepCopyInto(out *Application) { + *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 Application. +func (in *Application) DeepCopy() *Application { + if in == nil { + return nil + } + out := new(Application) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Application) 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 *ApplicationList) DeepCopyInto(out *ApplicationList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Application, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationList. +func (in *ApplicationList) DeepCopy() *ApplicationList { + if in == nil { + return nil + } + out := new(ApplicationList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ApplicationList) 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 *ApplicationParameters) DeepCopyInto(out *ApplicationParameters) { + *out = *in + if in.AvailableToOtherTenants != nil { + in, out := &in.AvailableToOtherTenants, &out.AvailableToOtherTenants + *out = new(bool) + **out = **in + } + if in.DisplayName != nil { + in, out := &in.DisplayName, &out.DisplayName + *out = new(string) + **out = **in + } + if in.Homepage != nil { + in, out := &in.Homepage, &out.Homepage + *out = new(string) + **out = **in + } + if in.IdentifierUris != nil { + in, out := &in.IdentifierUris, &out.IdentifierUris + *out = new([]string) + if **in != nil { + in, out := *in, *out + *out = make([]string, len(*in)) + copy(*out, *in) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationParameters. +func (in *ApplicationParameters) DeepCopy() *ApplicationParameters { + if in == nil { + return nil + } + out := new(ApplicationParameters) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApplicationSpec) DeepCopyInto(out *ApplicationSpec) { + *out = *in + in.ResourceSpec.DeepCopyInto(&out.ResourceSpec) + in.ApplicationParameters.DeepCopyInto(&out.ApplicationParameters) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationSpec. +func (in *ApplicationSpec) DeepCopy() *ApplicationSpec { + if in == nil { + return nil + } + out := new(ApplicationSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApplicationStatus) DeepCopyInto(out *ApplicationStatus) { + *out = *in + in.ResourceStatus.DeepCopyInto(&out.ResourceStatus) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationStatus. +func (in *ApplicationStatus) DeepCopy() *ApplicationStatus { + if in == nil { + return nil + } + out := new(ApplicationStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Role) DeepCopyInto(out *Role) { + *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 Role. +func (in *Role) DeepCopy() *Role { + if in == nil { + return nil + } + out := new(Role) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Role) 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 *RoleAssignment) DeepCopyInto(out *RoleAssignment) { + *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 RoleAssignment. +func (in *RoleAssignment) DeepCopy() *RoleAssignment { + if in == nil { + return nil + } + out := new(RoleAssignment) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *RoleAssignment) 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 *RoleAssignmentList) DeepCopyInto(out *RoleAssignmentList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]RoleAssignment, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RoleAssignmentList. +func (in *RoleAssignmentList) DeepCopy() *RoleAssignmentList { + if in == nil { + return nil + } + out := new(RoleAssignmentList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *RoleAssignmentList) 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 *RoleAssignmentSpec) DeepCopyInto(out *RoleAssignmentSpec) { + *out = *in + in.ResourceSpec.DeepCopyInto(&out.ResourceSpec) + if in.PrincipalIDRef != nil { + in, out := &in.PrincipalIDRef, &out.PrincipalIDRef + *out = new(v1.Reference) + **out = **in + } + if in.PrincipalIDSelector != nil { + in, out := &in.PrincipalIDSelector, &out.PrincipalIDSelector + *out = new(v1.Selector) + (*in).DeepCopyInto(*out) + } + if in.GroupIDRef != nil { + in, out := &in.GroupIDRef, &out.GroupIDRef + *out = new(v1.Reference) + **out = **in + } + if in.GroupIDSelector != nil { + in, out := &in.GroupIDSelector, &out.GroupIDSelector + *out = new(v1.Selector) + (*in).DeepCopyInto(*out) + } + if in.RoleIDRef != nil { + in, out := &in.RoleIDRef, &out.RoleIDRef + *out = new(v1.Reference) + **out = **in + } + if in.RoleIDSelector != nil { + in, out := &in.RoleIDSelector, &out.RoleIDSelector + *out = new(v1.Selector) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RoleAssignmentSpec. +func (in *RoleAssignmentSpec) DeepCopy() *RoleAssignmentSpec { + if in == nil { + return nil + } + out := new(RoleAssignmentSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RoleAssignmentStatus) DeepCopyInto(out *RoleAssignmentStatus) { + *out = *in + in.ResourceStatus.DeepCopyInto(&out.ResourceStatus) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RoleAssignmentStatus. +func (in *RoleAssignmentStatus) DeepCopy() *RoleAssignmentStatus { + if in == nil { + return nil + } + out := new(RoleAssignmentStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RoleList) DeepCopyInto(out *RoleList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Role, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RoleList. +func (in *RoleList) DeepCopy() *RoleList { + if in == nil { + return nil + } + out := new(RoleList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *RoleList) 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 *RoleSpec) DeepCopyInto(out *RoleSpec) { + *out = *in + in.ResourceSpec.DeepCopyInto(&out.ResourceSpec) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RoleSpec. +func (in *RoleSpec) DeepCopy() *RoleSpec { + if in == nil { + return nil + } + out := new(RoleSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RoleStatus) DeepCopyInto(out *RoleStatus) { + *out = *in + in.ResourceStatus.DeepCopyInto(&out.ResourceStatus) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RoleStatus. +func (in *RoleStatus) DeepCopy() *RoleStatus { + if in == nil { + return nil + } + out := new(RoleStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServicePrincipal) DeepCopyInto(out *ServicePrincipal) { + *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 ServicePrincipal. +func (in *ServicePrincipal) DeepCopy() *ServicePrincipal { + if in == nil { + return nil + } + out := new(ServicePrincipal) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ServicePrincipal) 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 *ServicePrincipalList) DeepCopyInto(out *ServicePrincipalList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ServicePrincipal, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServicePrincipalList. +func (in *ServicePrincipalList) DeepCopy() *ServicePrincipalList { + if in == nil { + return nil + } + out := new(ServicePrincipalList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ServicePrincipalList) 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 *ServicePrincipalSpec) DeepCopyInto(out *ServicePrincipalSpec) { + *out = *in + in.ResourceSpec.DeepCopyInto(&out.ResourceSpec) + if in.ApplicationIDRef != nil { + in, out := &in.ApplicationIDRef, &out.ApplicationIDRef + *out = new(v1.Reference) + **out = **in + } + if in.ApplicationIDSelector != nil { + in, out := &in.ApplicationIDSelector, &out.ApplicationIDSelector + *out = new(v1.Selector) + (*in).DeepCopyInto(*out) + } + if in.AccountEnabled != nil { + in, out := &in.AccountEnabled, &out.AccountEnabled + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServicePrincipalSpec. +func (in *ServicePrincipalSpec) DeepCopy() *ServicePrincipalSpec { + if in == nil { + return nil + } + out := new(ServicePrincipalSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServicePrincipalStatus) DeepCopyInto(out *ServicePrincipalStatus) { + *out = *in + in.ResourceStatus.DeepCopyInto(&out.ResourceStatus) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServicePrincipalStatus. +func (in *ServicePrincipalStatus) DeepCopy() *ServicePrincipalStatus { + if in == nil { + return nil + } + out := new(ServicePrincipalStatus) + in.DeepCopyInto(out) + return out +} diff --git a/apis/rbac/v1alpha1/zz_generated.managed.go b/apis/rbac/v1alpha1/zz_generated.managed.go new file mode 100644 index 00000000..c67d3d08 --- /dev/null +++ b/apis/rbac/v1alpha1/zz_generated.managed.go @@ -0,0 +1,301 @@ +/* +Copyright 2019 The Crossplane 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. +*/ + +// Code generated by angryjet. DO NOT EDIT. + +package v1alpha1 + +import xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1" + +// GetCondition of this ADGroup. +func (mg *ADGroup) GetCondition(ct xpv1.ConditionType) xpv1.Condition { + return mg.Status.GetCondition(ct) +} + +// GetDeletionPolicy of this ADGroup. +func (mg *ADGroup) GetDeletionPolicy() xpv1.DeletionPolicy { + return mg.Spec.DeletionPolicy +} + +// GetProviderConfigReference of this ADGroup. +func (mg *ADGroup) GetProviderConfigReference() *xpv1.Reference { + return mg.Spec.ProviderConfigReference +} + +/* +GetProviderReference of this ADGroup. +Deprecated: Use GetProviderConfigReference. +*/ +func (mg *ADGroup) GetProviderReference() *xpv1.Reference { + return mg.Spec.ProviderReference +} + +// GetWriteConnectionSecretToReference of this ADGroup. +func (mg *ADGroup) GetWriteConnectionSecretToReference() *xpv1.SecretReference { + return mg.Spec.WriteConnectionSecretToReference +} + +// SetConditions of this ADGroup. +func (mg *ADGroup) SetConditions(c ...xpv1.Condition) { + mg.Status.SetConditions(c...) +} + +// SetDeletionPolicy of this ADGroup. +func (mg *ADGroup) SetDeletionPolicy(r xpv1.DeletionPolicy) { + mg.Spec.DeletionPolicy = r +} + +// SetProviderConfigReference of this ADGroup. +func (mg *ADGroup) SetProviderConfigReference(r *xpv1.Reference) { + mg.Spec.ProviderConfigReference = r +} + +/* +SetProviderReference of this ADGroup. +Deprecated: Use SetProviderConfigReference. +*/ +func (mg *ADGroup) SetProviderReference(r *xpv1.Reference) { + mg.Spec.ProviderReference = r +} + +// SetWriteConnectionSecretToReference of this ADGroup. +func (mg *ADGroup) SetWriteConnectionSecretToReference(r *xpv1.SecretReference) { + mg.Spec.WriteConnectionSecretToReference = r +} + +// GetCondition of this Application. +func (mg *Application) GetCondition(ct xpv1.ConditionType) xpv1.Condition { + return mg.Status.GetCondition(ct) +} + +// GetDeletionPolicy of this Application. +func (mg *Application) GetDeletionPolicy() xpv1.DeletionPolicy { + return mg.Spec.DeletionPolicy +} + +// GetProviderConfigReference of this Application. +func (mg *Application) GetProviderConfigReference() *xpv1.Reference { + return mg.Spec.ProviderConfigReference +} + +/* +GetProviderReference of this Application. +Deprecated: Use GetProviderConfigReference. +*/ +func (mg *Application) GetProviderReference() *xpv1.Reference { + return mg.Spec.ProviderReference +} + +// GetWriteConnectionSecretToReference of this Application. +func (mg *Application) GetWriteConnectionSecretToReference() *xpv1.SecretReference { + return mg.Spec.WriteConnectionSecretToReference +} + +// SetConditions of this Application. +func (mg *Application) SetConditions(c ...xpv1.Condition) { + mg.Status.SetConditions(c...) +} + +// SetDeletionPolicy of this Application. +func (mg *Application) SetDeletionPolicy(r xpv1.DeletionPolicy) { + mg.Spec.DeletionPolicy = r +} + +// SetProviderConfigReference of this Application. +func (mg *Application) SetProviderConfigReference(r *xpv1.Reference) { + mg.Spec.ProviderConfigReference = r +} + +/* +SetProviderReference of this Application. +Deprecated: Use SetProviderConfigReference. +*/ +func (mg *Application) SetProviderReference(r *xpv1.Reference) { + mg.Spec.ProviderReference = r +} + +// SetWriteConnectionSecretToReference of this Application. +func (mg *Application) SetWriteConnectionSecretToReference(r *xpv1.SecretReference) { + mg.Spec.WriteConnectionSecretToReference = r +} + +// GetCondition of this Role. +func (mg *Role) GetCondition(ct xpv1.ConditionType) xpv1.Condition { + return mg.Status.GetCondition(ct) +} + +// GetDeletionPolicy of this Role. +func (mg *Role) GetDeletionPolicy() xpv1.DeletionPolicy { + return mg.Spec.DeletionPolicy +} + +// GetProviderConfigReference of this Role. +func (mg *Role) GetProviderConfigReference() *xpv1.Reference { + return mg.Spec.ProviderConfigReference +} + +/* +GetProviderReference of this Role. +Deprecated: Use GetProviderConfigReference. +*/ +func (mg *Role) GetProviderReference() *xpv1.Reference { + return mg.Spec.ProviderReference +} + +// GetWriteConnectionSecretToReference of this Role. +func (mg *Role) GetWriteConnectionSecretToReference() *xpv1.SecretReference { + return mg.Spec.WriteConnectionSecretToReference +} + +// SetConditions of this Role. +func (mg *Role) SetConditions(c ...xpv1.Condition) { + mg.Status.SetConditions(c...) +} + +// SetDeletionPolicy of this Role. +func (mg *Role) SetDeletionPolicy(r xpv1.DeletionPolicy) { + mg.Spec.DeletionPolicy = r +} + +// SetProviderConfigReference of this Role. +func (mg *Role) SetProviderConfigReference(r *xpv1.Reference) { + mg.Spec.ProviderConfigReference = r +} + +/* +SetProviderReference of this Role. +Deprecated: Use SetProviderConfigReference. +*/ +func (mg *Role) SetProviderReference(r *xpv1.Reference) { + mg.Spec.ProviderReference = r +} + +// SetWriteConnectionSecretToReference of this Role. +func (mg *Role) SetWriteConnectionSecretToReference(r *xpv1.SecretReference) { + mg.Spec.WriteConnectionSecretToReference = r +} + +// GetCondition of this RoleAssignment. +func (mg *RoleAssignment) GetCondition(ct xpv1.ConditionType) xpv1.Condition { + return mg.Status.GetCondition(ct) +} + +// GetDeletionPolicy of this RoleAssignment. +func (mg *RoleAssignment) GetDeletionPolicy() xpv1.DeletionPolicy { + return mg.Spec.DeletionPolicy +} + +// GetProviderConfigReference of this RoleAssignment. +func (mg *RoleAssignment) GetProviderConfigReference() *xpv1.Reference { + return mg.Spec.ProviderConfigReference +} + +/* +GetProviderReference of this RoleAssignment. +Deprecated: Use GetProviderConfigReference. +*/ +func (mg *RoleAssignment) GetProviderReference() *xpv1.Reference { + return mg.Spec.ProviderReference +} + +// GetWriteConnectionSecretToReference of this RoleAssignment. +func (mg *RoleAssignment) GetWriteConnectionSecretToReference() *xpv1.SecretReference { + return mg.Spec.WriteConnectionSecretToReference +} + +// SetConditions of this RoleAssignment. +func (mg *RoleAssignment) SetConditions(c ...xpv1.Condition) { + mg.Status.SetConditions(c...) +} + +// SetDeletionPolicy of this RoleAssignment. +func (mg *RoleAssignment) SetDeletionPolicy(r xpv1.DeletionPolicy) { + mg.Spec.DeletionPolicy = r +} + +// SetProviderConfigReference of this RoleAssignment. +func (mg *RoleAssignment) SetProviderConfigReference(r *xpv1.Reference) { + mg.Spec.ProviderConfigReference = r +} + +/* +SetProviderReference of this RoleAssignment. +Deprecated: Use SetProviderConfigReference. +*/ +func (mg *RoleAssignment) SetProviderReference(r *xpv1.Reference) { + mg.Spec.ProviderReference = r +} + +// SetWriteConnectionSecretToReference of this RoleAssignment. +func (mg *RoleAssignment) SetWriteConnectionSecretToReference(r *xpv1.SecretReference) { + mg.Spec.WriteConnectionSecretToReference = r +} + +// GetCondition of this ServicePrincipal. +func (mg *ServicePrincipal) GetCondition(ct xpv1.ConditionType) xpv1.Condition { + return mg.Status.GetCondition(ct) +} + +// GetDeletionPolicy of this ServicePrincipal. +func (mg *ServicePrincipal) GetDeletionPolicy() xpv1.DeletionPolicy { + return mg.Spec.DeletionPolicy +} + +// GetProviderConfigReference of this ServicePrincipal. +func (mg *ServicePrincipal) GetProviderConfigReference() *xpv1.Reference { + return mg.Spec.ProviderConfigReference +} + +/* +GetProviderReference of this ServicePrincipal. +Deprecated: Use GetProviderConfigReference. +*/ +func (mg *ServicePrincipal) GetProviderReference() *xpv1.Reference { + return mg.Spec.ProviderReference +} + +// GetWriteConnectionSecretToReference of this ServicePrincipal. +func (mg *ServicePrincipal) GetWriteConnectionSecretToReference() *xpv1.SecretReference { + return mg.Spec.WriteConnectionSecretToReference +} + +// SetConditions of this ServicePrincipal. +func (mg *ServicePrincipal) SetConditions(c ...xpv1.Condition) { + mg.Status.SetConditions(c...) +} + +// SetDeletionPolicy of this ServicePrincipal. +func (mg *ServicePrincipal) SetDeletionPolicy(r xpv1.DeletionPolicy) { + mg.Spec.DeletionPolicy = r +} + +// SetProviderConfigReference of this ServicePrincipal. +func (mg *ServicePrincipal) SetProviderConfigReference(r *xpv1.Reference) { + mg.Spec.ProviderConfigReference = r +} + +/* +SetProviderReference of this ServicePrincipal. +Deprecated: Use SetProviderConfigReference. +*/ +func (mg *ServicePrincipal) SetProviderReference(r *xpv1.Reference) { + mg.Spec.ProviderReference = r +} + +// SetWriteConnectionSecretToReference of this ServicePrincipal. +func (mg *ServicePrincipal) SetWriteConnectionSecretToReference(r *xpv1.SecretReference) { + mg.Spec.WriteConnectionSecretToReference = r +} diff --git a/apis/rbac/v1alpha1/zz_generated.managedlist.go b/apis/rbac/v1alpha1/zz_generated.managedlist.go new file mode 100644 index 00000000..74131397 --- /dev/null +++ b/apis/rbac/v1alpha1/zz_generated.managedlist.go @@ -0,0 +1,66 @@ +/* +Copyright 2019 The Crossplane 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. +*/ + +// Code generated by angryjet. DO NOT EDIT. + +package v1alpha1 + +import resource "github.com/crossplane/crossplane-runtime/pkg/resource" + +// GetItems of this ADGroupList. +func (l *ADGroupList) GetItems() []resource.Managed { + items := make([]resource.Managed, len(l.Items)) + for i := range l.Items { + items[i] = &l.Items[i] + } + return items +} + +// GetItems of this ApplicationList. +func (l *ApplicationList) GetItems() []resource.Managed { + items := make([]resource.Managed, len(l.Items)) + for i := range l.Items { + items[i] = &l.Items[i] + } + return items +} + +// GetItems of this RoleAssignmentList. +func (l *RoleAssignmentList) GetItems() []resource.Managed { + items := make([]resource.Managed, len(l.Items)) + for i := range l.Items { + items[i] = &l.Items[i] + } + return items +} + +// GetItems of this RoleList. +func (l *RoleList) GetItems() []resource.Managed { + items := make([]resource.Managed, len(l.Items)) + for i := range l.Items { + items[i] = &l.Items[i] + } + return items +} + +// GetItems of this ServicePrincipalList. +func (l *ServicePrincipalList) GetItems() []resource.Managed { + items := make([]resource.Managed, len(l.Items)) + for i := range l.Items { + items[i] = &l.Items[i] + } + return items +} diff --git a/examples/rbac/application.yaml b/examples/rbac/application.yaml new file mode 100644 index 00000000..1d3d9d51 --- /dev/null +++ b/examples/rbac/application.yaml @@ -0,0 +1,10 @@ +apiVersion: rbac.azure.crossplane.io/v1alpha1 +kind: Application +metadata: + name: example-app +spec: + availableToOtherTenants: false + displayName: exampleapp + homepage: https://exampleapp.com + identifierUris: + - https://exampleapp.com \ No newline at end of file diff --git a/examples/rbac/group.yaml b/examples/rbac/group.yaml new file mode 100644 index 00000000..e30a4883 --- /dev/null +++ b/examples/rbac/group.yaml @@ -0,0 +1,6 @@ +apiVersion: rbac.azure.crossplane.io/v1alpha1 +kind: ADGroup +metadata: + name: example-group +spec: + groupID: c539b318-a997-4088-9c8d-159973d3c465 \ No newline at end of file diff --git a/examples/rbac/role.yaml b/examples/rbac/role.yaml new file mode 100644 index 00000000..234f92e7 --- /dev/null +++ b/examples/rbac/role.yaml @@ -0,0 +1,6 @@ +apiVersion: rbac.azure.crossplane.io/v1alpha1 +kind: Role +metadata: + name: contributor +spec: + roleID: /providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c \ No newline at end of file diff --git a/examples/rbac/roleassignment.yaml b/examples/rbac/roleassignment.yaml new file mode 100644 index 00000000..5e23c732 --- /dev/null +++ b/examples/rbac/roleassignment.yaml @@ -0,0 +1,25 @@ +apiVersion: rbac.azure.crossplane.io/v1alpha1 +kind: RoleAssignment +metadata: + name: contributor-group +spec: + principalType: 'group' + providerConfigRef: + name: default + roleIDRef: + name: contributor + groupIDRef: + name: example-group +--- +apiVersion: rbac.azure.crossplane.io/v1alpha1 +kind: RoleAssignment +metadata: + name: contributor-sp +spec: + principalType: 'service-principal' + providerConfigRef: + name: default + roleIDRef: + name: contributor + principalIDRef: + name: example-sp diff --git a/examples/rbac/serviceprincipal.yaml b/examples/rbac/serviceprincipal.yaml new file mode 100644 index 00000000..39463a49 --- /dev/null +++ b/examples/rbac/serviceprincipal.yaml @@ -0,0 +1,8 @@ +apiVersion: rbac.azure.crossplane.io/v1alpha1 +kind: ServicePrincipal +metadata: + name: example-sp +spec: + applicationIDRef: + name: example-app + accountEnabled: true \ No newline at end of file diff --git a/package/crds/rbac.azure.crossplane.io_adgroups.yaml b/package/crds/rbac.azure.crossplane.io_adgroups.yaml new file mode 100644 index 00000000..9f54be96 --- /dev/null +++ b/package/crds/rbac.azure.crossplane.io_adgroups.yaml @@ -0,0 +1,131 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.0 + creationTimestamp: null + name: adgroups.rbac.azure.crossplane.io +spec: + group: rbac.azure.crossplane.io + names: + categories: + - crossplane + - managed + - azure + kind: ADGroup + listKind: ADGroupList + plural: adgroups + singular: adgroup + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: AGE + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: A ADGroup is a resource that represents an ADGroup. + 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: An ADGroupSpec defines the desired state of an ADGroup. + properties: + deletionPolicy: + default: Delete + description: DeletionPolicy specifies what will happen to the underlying external when this managed resource is deleted - either "Delete" or "Orphan" the external resource. + enum: + - Orphan + - Delete + type: string + groupID: + description: GroupID - ID of ActiveDirectory group. + type: string + providerConfigRef: + default: + name: default + description: ProviderConfigReference specifies how the provider that will be used to create, observe, update, and delete this managed resource should be configured. + properties: + name: + description: Name of the referenced object. + type: string + required: + - name + type: object + providerRef: + description: 'ProviderReference specifies the provider that will be used to create, observe, update, and delete this managed resource. Deprecated: Please use ProviderConfigReference, i.e. `providerConfigRef`' + properties: + name: + description: Name of the referenced object. + type: string + required: + - name + type: object + writeConnectionSecretToRef: + description: WriteConnectionSecretToReference specifies the namespace and name of a Secret to which any connection details for this managed resource should be written. Connection details frequently include the endpoint, username, and password required to connect to the managed resource. + properties: + name: + description: Name of the secret. + type: string + namespace: + description: Namespace of the secret. + type: string + required: + - name + - namespace + type: object + required: + - groupID + type: object + status: + description: An ADGroupStatus represents the observed state of an ADGroup. + properties: + conditions: + description: Conditions of the resource. + items: + description: A Condition that may apply to a resource. + properties: + lastTransitionTime: + description: LastTransitionTime is the last time this condition transitioned from one status to another. + format: date-time + type: string + message: + description: A Message containing details about this condition's last transition from one status to another, if any. + type: string + reason: + description: A Reason for this condition's last transition from one status to another. + type: string + status: + description: Status of this condition; is it currently True, False, or Unknown? + type: string + type: + description: Type of this condition. At most one of each condition type may apply to a resource at any point in time. + type: string + required: + - lastTransitionTime + - reason + - status + - type + type: object + type: array + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/package/crds/rbac.azure.crossplane.io_applications.yaml b/package/crds/rbac.azure.crossplane.io_applications.yaml new file mode 100644 index 00000000..522ef7d0 --- /dev/null +++ b/package/crds/rbac.azure.crossplane.io_applications.yaml @@ -0,0 +1,149 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.0 + creationTimestamp: null + name: applications.rbac.azure.crossplane.io +spec: + group: rbac.azure.crossplane.io + names: + categories: + - crossplane + - managed + - azure + kind: Application + listKind: ApplicationList + plural: applications + singular: application + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=='Ready')].status + name: READY + type: string + - jsonPath: .status.conditions[?(@.type=='Synced')].status + name: SYNCED + type: string + - jsonPath: .metadata.creationTimestamp + name: AGE + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: A Application is a managed resource that represents an Application. + 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: An ApplicationSpec defines the desired state of an Application. + properties: + availableToOtherTenants: + description: AvailableToOtherTenants - Whether the application is available to other tenants. + type: boolean + deletionPolicy: + default: Delete + description: DeletionPolicy specifies what will happen to the underlying external when this managed resource is deleted - either "Delete" or "Orphan" the external resource. + enum: + - Orphan + - Delete + type: string + displayName: + description: DisplayName - The display name of the application. + type: string + homepage: + description: Homepage - The home page of the application. + type: string + identifierUris: + description: IdentifierUris - A collection of URIs for the application. + items: + type: string + type: array + providerConfigRef: + default: + name: default + description: ProviderConfigReference specifies how the provider that will be used to create, observe, update, and delete this managed resource should be configured. + properties: + name: + description: Name of the referenced object. + type: string + required: + - name + type: object + providerRef: + description: 'ProviderReference specifies the provider that will be used to create, observe, update, and delete this managed resource. Deprecated: Please use ProviderConfigReference, i.e. `providerConfigRef`' + properties: + name: + description: Name of the referenced object. + type: string + required: + - name + type: object + writeConnectionSecretToRef: + description: WriteConnectionSecretToReference specifies the namespace and name of a Secret to which any connection details for this managed resource should be written. Connection details frequently include the endpoint, username, and password required to connect to the managed resource. + properties: + name: + description: Name of the secret. + type: string + namespace: + description: Namespace of the secret. + type: string + required: + - name + - namespace + type: object + type: object + status: + description: An ApplicationStatus represents the observed state of an Application. + properties: + applicationID: + description: ApplicationID - The application ID. + type: string + conditions: + description: Conditions of the resource. + items: + description: A Condition that may apply to a resource. + properties: + lastTransitionTime: + description: LastTransitionTime is the last time this condition transitioned from one status to another. + format: date-time + type: string + message: + description: A Message containing details about this condition's last transition from one status to another, if any. + type: string + reason: + description: A Reason for this condition's last transition from one status to another. + type: string + status: + description: Status of this condition; is it currently True, False, or Unknown? + type: string + type: + description: Type of this condition. At most one of each condition type may apply to a resource at any point in time. + type: string + required: + - lastTransitionTime + - reason + - status + - type + type: object + type: array + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/package/crds/rbac.azure.crossplane.io_roleassignments.yaml b/package/crds/rbac.azure.crossplane.io_roleassignments.yaml new file mode 100644 index 00000000..9d615e2f --- /dev/null +++ b/package/crds/rbac.azure.crossplane.io_roleassignments.yaml @@ -0,0 +1,212 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.0 + creationTimestamp: null + name: roleassignments.rbac.azure.crossplane.io +spec: + group: rbac.azure.crossplane.io + names: + categories: + - crossplane + - managed + - azure + kind: RoleAssignment + listKind: RoleAssignmentList + plural: roleassignments + singular: roleassignment + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=='Ready')].status + name: READY + type: string + - jsonPath: .status.conditions[?(@.type=='Synced')].status + name: SYNCED + type: string + - jsonPath: .metadata.creationTimestamp + name: AGE + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: A RoleAssignment is a managed resource that represents an RoleAssignment. + 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: An RoleAssignmentSpec defines the desired state of an RoleAssignment. + properties: + deletionPolicy: + default: Delete + description: DeletionPolicy specifies what will happen to the underlying external when this managed resource is deleted - either "Delete" or "Orphan" the external resource. + enum: + - Orphan + - Delete + type: string + groupIDRef: + description: GroupIDRef - A reference to the Group id. + properties: + name: + description: Name of the referenced object. + type: string + required: + - name + type: object + groupIDSelector: + description: GroupIDSelector - Select a reference to the Group id. + properties: + matchControllerRef: + description: MatchControllerRef ensures an object with the same controller reference as the selecting object is selected. + type: boolean + matchLabels: + additionalProperties: + type: string + description: MatchLabels ensures an object with matching labels is selected. + type: object + type: object + principalID: + description: PrincipalID - The principal ID assigned to the role. This maps to the ID inside the Active Directory. It can point to a user, service principal, or security group. + type: string + principalIDRef: + description: PrincipalIDRef - A reference to the Principal id. + properties: + name: + description: Name of the referenced object. + type: string + required: + - name + type: object + principalIDSelector: + description: PrincipalIDRef - Select a reference to the Principal id. + properties: + matchControllerRef: + description: MatchControllerRef ensures an object with the same controller reference as the selecting object is selected. + type: boolean + matchLabels: + additionalProperties: + type: string + description: MatchLabels ensures an object with matching labels is selected. + type: object + type: object + principalType: + description: 'PrincipalType - type of principal oneof: [''group'', ''service-principal'']' + enum: + - group + - service-principal + type: string + providerConfigRef: + default: + name: default + description: ProviderConfigReference specifies how the provider that will be used to create, observe, update, and delete this managed resource should be configured. + properties: + name: + description: Name of the referenced object. + type: string + required: + - name + type: object + providerRef: + description: 'ProviderReference specifies the provider that will be used to create, observe, update, and delete this managed resource. Deprecated: Please use ProviderConfigReference, i.e. `providerConfigRef`' + properties: + name: + description: Name of the referenced object. + type: string + required: + - name + type: object + roleID: + description: RoleID - The role definition ID. + type: string + roleIDRef: + description: RoleIDRef - A reference to the Role id. + properties: + name: + description: Name of the referenced object. + type: string + required: + - name + type: object + roleIDSelector: + description: RoleIDSelector - Select a reference to the Role id. + properties: + matchControllerRef: + description: MatchControllerRef ensures an object with the same controller reference as the selecting object is selected. + type: boolean + matchLabels: + additionalProperties: + type: string + description: MatchLabels ensures an object with matching labels is selected. + type: object + type: object + scope: + description: Scope - The role assignment scope. + type: string + writeConnectionSecretToRef: + description: WriteConnectionSecretToReference specifies the namespace and name of a Secret to which any connection details for this managed resource should be written. Connection details frequently include the endpoint, username, and password required to connect to the managed resource. + properties: + name: + description: Name of the secret. + type: string + namespace: + description: Namespace of the secret. + type: string + required: + - name + - namespace + type: object + required: + - scope + type: object + status: + description: An RoleAssignmentStatus represents the observed state of an RoleAssignment. + properties: + conditions: + description: Conditions of the resource. + items: + description: A Condition that may apply to a resource. + properties: + lastTransitionTime: + description: LastTransitionTime is the last time this condition transitioned from one status to another. + format: date-time + type: string + message: + description: A Message containing details about this condition's last transition from one status to another, if any. + type: string + reason: + description: A Reason for this condition's last transition from one status to another. + type: string + status: + description: Status of this condition; is it currently True, False, or Unknown? + type: string + type: + description: Type of this condition. At most one of each condition type may apply to a resource at any point in time. + type: string + required: + - lastTransitionTime + - reason + - status + - type + type: object + type: array + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/package/crds/rbac.azure.crossplane.io_roles.yaml b/package/crds/rbac.azure.crossplane.io_roles.yaml new file mode 100644 index 00000000..de0ce6bb --- /dev/null +++ b/package/crds/rbac.azure.crossplane.io_roles.yaml @@ -0,0 +1,131 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.0 + creationTimestamp: null + name: roles.rbac.azure.crossplane.io +spec: + group: rbac.azure.crossplane.io + names: + categories: + - crossplane + - managed + - azure + kind: Role + listKind: RoleList + plural: roles + singular: role + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: AGE + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: A Role is a resource that represents an Role. + 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: An RoleSpec defines the desired state of an Role. + properties: + deletionPolicy: + default: Delete + description: DeletionPolicy specifies what will happen to the underlying external when this managed resource is deleted - either "Delete" or "Orphan" the external resource. + enum: + - Orphan + - Delete + type: string + providerConfigRef: + default: + name: default + description: ProviderConfigReference specifies how the provider that will be used to create, observe, update, and delete this managed resource should be configured. + properties: + name: + description: Name of the referenced object. + type: string + required: + - name + type: object + providerRef: + description: 'ProviderReference specifies the provider that will be used to create, observe, update, and delete this managed resource. Deprecated: Please use ProviderConfigReference, i.e. `providerConfigRef`' + properties: + name: + description: Name of the referenced object. + type: string + required: + - name + type: object + roleID: + description: RoleID - The role definition ID. + type: string + writeConnectionSecretToRef: + description: WriteConnectionSecretToReference specifies the namespace and name of a Secret to which any connection details for this managed resource should be written. Connection details frequently include the endpoint, username, and password required to connect to the managed resource. + properties: + name: + description: Name of the secret. + type: string + namespace: + description: Namespace of the secret. + type: string + required: + - name + - namespace + type: object + required: + - roleID + type: object + status: + description: An RoleStatus represents the observed state of an Role. + properties: + conditions: + description: Conditions of the resource. + items: + description: A Condition that may apply to a resource. + properties: + lastTransitionTime: + description: LastTransitionTime is the last time this condition transitioned from one status to another. + format: date-time + type: string + message: + description: A Message containing details about this condition's last transition from one status to another, if any. + type: string + reason: + description: A Reason for this condition's last transition from one status to another. + type: string + status: + description: Status of this condition; is it currently True, False, or Unknown? + type: string + type: + description: Type of this condition. At most one of each condition type may apply to a resource at any point in time. + type: string + required: + - lastTransitionTime + - reason + - status + - type + type: object + type: array + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/package/crds/rbac.azure.crossplane.io_serviceprincipals.yaml b/package/crds/rbac.azure.crossplane.io_serviceprincipals.yaml new file mode 100644 index 00000000..11bd2470 --- /dev/null +++ b/package/crds/rbac.azure.crossplane.io_serviceprincipals.yaml @@ -0,0 +1,159 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.0 + creationTimestamp: null + name: serviceprincipals.rbac.azure.crossplane.io +spec: + group: rbac.azure.crossplane.io + names: + categories: + - crossplane + - managed + - azure + kind: ServicePrincipal + listKind: ServicePrincipalList + plural: serviceprincipals + singular: serviceprincipal + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=='Ready')].status + name: READY + type: string + - jsonPath: .status.conditions[?(@.type=='Synced')].status + name: SYNCED + type: string + - jsonPath: .metadata.creationTimestamp + name: AGE + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: A ServicePrincipal is a managed resource that represents an ServicePrincipal. + 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: An ServicePrincipalSpec defines the desired state of an ServicePrincipal. + properties: + accountEnabled: + description: AccountEnabled - whether or not the service principal account is enabled + type: boolean + applicationID: + description: ApplicationID - The application ID. + type: string + applicationIDRef: + description: ApplicationIDRef - A reference to the Application id. + properties: + name: + description: Name of the referenced object. + type: string + required: + - name + type: object + applicationIDSelector: + description: ApplicationIDSelector - Select a reference to the Application id. + properties: + matchControllerRef: + description: MatchControllerRef ensures an object with the same controller reference as the selecting object is selected. + type: boolean + matchLabels: + additionalProperties: + type: string + description: MatchLabels ensures an object with matching labels is selected. + type: object + type: object + deletionPolicy: + default: Delete + description: DeletionPolicy specifies what will happen to the underlying external when this managed resource is deleted - either "Delete" or "Orphan" the external resource. + enum: + - Orphan + - Delete + type: string + providerConfigRef: + default: + name: default + description: ProviderConfigReference specifies how the provider that will be used to create, observe, update, and delete this managed resource should be configured. + properties: + name: + description: Name of the referenced object. + type: string + required: + - name + type: object + providerRef: + description: 'ProviderReference specifies the provider that will be used to create, observe, update, and delete this managed resource. Deprecated: Please use ProviderConfigReference, i.e. `providerConfigRef`' + properties: + name: + description: Name of the referenced object. + type: string + required: + - name + type: object + writeConnectionSecretToRef: + description: WriteConnectionSecretToReference specifies the namespace and name of a Secret to which any connection details for this managed resource should be written. Connection details frequently include the endpoint, username, and password required to connect to the managed resource. + properties: + name: + description: Name of the secret. + type: string + namespace: + description: Namespace of the secret. + type: string + required: + - name + - namespace + type: object + type: object + status: + description: An ServicePrincipalStatus represents the observed state of an ServicePrincipal. + properties: + conditions: + description: Conditions of the resource. + items: + description: A Condition that may apply to a resource. + properties: + lastTransitionTime: + description: LastTransitionTime is the last time this condition transitioned from one status to another. + format: date-time + type: string + message: + description: A Message containing details about this condition's last transition from one status to another, if any. + type: string + reason: + description: A Reason for this condition's last transition from one status to another. + type: string + status: + description: Status of this condition; is it currently True, False, or Unknown? + type: string + type: + description: Type of this condition. At most one of each condition type may apply to a resource at any point in time. + type: string + required: + - lastTransitionTime + - reason + - status + - type + type: object + type: array + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/pkg/clients/azure.go b/pkg/clients/azure.go index 1272009a..114e552f 100644 --- a/pkg/clients/azure.go +++ b/pkg/clients/azure.go @@ -19,6 +19,7 @@ package azure import ( "context" "encoding/json" + "fmt" "net/http" "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2018-05-01/resources" @@ -31,6 +32,7 @@ import ( "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" + xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1" "github.com/crossplane/crossplane-runtime/pkg/resource" "github.com/crossplane/provider-azure/apis/v1alpha3" @@ -149,6 +151,19 @@ func UseProviderConfig(ctx context.Context, c client.Client, mg resource.Managed return m, a, errors.Wrap(err, errGetAuthorizer) } +// ResolveSecret getting value from secret ref +func ResolveSecret(ctx context.Context, c client.Reader, ref xpv1.SecretKeySelector) ([]byte, error) { + s := &corev1.Secret{} + if err := c.Get(ctx, types.NamespacedName{Name: ref.Name, Namespace: ref.Namespace}, s); err != nil { + return nil, err + } + key, ok := s.Data[ref.Key] + if !ok { + return nil, fmt.Errorf("%s key not found in %s:%s secret", ref.Key, ref.Name, ref.Namespace) + } + return key, nil +} + // Client struct that represents the information needed to connect to the Azure services as a client type Client struct { autorest.Authorizer diff --git a/pkg/controller/azure.go b/pkg/controller/azure.go index 9386fc82..ecf74bfd 100644 --- a/pkg/controller/azure.go +++ b/pkg/controller/azure.go @@ -37,6 +37,9 @@ import ( "github.com/crossplane/provider-azure/pkg/controller/database/postgresqlservervirtualnetworkrule" "github.com/crossplane/provider-azure/pkg/controller/network/subnet" "github.com/crossplane/provider-azure/pkg/controller/network/virtualnetwork" + "github.com/crossplane/provider-azure/pkg/controller/rbac/application" + "github.com/crossplane/provider-azure/pkg/controller/rbac/roleassignment" + "github.com/crossplane/provider-azure/pkg/controller/rbac/serviceprincipal" "github.com/crossplane/provider-azure/pkg/controller/resourcegroup" "github.com/crossplane/provider-azure/pkg/controller/storage/account" "github.com/crossplane/provider-azure/pkg/controller/storage/container" @@ -57,6 +60,9 @@ func Setup(mgr ctrl.Manager, l logging.Logger, rl workqueue.RateLimiter, poll ti cosmosdb.Setup, virtualnetwork.Setup, subnet.Setup, + application.Setup, + roleassignment.Setup, + serviceprincipal.Setup, resourcegroup.Setup, account.Setup, container.Setup, diff --git a/pkg/controller/rbac/application/managed.go b/pkg/controller/rbac/application/managed.go new file mode 100644 index 00000000..b6b64eb1 --- /dev/null +++ b/pkg/controller/rbac/application/managed.go @@ -0,0 +1,195 @@ +/* +Copyright 2021 The Crossplane 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 application + +import ( + "context" + "time" + + "github.com/Azure/azure-sdk-for-go/services/graphrbac/1.6/graphrbac" + "github.com/Azure/azure-sdk-for-go/services/graphrbac/1.6/graphrbac/graphrbacapi" + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/adal" + "github.com/Azure/go-autorest/autorest/date" + "github.com/Azure/go-autorest/autorest/to" + "github.com/google/uuid" + "github.com/pkg/errors" + "k8s.io/client-go/util/workqueue" + + xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1" + "github.com/crossplane/crossplane-runtime/pkg/event" + "github.com/crossplane/crossplane-runtime/pkg/logging" + "github.com/crossplane/crossplane-runtime/pkg/meta" + "github.com/crossplane/crossplane-runtime/pkg/password" + "github.com/crossplane/crossplane-runtime/pkg/ratelimiter" + "github.com/crossplane/crossplane-runtime/pkg/reconciler/managed" + "github.com/crossplane/crossplane-runtime/pkg/resource" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller" + + "github.com/crossplane/provider-azure/apis/rbac/v1alpha1" + azure "github.com/crossplane/provider-azure/pkg/clients" + azureclients "github.com/crossplane/provider-azure/pkg/clients" +) + +// Error strings. +const ( + errNotApplication = "managed resource is not an Application" + errCreateApplication = "cannot create Application" + errUpdateApplication = "cannot update Application" + errGetApplication = "cannot get Application" + errDeleteApplication = "cannot delete Application" +) + +// Setup adds a controller that reconciles Application. +func Setup(mgr ctrl.Manager, l logging.Logger, rl workqueue.RateLimiter, poll time.Duration) error { + name := managed.ControllerName(v1alpha1.ApplicationKind) + + return ctrl.NewControllerManagedBy(mgr). + Named(name). + WithOptions(controller.Options{ + RateLimiter: ratelimiter.NewDefaultManagedRateLimiter(rl), + }). + For(&v1alpha1.Application{}). + Complete(managed.NewReconciler(mgr, + resource.ManagedKind(v1alpha1.ApplicationGroupVersionKind), + // Override default initializers in case to remove NewNameAsExternalName Initializer + managed.WithInitializers(), + managed.WithConnectionPublishers(), + managed.WithExternalConnecter(&connecter{client: mgr.GetClient()}), + managed.WithReferenceResolver(managed.NewAPISimpleReferenceResolver(mgr.GetClient())), + managed.WithPollInterval(poll), + managed.WithLogger(l.WithValues("controller", name)), + managed.WithRecorder(event.NewAPIRecorder(mgr.GetEventRecorderFor(name))))) +} + +type connecter struct { + client client.Client +} + +func (c *connecter) Connect(ctx context.Context, mg resource.Managed) (managed.ExternalClient, error) { + creds, _, err := azureclients.GetAuthInfo(ctx, c.client, mg) + if err != nil { + return nil, err + } + cfg, err := adal.NewOAuthConfig(creds[azure.CredentialsKeyActiveDirectoryEndpointURL], creds[azure.CredentialsKeyTenantID]) + if err != nil { + return nil, errors.Wrap(err, "cannot create OAuth configuration") + } + token, err := adal.NewServicePrincipalToken(*cfg, + creds[azure.CredentialsKeyClientID], + creds[azure.CredentialsKeyClientSecret], + creds[azure.CredentialsKeyActiveDirectoryGraphResourceID]) + if err != nil { + return nil, errors.Wrap(err, "cannot create service principal token") + } + if err := token.Refresh(); err != nil { + return nil, errors.Wrap(err, "cannot refresh service principal token") + } + ta := autorest.NewBearerAuthorizer(token) + ac := graphrbac.NewApplicationsClient(creds[azure.CredentialsKeyTenantID]) + ac.Authorizer = ta + return &external{c: ac}, nil +} + +type external struct { + c graphrbacapi.ApplicationsClientAPI +} + +func (e *external) Observe(ctx context.Context, mg resource.Managed) (managed.ExternalObservation, error) { + s, ok := mg.(*v1alpha1.Application) + if !ok { + return managed.ExternalObservation{}, errors.New(errNotApplication) + } + if meta.GetExternalName(s) == "" { + return managed.ExternalObservation{}, nil + } + + az, err := e.c.Get(ctx, meta.GetExternalName(s)) + if err != nil { + err = errors.Wrap(err, errGetApplication) + err = resource.Ignore(azureclients.IsNotFound, err) + return managed.ExternalObservation{}, err + } + + s.Status.ApplicationID = azure.ToString(az.AppID) + s.SetConditions(xpv1.Available()) + return managed.ExternalObservation{ + ResourceExists: true, + ResourceUpToDate: true, + }, nil +} + +func (e *external) Create(ctx context.Context, mg resource.Managed) (managed.ExternalCreation, error) { + s, ok := mg.(*v1alpha1.Application) + if !ok { + return managed.ExternalCreation{}, errors.New(errNotApplication) + } + pw, err := password.Generate() + if err != nil { + return managed.ExternalCreation{}, errors.Wrap(err, errCreateApplication) + } + pc, err := newPasswordCredential(pw) + if err != nil { + return managed.ExternalCreation{}, errors.Wrap(err, errCreateApplication) + } + p := graphrbac.ApplicationCreateParameters{ + AvailableToOtherTenants: s.Spec.AvailableToOtherTenants, + DisplayName: s.Spec.DisplayName, + Homepage: s.Spec.Homepage, + IdentifierUris: s.Spec.IdentifierUris, + PasswordCredentials: &[]graphrbac.PasswordCredential{pc}, + } + rsp, err := e.c.Create(ctx, p) + if err != nil { + return managed.ExternalCreation{}, errors.Wrap(err, errCreateApplication) + } + meta.SetExternalName(s, azure.ToString(rsp.ObjectID)) + return managed.ExternalCreation{ + ConnectionDetails: map[string][]byte{ + xpv1.ResourceCredentialsSecretPasswordKey: []byte(pw), + }, + }, nil +} + +func (e *external) Update(ctx context.Context, mg resource.Managed) (managed.ExternalUpdate, error) { + return managed.ExternalUpdate{}, errors.Wrap(errors.New("not supported"), errUpdateApplication) +} + +func (e *external) Delete(ctx context.Context, mg resource.Managed) error { + s, ok := mg.(*v1alpha1.Application) + if !ok { + return errors.New(errNotApplication) + } + _, err := e.c.Delete(ctx, meta.GetExternalName(s)) + return errors.Wrap(resource.IgnoreNotFound(err), errDeleteApplication) +} + +const ( + appCredsValidYears = 5 +) + +func newPasswordCredential(secret string) (graphrbac.PasswordCredential, error) { + keyID, err := uuid.NewRandom() + return graphrbac.PasswordCredential{ + StartDate: &date.Time{Time: time.Now()}, + EndDate: &date.Time{Time: time.Now().AddDate(appCredsValidYears, 0, 0)}, + KeyID: to.StringPtr(keyID.String()), + Value: to.StringPtr(secret), + }, err +} diff --git a/pkg/controller/rbac/roleassignment/managed.go b/pkg/controller/rbac/roleassignment/managed.go new file mode 100644 index 00000000..7f8e7b3b --- /dev/null +++ b/pkg/controller/rbac/roleassignment/managed.go @@ -0,0 +1,153 @@ +/* +Copyright 2021 The Crossplane 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 roleassignment + +import ( + "context" + "fmt" + "time" + + "github.com/Azure/azure-sdk-for-go/services/preview/authorization/mgmt/2018-01-01-preview/authorization" + "github.com/Azure/azure-sdk-for-go/services/preview/authorization/mgmt/2018-01-01-preview/authorization/authorizationapi" + "github.com/google/uuid" + "github.com/pkg/errors" + "k8s.io/client-go/util/workqueue" + ctrl "sigs.k8s.io/controller-runtime" + + xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1" + "github.com/crossplane/crossplane-runtime/pkg/event" + "github.com/crossplane/crossplane-runtime/pkg/logging" + "github.com/crossplane/crossplane-runtime/pkg/meta" + "github.com/crossplane/crossplane-runtime/pkg/ratelimiter" + "github.com/crossplane/crossplane-runtime/pkg/reconciler/managed" + "github.com/crossplane/crossplane-runtime/pkg/resource" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller" + + "github.com/crossplane/provider-azure/apis/rbac/v1alpha1" + azure "github.com/crossplane/provider-azure/pkg/clients" + azureclients "github.com/crossplane/provider-azure/pkg/clients" +) + +// Error strings. +const ( + errNotRoleAssignment = "managed resource is not an RoleAssignment" + errCreateRoleAssignment = "cannot create RoleAssignment" + errUpdateRoleAssignment = "cannot update RoleAssignment" + errGetRoleAssignment = "cannot get RoleAssignment" + errDeleteRoleAssignment = "cannot delete RoleAssignment" +) + +// Setup adds a controller that reconciles RoleAssignment. +func Setup(mgr ctrl.Manager, l logging.Logger, rl workqueue.RateLimiter, poll time.Duration) error { + name := managed.ControllerName(v1alpha1.RoleAssignmentKind) + + return ctrl.NewControllerManagedBy(mgr). + Named(name). + WithOptions(controller.Options{ + RateLimiter: ratelimiter.NewDefaultManagedRateLimiter(rl), + }). + For(&v1alpha1.RoleAssignment{}). + Complete(managed.NewReconciler(mgr, + resource.ManagedKind(v1alpha1.RoleAssignmentGroupVersionKind), + // Override default initializers in case to remove NewNameAsExternalName Initializer + managed.WithInitializers(), + managed.WithConnectionPublishers(), + managed.WithExternalConnecter(&connecter{client: mgr.GetClient()}), + managed.WithReferenceResolver(managed.NewAPISimpleReferenceResolver(mgr.GetClient())), + managed.WithLogger(l.WithValues("controller", name)), + managed.WithRecorder(event.NewAPIRecorder(mgr.GetEventRecorderFor(name))), + )) +} + +type connecter struct { + client client.Client +} + +func (c *connecter) Connect(ctx context.Context, mg resource.Managed) (managed.ExternalClient, error) { + creds, auth, err := azureclients.GetAuthInfo(ctx, c.client, mg) + if err != nil { + return nil, err + } + subID := creds[azure.CredentialsKeySubscriptionID] + rac := authorization.NewRoleAssignmentsClient(subID) + rac.Authorizer = auth + _ = rac.AddToUserAgent(azure.UserAgent) + return &external{c: rac, subID: subID}, nil +} + +type external struct { + c authorizationapi.RoleAssignmentsClientAPI + subID string +} + +func (e *external) Observe(ctx context.Context, mg resource.Managed) (managed.ExternalObservation, error) { + s, ok := mg.(*v1alpha1.RoleAssignment) + if !ok { + return managed.ExternalObservation{}, errors.New(errNotRoleAssignment) + } + name := "" + filter := fmt.Sprintf("principalId eq '%s'", s.Spec.PrincipalID) + for l, err := e.c.ListForScopeComplete(ctx, s.Spec.Scope, filter); l.NotDone(); err = l.NextWithContext(ctx) { + if err != nil { + return managed.ExternalObservation{}, errors.Wrap(err, errGetRoleAssignment) + } + name = azure.ToString(l.Value().Name) + // nolint:staticcheck + break + } + meta.SetExternalName(s, name) + if meta.GetExternalName(s) == "" { + return managed.ExternalObservation{}, nil + } + s.SetConditions(xpv1.Available()) + return managed.ExternalObservation{ResourceExists: true, ResourceUpToDate: true}, nil +} + +func (e *external) Create(ctx context.Context, mg resource.Managed) (managed.ExternalCreation, error) { + s, ok := mg.(*v1alpha1.RoleAssignment) + if !ok { + return managed.ExternalCreation{}, errors.New(errNotRoleAssignment) + } + p := authorization.RoleAssignmentCreateParameters{RoleAssignmentProperties: &authorization.RoleAssignmentProperties{ + RoleDefinitionID: azure.ToStringPtr(fmt.Sprintf("/subscriptions/%s%s", e.subID, s.Spec.RoleID)), + PrincipalID: azure.ToStringPtr(s.Spec.PrincipalID), + }} + uuidName, err := uuid.NewRandom() + if err != nil { + return managed.ExternalCreation{}, errors.Wrap(err, errCreateRoleAssignment) + } + name := uuidName.String() + _, err = e.c.Create(ctx, s.Spec.Scope, name, p) + if err != nil { + return managed.ExternalCreation{}, errors.Wrap(err, errCreateRoleAssignment) + } + return managed.ExternalCreation{}, nil +} + +func (e *external) Update(ctx context.Context, mg resource.Managed) (managed.ExternalUpdate, error) { + return managed.ExternalUpdate{}, errors.New(errUpdateRoleAssignment) +} + +func (e *external) Delete(ctx context.Context, mg resource.Managed) error { + s, ok := mg.(*v1alpha1.RoleAssignment) + if !ok { + return errors.New(errNotRoleAssignment) + } + _, err := e.c.Delete(ctx, s.Spec.Scope, meta.GetExternalName(s)) + return errors.Wrap(resource.IgnoreNotFound(err), errDeleteRoleAssignment) +} diff --git a/pkg/controller/rbac/serviceprincipal/managed.go b/pkg/controller/rbac/serviceprincipal/managed.go new file mode 100644 index 00000000..0facfca0 --- /dev/null +++ b/pkg/controller/rbac/serviceprincipal/managed.go @@ -0,0 +1,158 @@ +/* +Copyright 2021 The Crossplane 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 serviceprincipal + +import ( + "context" + "time" + + "github.com/Azure/azure-sdk-for-go/services/graphrbac/1.6/graphrbac" + "github.com/Azure/azure-sdk-for-go/services/graphrbac/1.6/graphrbac/graphrbacapi" + "github.com/Azure/go-autorest/autorest" + "github.com/Azure/go-autorest/autorest/adal" + "github.com/Azure/go-autorest/autorest/to" + "github.com/pkg/errors" + "k8s.io/client-go/util/workqueue" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller" + + xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1" + "github.com/crossplane/crossplane-runtime/pkg/event" + "github.com/crossplane/crossplane-runtime/pkg/logging" + "github.com/crossplane/crossplane-runtime/pkg/meta" + "github.com/crossplane/crossplane-runtime/pkg/ratelimiter" + "github.com/crossplane/crossplane-runtime/pkg/reconciler/managed" + "github.com/crossplane/crossplane-runtime/pkg/resource" + + "github.com/crossplane/provider-azure/apis/rbac/v1alpha1" + azure "github.com/crossplane/provider-azure/pkg/clients" + azureclients "github.com/crossplane/provider-azure/pkg/clients" +) + +// Error strings. +const ( + errNotServicePrincipal = "managed resource is not an ServicePrincipal" + errCreateServicePrincipal = "cannot create ServicePrincipal" + errUpdateServicePrincipal = "update ServicePrincipal" + errGetServicePrincipal = "cannot get ServicePrincipal" + errDeleteServicePrincipal = "cannot delete ServicePrincipal" +) + +// Setup adds a controller that reconciles ServicePrincipal. +func Setup(mgr ctrl.Manager, l logging.Logger, rl workqueue.RateLimiter, poll time.Duration) error { + name := managed.ControllerName(v1alpha1.ServicePrincipalKind) + + return ctrl.NewControllerManagedBy(mgr). + Named(name). + WithOptions(controller.Options{ + RateLimiter: ratelimiter.NewDefaultManagedRateLimiter(rl), + }). + For(&v1alpha1.ServicePrincipal{}). + Complete(managed.NewReconciler(mgr, + resource.ManagedKind(v1alpha1.ServicePrincipalGroupVersionKind), + // Override default initializers in case to remove NewNameAsExternalName Initializer + managed.WithInitializers(), + managed.WithConnectionPublishers(), + managed.WithExternalConnecter(&connecter{client: mgr.GetClient()}), + managed.WithReferenceResolver(managed.NewAPISimpleReferenceResolver(mgr.GetClient())), + managed.WithPollInterval(poll), + managed.WithLogger(l.WithValues("controller", name)), + managed.WithRecorder(event.NewAPIRecorder(mgr.GetEventRecorderFor(name))))) +} + +type connecter struct { + client client.Client +} + +func (c *connecter) Connect(ctx context.Context, mg resource.Managed) (managed.ExternalClient, error) { + creds, _, err := azureclients.GetAuthInfo(ctx, c.client, mg) + if err != nil { + return nil, err + } + cfg, err := adal.NewOAuthConfig(creds[azure.CredentialsKeyActiveDirectoryEndpointURL], creds[azure.CredentialsKeyTenantID]) + if err != nil { + return nil, errors.Wrap(err, "cannot create OAuth configuration") + } + token, err := adal.NewServicePrincipalToken(*cfg, + creds[azure.CredentialsKeyClientID], + creds[azure.CredentialsKeyClientSecret], + creds[azure.CredentialsKeyActiveDirectoryGraphResourceID]) + if err != nil { + return nil, errors.Wrap(err, "cannot create service principal token") + } + if err := token.Refresh(); err != nil { + return nil, errors.Wrap(err, "cannot refresh service principal token") + } + ta := autorest.NewBearerAuthorizer(token) + spc := graphrbac.NewServicePrincipalsClient(creds[azure.CredentialsKeyTenantID]) + spc.Authorizer = ta + return &external{spc: spc}, nil +} + +type external struct { + spc graphrbacapi.ServicePrincipalsClientAPI +} + +func (e *external) Observe(ctx context.Context, mg resource.Managed) (managed.ExternalObservation, error) { + s, ok := mg.(*v1alpha1.ServicePrincipal) + if !ok { + return managed.ExternalObservation{}, errors.New(errNotServicePrincipal) + } + if meta.GetExternalName(s) == "" { + return managed.ExternalObservation{}, nil + } + _, err := e.spc.Get(ctx, meta.GetExternalName(s)) + if err != nil { + return managed.ExternalObservation{}, resource.IgnoreNotFound(errors.Wrap(err, errGetServicePrincipal)) + } + s.SetConditions(xpv1.Available()) + return managed.ExternalObservation{ + ResourceExists: true, + ResourceUpToDate: true, + }, nil +} + +func (e *external) Create(ctx context.Context, mg resource.Managed) (managed.ExternalCreation, error) { + s, ok := mg.(*v1alpha1.ServicePrincipal) + if !ok { + return managed.ExternalCreation{}, errors.New(errNotServicePrincipal) + } + p := graphrbac.ServicePrincipalCreateParameters{ + AppID: to.StringPtr(s.Spec.ApplicationID), + AccountEnabled: s.Spec.AccountEnabled, + } + rsp, err := e.spc.Create(ctx, p) + if err != nil { + return managed.ExternalCreation{}, errors.Wrap(err, errCreateServicePrincipal) + } + meta.SetExternalName(s, azure.ToString(rsp.ObjectID)) + return managed.ExternalCreation{}, nil +} + +func (e *external) Update(ctx context.Context, mg resource.Managed) (managed.ExternalUpdate, error) { + return managed.ExternalUpdate{}, errors.Wrap(errors.New("not supported"), errUpdateServicePrincipal) +} + +func (e *external) Delete(ctx context.Context, mg resource.Managed) error { + s, ok := mg.(*v1alpha1.ServicePrincipal) + if !ok { + return errors.New(errNotServicePrincipal) + } + _, err := e.spc.Delete(ctx, meta.GetExternalName(s)) + return errors.Wrap(resource.IgnoreNotFound(err), errDeleteServicePrincipal) +}