package bannerctl import ( "fmt" "strings" bannerAPI "edge-infra.dev/pkg/edge/apis/banner/v1alpha1" "edge-infra.dev/pkg/k8s/konfigkonnector/apis/meta" "edge-infra.dev/pkg/lib/gcp/iam" "edge-infra.dev/pkg/lib/gcp/iam/roles" "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/iam/v1beta1" k8sAPI "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/k8s/v1alpha1" resourceAPI "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/resourcemanager/v1beta1" storageAPI "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/storage/v1beta1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" ) const ( kccOperatorName = "cnrm-controller-manager" kccNamespace = "cnrm-system" rolesFormat = "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])" siemPolicy = "storage-siemwriter" siemBucket = "siem" ) var ( KccDelegatedRoles = []string{roles.LogWriter} KccDelegatedRolesExpression = fmt.Sprintf(rolesFormat, "'"+strings.Join(KccDelegatedRoles, "', '")+"'") ) func (r *BannerReconciler) createClusterInfraKCCResources(b *bannerAPI.Banner, kccResourceName string, projectNumber string) []client.Object { var objs []client.Object objs = append(objs, r.createKCCIAMSA(b, kccResourceName)) for _, obj := range r.createKCCIAMMembers(b, kccResourceName, projectNumber) { objs = append(objs, obj) } return objs } func (r *BannerReconciler) createKCCIAMSA(b *bannerAPI.Banner, kccResourceName string) *v1beta1.IAMServiceAccount { kccSaDisplayName := fmt.Sprintf("k8s cfg connector for project %s", b.Spec.DisplayName) return &v1beta1.IAMServiceAccount{ TypeMeta: gvkToTypeMeta(v1beta1.IAMServiceAccountGVK), ObjectMeta: metav1.ObjectMeta{ Name: kccResourceName, Namespace: b.Name, Annotations: map[string]string{ meta.DeletionPolicyAnnotation: meta.DeletionPolicyAbandon, }, OwnerReferences: r.ownerRef(b), }, // note: annotations Spec: v1beta1.IAMServiceAccountSpec{ DisplayName: &kccSaDisplayName, }, } } func (r *BannerReconciler) createKCCIAMMembers(b *bannerAPI.Banner, kccResourceName string, projectNumber string) []*v1beta1.IAMPolicyMember { policyMember := iam.StandardSvcAccountMember(kccResourceName, b.Spec.GCP.ProjectID) memberGVK := gvkToTypeMeta(v1beta1.IAMPolicyMemberGVK) projectOwner := &v1beta1.IAMPolicyMember{ TypeMeta: memberGVK, ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf("%s-owner", kccResourceName), Namespace: b.Name, Annotations: map[string]string{ meta.DeletionPolicyAnnotation: meta.DeletionPolicyAbandon, }, OwnerReferences: r.ownerRef(b), }, Spec: v1beta1.IAMPolicyMemberSpec{ Member: &policyMember, ResourceRef: k8sAPI.IAMResourceRef{ APIVersion: resourceAPI.SchemeGroupVersion.String(), Kind: resourceAPI.ProjectGVK.Kind, External: b.Spec.GCP.ProjectID, }, Role: roles.Owner, }, } policyName := fmt.Sprintf("%s-logging-logwriter", kccResourceName) description := "KCC delegated roles on foreman" delegatedRoles := &v1beta1.IAMPolicyMember{ TypeMeta: memberGVK, ObjectMeta: metav1.ObjectMeta{ Name: policyName, Namespace: b.Name, Annotations: map[string]string{ meta.DeletionPolicyAnnotation: meta.DeletionPolicyAbandon, }, OwnerReferences: r.ownerRef(b), }, Spec: v1beta1.IAMPolicyMemberSpec{ Member: &policyMember, ResourceRef: k8sAPI.IAMResourceRef{ APIVersion: resourceAPI.SchemeGroupVersion.String(), Kind: resourceAPI.ProjectGVK.Kind, External: r.ForemanProjectID, }, Role: roles.ProjectAdmin, Condition: &v1beta1.PolicymemberCondition{ Title: "kcc_delegated_foreman_roles", Description: &description, Expression: KccDelegatedRolesExpression, }, }, } policyName = fmt.Sprintf("%s-pubsub-admin", kccResourceName) pubSubAdmin := &v1beta1.IAMPolicyMember{ TypeMeta: memberGVK, ObjectMeta: metav1.ObjectMeta{ Name: policyName, Namespace: b.Name, Annotations: map[string]string{ meta.DeletionPolicyAnnotation: meta.DeletionPolicyAbandon, }, OwnerReferences: r.ownerRef(b), }, Spec: v1beta1.IAMPolicyMemberSpec{ Member: &policyMember, ResourceRef: k8sAPI.IAMResourceRef{ APIVersion: resourceAPI.SchemeGroupVersion.String(), Kind: resourceAPI.ProjectGVK.Kind, External: r.ForemanProjectID, }, Role: roles.PubsubAdmin, }, } wiMember := iam.WorkloadIdentityMember(b.Spec.GCP.ProjectID, kccNamespace, kccOperatorName) wiUser := &v1beta1.IAMPolicyMember{ TypeMeta: memberGVK, ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf("%s-workload-id", kccResourceName), Namespace: b.Name, Annotations: map[string]string{ meta.DeletionPolicyAnnotation: meta.DeletionPolicyAbandon, }, OwnerReferences: r.ownerRef(b), }, Spec: v1beta1.IAMPolicyMemberSpec{ Member: &wiMember, ResourceRef: k8sAPI.IAMResourceRef{ APIVersion: v1beta1.SchemeGroupVersion.String(), Kind: v1beta1.IAMServiceAccountGVK.Kind, Name: kccResourceName, }, Role: roles.WorkloadIdentityUser, }, } loggingPolicyMember := iam.LoggingServiceAccountMember(projectNumber) siemPolicyName := fmt.Sprintf("%s-%s", kccResourceName, siemPolicy) siemSinkWriter := &v1beta1.IAMPolicyMember{ TypeMeta: memberGVK, ObjectMeta: metav1.ObjectMeta{ Name: siemPolicyName, Namespace: b.Name, Annotations: map[string]string{ meta.DeletionPolicyAnnotation: meta.DeletionPolicyAbandon, }, OwnerReferences: r.ownerRef(b), }, Spec: v1beta1.IAMPolicyMemberSpec{ Member: &loggingPolicyMember, ResourceRef: k8sAPI.IAMResourceRef{ APIVersion: storageAPI.SchemeGroupVersion.String(), Kind: storageAPI.StorageBucketGVK.Kind, External: fmt.Sprintf("%s-%s", r.ForemanProjectID, siemBucket), }, Role: roles.StorageObjectCreator, }, } return []*v1beta1.IAMPolicyMember{projectOwner, delegatedRoles, pubSubAdmin, wiUser, siemSinkWriter} }