From 534e5e210fd423291c3a8a615d29fef452a82564 Mon Sep 17 00:00:00 2001 From: Chris Laprun Date: Wed, 18 Sep 2024 21:42:22 +0200 Subject: [PATCH] Add build item for extensions to contribute ClusterRoleBindings Signed-off-by: Chris Laprun --- .../kind/deployment/KindProcessor.java | 4 +- .../deployment/MinikubeProcessor.java | 4 +- ...KubernetesClusterRoleBindingBuildItem.java | 70 +++++++++++++++++++ .../spi/KubernetesRoleBindingBuildItem.java | 2 +- .../deployment/DevClusterHelper.java | 5 +- .../deployment/KnativeProcessor.java | 4 +- .../deployment/KubernetesCommonHelper.java | 18 ++++- .../deployment/OpenshiftProcessor.java | 5 +- .../VanillaKubernetesProcessor.java | 7 +- 9 files changed, 108 insertions(+), 11 deletions(-) create mode 100644 extensions/kubernetes/spi/src/main/java/io/quarkus/kubernetes/spi/KubernetesClusterRoleBindingBuildItem.java diff --git a/extensions/kubernetes/kind/deployment/src/main/java/io/quarkus/kind/deployment/KindProcessor.java b/extensions/kubernetes/kind/deployment/src/main/java/io/quarkus/kind/deployment/KindProcessor.java index b3b2ce748ddf23..24c23d8ef165b9 100644 --- a/extensions/kubernetes/kind/deployment/src/main/java/io/quarkus/kind/deployment/KindProcessor.java +++ b/extensions/kubernetes/kind/deployment/src/main/java/io/quarkus/kind/deployment/KindProcessor.java @@ -35,6 +35,7 @@ import io.quarkus.kubernetes.spi.CustomProjectRootBuildItem; import io.quarkus.kubernetes.spi.DecoratorBuildItem; import io.quarkus.kubernetes.spi.KubernetesAnnotationBuildItem; +import io.quarkus.kubernetes.spi.KubernetesClusterRoleBindingBuildItem; import io.quarkus.kubernetes.spi.KubernetesClusterRoleBuildItem; import io.quarkus.kubernetes.spi.KubernetesCommandBuildItem; import io.quarkus.kubernetes.spi.KubernetesDeploymentTargetBuildItem; @@ -132,6 +133,7 @@ public List createDecorators(ApplicationInfoBuildItem applic List clusterRoles, List serviceAccounts, List roleBindings, + List clusterRoleBindings, Optional customProjectRoot) { return DevClusterHelper.createDecorators(KIND, KUBERNETES, applicationInfo, outputTarget, config, packageConfig, @@ -139,7 +141,7 @@ public List createDecorators(ApplicationInfoBuildItem applic envs, baseImage, image, command, ports, portName, livenessPath, readinessPath, startupPath, - roles, clusterRoles, serviceAccounts, roleBindings, customProjectRoot); + roles, clusterRoles, serviceAccounts, roleBindings, clusterRoleBindings, customProjectRoot); } @BuildStep diff --git a/extensions/kubernetes/minikube/deployment/src/main/java/io/quarkus/minikube/deployment/MinikubeProcessor.java b/extensions/kubernetes/minikube/deployment/src/main/java/io/quarkus/minikube/deployment/MinikubeProcessor.java index 051514efc49366..c234c062c86ef7 100644 --- a/extensions/kubernetes/minikube/deployment/src/main/java/io/quarkus/minikube/deployment/MinikubeProcessor.java +++ b/extensions/kubernetes/minikube/deployment/src/main/java/io/quarkus/minikube/deployment/MinikubeProcessor.java @@ -32,6 +32,7 @@ import io.quarkus.kubernetes.spi.CustomProjectRootBuildItem; import io.quarkus.kubernetes.spi.DecoratorBuildItem; import io.quarkus.kubernetes.spi.KubernetesAnnotationBuildItem; +import io.quarkus.kubernetes.spi.KubernetesClusterRoleBindingBuildItem; import io.quarkus.kubernetes.spi.KubernetesClusterRoleBuildItem; import io.quarkus.kubernetes.spi.KubernetesCommandBuildItem; import io.quarkus.kubernetes.spi.KubernetesDeploymentTargetBuildItem; @@ -127,6 +128,7 @@ public List createDecorators(ApplicationInfoBuildItem applic List clusterRoles, List serviceAccounts, List roleBindings, + List clusterRoleBindings, Optional customProjectRoot) { return DevClusterHelper.createDecorators(MINIKUBE, KUBERNETES, applicationInfo, outputTarget, config, packageConfig, @@ -134,7 +136,7 @@ public List createDecorators(ApplicationInfoBuildItem applic envs, baseImage, image, command, ports, portName, livenessPath, readinessPath, startupPath, - roles, clusterRoles, serviceAccounts, roleBindings, customProjectRoot); + roles, clusterRoles, serviceAccounts, roleBindings, clusterRoleBindings, customProjectRoot); } @BuildStep diff --git a/extensions/kubernetes/spi/src/main/java/io/quarkus/kubernetes/spi/KubernetesClusterRoleBindingBuildItem.java b/extensions/kubernetes/spi/src/main/java/io/quarkus/kubernetes/spi/KubernetesClusterRoleBindingBuildItem.java new file mode 100644 index 00000000000000..d06892378c8b3d --- /dev/null +++ b/extensions/kubernetes/spi/src/main/java/io/quarkus/kubernetes/spi/KubernetesClusterRoleBindingBuildItem.java @@ -0,0 +1,70 @@ +package io.quarkus.kubernetes.spi; + +import java.util.Collections; +import java.util.Map; + +/** + * Produce this build item to request the Kubernetes extension to generate + * a Kubernetes {@code ClusterRoleBinding} resource. The configuration here is limited; + * in particular, you can't specify subjects of the role binding. The role will always + * be bound to the application's service account. + */ +public final class KubernetesClusterRoleBindingBuildItem extends BaseTargetable { + /** + * Name of the generated {@code RoleBinding} resource. + * Can be {@code null}, in which case the resource name is autogenerated. + */ + private final String name; + /** + * RoleRef configuration. + */ + private final RoleRef roleRef; + /** + * The target subjects. + */ + private final Subject[] subjects; + + /** + * The labels of the cluster role resource. + */ + private final Map labels; + + public KubernetesClusterRoleBindingBuildItem(String role, boolean clusterWide) { + this(null, role, clusterWide, null); + } + + public KubernetesClusterRoleBindingBuildItem(String name, String role, boolean clusterWide) { + this(name, role, clusterWide, null); + } + + public KubernetesClusterRoleBindingBuildItem(String name, String role, boolean clusterWide, String target) { + this(name, target, Collections.emptyMap(), + new RoleRef(role, clusterWide), + new Subject("", "ServiceAccount", name, null)); + } + + public KubernetesClusterRoleBindingBuildItem(String name, String target, Map labels, RoleRef roleRef, + Subject... subjects) { + super(target); + this.name = name; + this.labels = labels; + this.roleRef = roleRef; + this.subjects = subjects; + } + + public String getName() { + return this.name; + } + + public Map getLabels() { + return labels; + } + + public RoleRef getRoleRef() { + return roleRef; + } + + public Subject[] getSubjects() { + return subjects; + } +} diff --git a/extensions/kubernetes/spi/src/main/java/io/quarkus/kubernetes/spi/KubernetesRoleBindingBuildItem.java b/extensions/kubernetes/spi/src/main/java/io/quarkus/kubernetes/spi/KubernetesRoleBindingBuildItem.java index 7187c92d1da7a2..d949b5ba893035 100644 --- a/extensions/kubernetes/spi/src/main/java/io/quarkus/kubernetes/spi/KubernetesRoleBindingBuildItem.java +++ b/extensions/kubernetes/spi/src/main/java/io/quarkus/kubernetes/spi/KubernetesRoleBindingBuildItem.java @@ -9,7 +9,7 @@ * in particular, you can't specify subjects of the role binding. The role will always * be bound to the application's service account. *

