Repository: quarkusio/quarkus
Issue: Generating Role or ClusterRole resources with empty API group property produces invalid manifests

### Describe the bug

When generating a Role or a ClusterRole resource like:
```
quarkus.kubernetes.rbac.cluster-roles.secret-reader.policy-rules.0.resources=secrets
quarkus.kubernetes.rbac.cluster-roles.secret-reader.policy-rules.0.verbs=get,watch,list
```

Produces the following resource:

```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: secret-reader
rules:
  - resources:
      - secrets
    verbs:
      - get
      - watch
      - list
```

This is invalid because the `apiGroups` field in the rule is mandatory and it's not added by default (because it's null). 


### Expected behavior

When users do not set the `api-groups`, it should use a list with an empty element, to produce:

```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: secret-reader
rules:
  - resources:
      - secrets
    apiGroups: [""]
    verbs:
      - get
      - watch
      - list
```

More context in this comment: https://github.com/quarkusio/quarkus/pull/31797#issuecomment-1497311563

### Actual behavior

_No response_

### How to Reproduce?

_No response_

### Output of `uname -a` or `ver`

_No response_

### Output of `java -version`

_No response_

### GraalVM version (if different from Java)

_No response_

### Quarkus version or git rev

_No response_

### Build tool (ie. output of `mvnw --version` or `gradlew --version`)

_No response_

### Additional information

_No response_

Changed files:
extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KubernetesCommonHelper.java
integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesWithRbacFullTest.java

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 1eac16be796..ec91ba8b7f9 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
@@ -104,6 +104,7 @@ public class KubernetesCommonHelper {
     private static final String[] PROMETHEUS_ANNOTATION_TARGETS = { "Service",
             "Deployment", "DeploymentConfig" };
     private static final String DEFAULT_ROLE_NAME_VIEW = "view";
+    private static final List<String> LIST_WITH_EMPTY = List.of("");
 
     public static Optional<Project> createProject(ApplicationInfoBuildItem app,
             Optional<CustomProjectRootBuildItem> customProjectRoot, OutputTargetBuildItem outputTarget,
@@ -1011,7 +1012,7 @@ private static List<PolicyRule> toPolicyRulesList(Map<String, PolicyRuleConfig>
         return policyRules.values()
                 .stream()
                 .map(it -> new PolicyRuleBuilder()
-                        .withApiGroups(it.apiGroups.orElse(null))
+                        .withApiGroups(it.apiGroups.orElse(LIST_WITH_EMPTY))
                         .withNonResourceURLs(it.nonResourceUrls.orElse(null))
                         .withResourceNames(it.resourceNames.orElse(null))
                         .withResources(it.resources.orElse(null))
diff --git a/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesWithRbacFullTest.java b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesWithRbacFullTest.java
index 3ff3de62fb5..e93f96d6054 100644
--- a/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesWithRbacFullTest.java
+++ b/integration-tests/kubernetes/quarkus-standard-way/src/test/java/io/quarkus/it/kubernetes/KubernetesWithRbacFullTest.java
@@ -61,6 +61,7 @@ public void assertGeneratedResources() throws IOException {
         Role podWriterRole = getRoleByName(kubernetesList, "pod-writer");
         assertEquals(APP_NAMESPACE, podWriterRole.getMetadata().getNamespace());
         assertThat(podWriterRole.getRules()).satisfiesOnlyOnce(r -> {
+            assertThat(r.getApiGroups()).containsExactly("");
             assertThat(r.getResources()).containsExactly("pods");
             assertThat(r.getVerbs()).containsExactly("update");
         });
@@ -69,6 +70,7 @@ public void assertGeneratedResources() throws IOException {
         Role podReaderRole = getRoleByName(kubernetesList, "pod-reader");
         assertEquals("projectb", podReaderRole.getMetadata().getNamespace());
         assertThat(podReaderRole.getRules()).satisfiesOnlyOnce(r -> {
+            assertThat(r.getApiGroups()).containsExactly("");
             assertThat(r.getResources()).containsExactly("pods");
             assertThat(r.getVerbs()).containsExactly("get", "watch", "list");
         });
@@ -76,6 +78,7 @@ public void assertGeneratedResources() throws IOException {
         // secret-reader assertions
         ClusterRole secretReaderRole = getClusterRoleByName(kubernetesList, "secret-reader");
         assertThat(secretReaderRole.getRules()).satisfiesOnlyOnce(r -> {
+            assertThat(r.getApiGroups()).containsExactly("");
             assertThat(r.getResources()).containsExactly("secrets");
             assertThat(r.getVerbs()).containsExactly("get", "watch", "list");
         });