- * Note that this can't be used to generate a {@code ClusterRoleBinding}. + * Use {@link KubernetesClusterRoleBindingBuildItem} to generate a {@code ClusterRoleBinding}. */ public final class KubernetesRoleBindingBuildItem extends BaseTargetable { /** diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/DevClusterHelper.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/DevClusterHelper.java index a8260e326e3c49..55326aadf0b7c7 100644 --- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/DevClusterHelper.java +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/DevClusterHelper.java @@ -38,6 +38,7 @@ import io.quarkus.kubernetes.spi.CustomProjectRootBuildItem; import io.quarkus.kubernetes.spi.DecoratorBuildItem; import io.quarkus.kubernetes.spi.KubernetesAnnotationBuildItem; +import io.quarkus.kubernetes.spi.KubernetesClusterRoleBindingBuildItem; import io.quarkus.kubernetes.spi.KubernetesClusterRoleBuildItem; import io.quarkus.kubernetes.spi.KubernetesCommandBuildItem; import io.quarkus.kubernetes.spi.KubernetesEffectiveServiceAccountBuildItem; @@ -86,6 +87,7 @@ public static List createDecorators(String clusterKind, List clusterRoles, List serviceAccounts, List roleBindings, + List clusterRoleBindings, Optional customProjectRoot) { String name = ResourceNameUtil.getResourceName(config, applicationInfo); @@ -100,7 +102,8 @@ public static List createDecorators(String clusterKind, KubernetesCommonHelper.createDecorators(project, clusterKind, name, namespace, config, metricsConfiguration, kubernetesClientConfiguration, annotations, labels, image, command, - port, livenessPath, readinessPath, startupPath, roles, clusterRoles, serviceAccounts, roleBindings)); + port, livenessPath, readinessPath, startupPath, roles, clusterRoles, serviceAccounts, roleBindings, + clusterRoleBindings)); image.ifPresent( i -> result.add(new DecoratorBuildItem(clusterKind, new ApplyContainerImageDecorator(name, i.getImage())))); diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KnativeProcessor.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KnativeProcessor.java index 24962f3c60a66e..0b4a1735461d8e 100644 --- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KnativeProcessor.java +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KnativeProcessor.java @@ -61,6 +61,7 @@ import io.quarkus.kubernetes.spi.CustomProjectRootBuildItem; import io.quarkus.kubernetes.spi.DecoratorBuildItem; import io.quarkus.kubernetes.spi.KubernetesAnnotationBuildItem; +import io.quarkus.kubernetes.spi.KubernetesClusterRoleBindingBuildItem; import io.quarkus.kubernetes.spi.KubernetesClusterRoleBuildItem; import io.quarkus.kubernetes.spi.KubernetesCommandBuildItem; import io.quarkus.kubernetes.spi.KubernetesDeploymentTargetBuildItem; @@ -167,6 +168,7 @@ public List createDecorators(ApplicationInfoBuildItem applic List clusterRoles, List serviceAccounts, List roleBindings, + List clusterRoleBindings, Optional customProjectRoot, List targets) { @@ -187,7 +189,7 @@ public List createDecorators(ApplicationInfoBuildItem applic result.addAll(KubernetesCommonHelper.createDecorators(project, KNATIVE, name, namespace, config, metricsConfiguration, kubernetesClientConfiguration, annotations, labels, image, command, port, livenessPath, readinessPath, startupProbePath, - roles, clusterRoles, serviceAccounts, roleBindings)); + roles, clusterRoles, serviceAccounts, roleBindings, clusterRoleBindings)); image.ifPresent(i -> result.add(new DecoratorBuildItem(KNATIVE, new ApplyContainerImageDecorator(name, i.getImage())))); result.add(new DecoratorBuildItem(KNATIVE, new ApplyImagePullPolicyDecorator(name, config.getImagePullPolicy()))); diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesCommonHelper.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesCommonHelper.java index c0008f7f306152..efd0056b1a63c6 100644 --- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesCommonHelper.java +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesCommonHelper.java @@ -86,6 +86,7 @@ import io.quarkus.kubernetes.spi.CustomProjectRootBuildItem; import io.quarkus.kubernetes.spi.DecoratorBuildItem; import io.quarkus.kubernetes.spi.KubernetesAnnotationBuildItem; +import io.quarkus.kubernetes.spi.KubernetesClusterRoleBindingBuildItem; import io.quarkus.kubernetes.spi.KubernetesClusterRoleBuildItem; import io.quarkus.kubernetes.spi.KubernetesCommandBuildItem; import io.quarkus.kubernetes.spi.KubernetesEffectiveServiceAccountBuildItem; @@ -246,7 +247,8 @@ public static List createDecorators(Optional projec List roles, List clusterRoles, List serviceAccounts, - List roleBindings) { + List roleBindings, + List clusterRoleBindings) { List result = new ArrayList<>(); result.addAll(createLabelDecorators(target, name, config, labels)); @@ -279,7 +281,7 @@ public static List createDecorators(Optional projec // Handle RBAC result.addAll(createRbacDecorators(name, target, config, kubernetesClientConfiguration, roles, clusterRoles, - serviceAccounts, roleBindings)); + serviceAccounts, roleBindings, clusterRoleBindings)); return result; } @@ -289,7 +291,8 @@ private static Collection createRbacDecorators(String name, List rolesFromExtensions, List clusterRolesFromExtensions, List effectiveServiceAccounts, - List roleBindingsFromExtensions) { + List roleBindingsFromExtensions, + List clusterRoleBindingsFromExtensions) { List result = new ArrayList<>(); boolean kubernetesClientRequiresRbacGeneration = kubernetesClientConfiguration .map(KubernetesClientCapabilityBuildItem::isGenerateRbac).orElse(false); @@ -410,6 +413,15 @@ private static Collection createRbacDecorators(String name, subjects.toArray(new Subject[0])))); } + // Add cluster role bindings from extensions + Targetable.filteredByTarget(clusterRoleBindingsFromExtensions, target) + .map(rb -> new DecoratorBuildItem(target, new AddClusterRoleBindingResourceDecorator(name, + Strings.isNotNullOrEmpty(rb.getName()) ? rb.getName() : name + "-" + rb.getRoleRef().getName(), + rb.getLabels(), + rb.getRoleRef(), + rb.getSubjects()))) + .forEach(result::add); + // Add cluster role bindings from configuration for (Map.Entry rb : config.getRbacConfig().clusterRoleBindings.entrySet()) { String rbName = rb.getValue().name.orElse(rb.getKey()); diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/OpenshiftProcessor.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/OpenshiftProcessor.java index 726a7aac568f12..d1ca3db931133b 100644 --- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/OpenshiftProcessor.java +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/OpenshiftProcessor.java @@ -52,6 +52,7 @@ import io.quarkus.kubernetes.spi.CustomProjectRootBuildItem; import io.quarkus.kubernetes.spi.DecoratorBuildItem; import io.quarkus.kubernetes.spi.KubernetesAnnotationBuildItem; +import io.quarkus.kubernetes.spi.KubernetesClusterRoleBindingBuildItem; import io.quarkus.kubernetes.spi.KubernetesClusterRoleBuildItem; import io.quarkus.kubernetes.spi.KubernetesCommandBuildItem; import io.quarkus.kubernetes.spi.KubernetesDeploymentTargetBuildItem; @@ -207,6 +208,7 @@ public List createDecorators(ApplicationInfoBuildItem applic List clusterRoles, List serviceAccounts, List roleBindings, + List clusterRoleBindings, Optional customProjectRoot, List targets) { @@ -226,7 +228,8 @@ public List createDecorators(ApplicationInfoBuildItem applic result.addAll(KubernetesCommonHelper.createDecorators(project, OPENSHIFT, name, namespace, config, metricsConfiguration, kubernetesClientConfiguration, annotations, labels, image, command, - port, livenessPath, readinessPath, startupPath, roles, clusterRoles, serviceAccounts, roleBindings)); + port, livenessPath, readinessPath, startupPath, roles, clusterRoles, serviceAccounts, roleBindings, + clusterRoleBindings)); if (config.flavor == v3) { //Openshift 3.x doesn't recognize 'app.kubernetes.io/name', it uses 'app' instead. diff --git a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/VanillaKubernetesProcessor.java b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/VanillaKubernetesProcessor.java index d42b935976b0c6..d75c3dbca7402e 100644 --- a/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/VanillaKubernetesProcessor.java +++ b/extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/VanillaKubernetesProcessor.java @@ -49,6 +49,7 @@ import io.quarkus.kubernetes.spi.CustomProjectRootBuildItem; import io.quarkus.kubernetes.spi.DecoratorBuildItem; import io.quarkus.kubernetes.spi.KubernetesAnnotationBuildItem; +import io.quarkus.kubernetes.spi.KubernetesClusterRoleBindingBuildItem; import io.quarkus.kubernetes.spi.KubernetesClusterRoleBuildItem; import io.quarkus.kubernetes.spi.KubernetesCommandBuildItem; import io.quarkus.kubernetes.spi.KubernetesDeploymentTargetBuildItem; @@ -164,7 +165,9 @@ public List createDecorators(ApplicationInfoBuildItem applic List roles, List clusterRoles, List serviceAccounts, - List roleBindings, Optional customProjectRoot, + List roleBindings, + List clusterRoleBindings, + Optional customProjectRoot, List targets) { final List result = new ArrayList<>(); @@ -182,7 +185,7 @@ public List createDecorators(ApplicationInfoBuildItem applic result.addAll(KubernetesCommonHelper.createDecorators(project, KUBERNETES, name, namespace, config, metricsConfiguration, kubernetesClientConfiguration, annotations, labels, image, command, port, livenessPath, readinessPath, startupPath, - roles, clusterRoles, serviceAccounts, roleBindings)); + roles, clusterRoles, serviceAccounts, roleBindings, clusterRoleBindings)); DeploymentResourceKind deploymentKind = config.getDeploymentResourceKind(capabilities); if (deploymentKind != DeploymentResourceKind.Deployment) {