3232import io .fabric8 .kubernetes .api .model .networking .v1 .NetworkPolicyPeer ;
3333import io .fabric8 .kubernetes .api .model .policy .v1 .PodDisruptionBudget ;
3434import io .fabric8 .kubernetes .api .model .rbac .ClusterRoleBinding ;
35+ import io .fabric8 .kubernetes .api .model .rbac .PolicyRule ;
36+ import io .fabric8 .kubernetes .api .model .rbac .PolicyRuleBuilder ;
37+ import io .fabric8 .kubernetes .api .model .rbac .Role ;
38+ import io .fabric8 .kubernetes .api .model .rbac .RoleBinding ;
3539import io .fabric8 .kubernetes .api .model .rbac .RoleRef ;
3640import io .fabric8 .kubernetes .api .model .rbac .RoleRefBuilder ;
3741import io .fabric8 .kubernetes .api .model .rbac .Subject ;
3842import io .fabric8 .kubernetes .api .model .rbac .SubjectBuilder ;
3943import io .fabric8 .openshift .api .model .Route ;
4044import io .fabric8 .openshift .api .model .RouteBuilder ;
41- import io .strimzi .api .kafka .model .common .CertAndKeySecretSource ;
4245import io .strimzi .api .kafka .model .common .Condition ;
4346import io .strimzi .api .kafka .model .common .Rack ;
4447import io .strimzi .api .kafka .model .common .metrics .JmxPrometheusExporterMetrics ;
6366import io .strimzi .api .kafka .model .kafka .listener .GenericKafkaListener ;
6467import io .strimzi .api .kafka .model .kafka .listener .KafkaListenerAuthenticationCustom ;
6568import io .strimzi .api .kafka .model .kafka .listener .KafkaListenerAuthenticationOAuth ;
69+ import io .strimzi .api .kafka .model .kafka .listener .KafkaListenerAuthenticationTls ;
6670import io .strimzi .api .kafka .model .kafka .listener .KafkaListenerType ;
6771import io .strimzi .api .kafka .model .kafka .quotas .QuotasPlugin ;
6872import io .strimzi .api .kafka .model .kafka .quotas .QuotasPluginStrimzi ;
97101import java .util .ArrayList ;
98102import java .util .Collections ;
99103import java .util .HashMap ;
104+ import java .util .HashSet ;
100105import java .util .LinkedHashSet ;
101106import java .util .List ;
102107import java .util .Map ;
@@ -142,6 +147,7 @@ public class KafkaCluster extends AbstractModel implements SupportsMetrics, Supp
142147
143148 protected static final String ENV_VAR_KAFKA_INIT_EXTERNAL_ADDRESS = "EXTERNAL_ADDRESS" ;
144149 private static final String ENV_VAR_KAFKA_JMX_EXPORTER_ENABLED = "KAFKA_JMX_EXPORTER_ENABLED" ;
150+ private static final String ENV_VAR_KAFKA_CLUSTER_NAME = "KAFKA_CLUSTER_NAME" ;
145151 private static final String ENV_VAR_STRIMZI_OPA_AUTHZ_TRUSTED_CERTS = "STRIMZI_OPA_AUTHZ_TRUSTED_CERTS" ;
146152 private static final String ENV_VAR_STRIMZI_KEYCLOAK_AUTHZ_TRUSTED_CERTS = "STRIMZI_KEYCLOAK_AUTHZ_TRUSTED_CERTS" ;
147153
@@ -172,12 +178,6 @@ public class KafkaCluster extends AbstractModel implements SupportsMetrics, Supp
172178 public static final int INGRESS_PORT = 443 ;
173179
174180 protected static final String KAFKA_NAME = "kafka" ;
175- protected static final String CLUSTER_CA_CERTS_VOLUME = "cluster-ca" ;
176- protected static final String BROKER_CERTS_VOLUME = "broker-certs" ;
177- protected static final String CLIENT_CA_CERTS_VOLUME = "client-ca-cert" ;
178- protected static final String CLUSTER_CA_CERTS_VOLUME_MOUNT = "/opt/kafka/cluster-ca-certs" ;
179- protected static final String BROKER_CERTS_VOLUME_MOUNT = "/opt/kafka/broker-certs" ;
180- protected static final String CLIENT_CA_CERTS_VOLUME_MOUNT = "/opt/kafka/client-ca-certs" ;
181181 protected static final String TRUSTED_CERTS_BASE_VOLUME_MOUNT = "/opt/kafka/certificates" ;
182182 protected static final String CUSTOM_AUTHN_SECRETS_VOLUME_MOUNT = "/opt/kafka/custom-authn-secrets" ;
183183 private static final String LOG_AND_METRICS_CONFIG_VOLUME_NAME = "kafka-metrics-and-logging" ;
@@ -1368,9 +1368,6 @@ private List<Volume> getNonDataVolumes(boolean isOpenShift, NodeRef node, PodTem
13681368 List <Volume > volumeList = new ArrayList <>();
13691369
13701370 volumeList .add (VolumeUtils .createTempDirVolume (templatePod ));
1371- volumeList .add (VolumeUtils .createSecretVolume (CLUSTER_CA_CERTS_VOLUME , AbstractModel .clusterCaCertSecretName (cluster ), isOpenShift ));
1372- volumeList .add (VolumeUtils .createSecretVolume (BROKER_CERTS_VOLUME , node .podName (), isOpenShift ));
1373- volumeList .add (VolumeUtils .createSecretVolume (CLIENT_CA_CERTS_VOLUME , KafkaResources .clientsCaCertificateSecretName (cluster ), isOpenShift ));
13741371 volumeList .add (VolumeUtils .createConfigMapVolume (LOG_AND_METRICS_CONFIG_VOLUME_NAME , node .podName ()));
13751372 volumeList .add (VolumeUtils .createEmptyDirVolume ("ready-files" , "1Ki" , "Memory" ));
13761373
@@ -1383,25 +1380,6 @@ private List<Volume> getNonDataVolumes(boolean isOpenShift, NodeRef node, PodTem
13831380
13841381 // Listener specific volumes related to their specific authentication or encryption settings
13851382 for (GenericKafkaListener listener : listeners ) {
1386- if (listener .isTls ()
1387- && listener .getConfiguration () != null
1388- && listener .getConfiguration ().getBrokerCertChainAndKey () != null ) {
1389- CertAndKeySecretSource secretSource = listener .getConfiguration ().getBrokerCertChainAndKey ();
1390-
1391- Map <String , String > items = new HashMap <>(2 );
1392- items .put (secretSource .getKey (), "tls.key" );
1393- items .put (secretSource .getCertificate (), "tls.crt" );
1394-
1395- volumeList .add (
1396- VolumeUtils .createSecretVolume (
1397- "custom-" + ListenersUtils .identifier (listener ) + "-certs" ,
1398- secretSource .getSecretName (),
1399- items ,
1400- isOpenShift
1401- )
1402- );
1403- }
1404-
14051383 if (ListenersUtils .isListenerWithOAuth (listener )) {
14061384 KafkaListenerAuthenticationOAuth oauth = (KafkaListenerAuthenticationOAuth ) listener .getAuth ();
14071385 CertUtils .createTrustedCertificatesVolumes (volumeList , oauth .getTlsTrustedCertificates (), isOpenShift , "oauth-" + ListenersUtils .identifier (listener ));
@@ -1460,9 +1438,6 @@ private List<Volume> getPodSetVolumes(NodeRef node, Storage storage, PodTemplate
14601438 private List <VolumeMount > getVolumeMounts (Storage storage , ContainerTemplate containerTemplate , boolean isBroker ) {
14611439 List <VolumeMount > volumeMountList = new ArrayList <>(VolumeUtils .createVolumeMounts (storage , false ));
14621440 volumeMountList .add (VolumeUtils .createTempDirVolumeMount ());
1463- volumeMountList .add (VolumeUtils .createVolumeMount (CLUSTER_CA_CERTS_VOLUME , CLUSTER_CA_CERTS_VOLUME_MOUNT ));
1464- volumeMountList .add (VolumeUtils .createVolumeMount (BROKER_CERTS_VOLUME , BROKER_CERTS_VOLUME_MOUNT ));
1465- volumeMountList .add (VolumeUtils .createVolumeMount (CLIENT_CA_CERTS_VOLUME , CLIENT_CA_CERTS_VOLUME_MOUNT ));
14661441 volumeMountList .add (VolumeUtils .createVolumeMount (LOG_AND_METRICS_CONFIG_VOLUME_NAME , LOG_AND_METRICS_CONFIG_VOLUME_MOUNT ));
14671442 volumeMountList .add (VolumeUtils .createVolumeMount ("ready-files" , "/var/opt/kafka" ));
14681443
@@ -1477,12 +1452,6 @@ private List<VolumeMount> getVolumeMounts(Storage storage, ContainerTemplate con
14771452 for (GenericKafkaListener listener : listeners ) {
14781453 String identifier = ListenersUtils .identifier (listener );
14791454
1480- if (listener .isTls ()
1481- && listener .getConfiguration () != null
1482- && listener .getConfiguration ().getBrokerCertChainAndKey () != null ) {
1483- volumeMountList .add (VolumeUtils .createVolumeMount ("custom-" + identifier + "-certs" , "/opt/kafka/certificates/custom-" + identifier + "-certs" ));
1484- }
1485-
14861455 if (ListenersUtils .isListenerWithOAuth (listener )) {
14871456 KafkaListenerAuthenticationOAuth oauth = (KafkaListenerAuthenticationOAuth ) listener .getAuth ();
14881457 CertUtils .createTrustedCertificatesVolumeMounts (volumeMountList , oauth .getTlsTrustedCertificates (), TRUSTED_CERTS_BASE_VOLUME_MOUNT + "/oauth-" + identifier + "-certs/" , "oauth-" + identifier );
@@ -1626,6 +1595,7 @@ private List<EnvVar> getEnvVars(KafkaPool pool) {
16261595 varList .add (ContainerUtils .createEnvVar (ENV_VAR_KAFKA_JMX_EXPORTER_ENABLED ,
16271596 String .valueOf (metrics instanceof JmxPrometheusExporterModel )));
16281597 varList .add (ContainerUtils .createEnvVar (ENV_VAR_STRIMZI_KAFKA_GC_LOG_ENABLED , String .valueOf (pool .gcLoggingEnabled )));
1598+ varList .add (ContainerUtils .createEnvVar (ENV_VAR_KAFKA_CLUSTER_NAME , cluster ));
16291599
16301600 JvmOptionUtils .heapOptions (varList , 50 , 5L * 1024L * 1024L * 1024L , pool .jvmOptions , pool .resources );
16311601 JvmOptionUtils .jvmPerformanceOptions (varList , pool .jvmOptions );
@@ -1699,6 +1669,61 @@ public ClusterRoleBinding generateClusterRoleBinding(String assemblyNamespace) {
16991669 }
17001670 }
17011671
1672+ /**
1673+ * Creates a Role for reading TLS certificate secrets in the same namespace as the resource.
1674+ * This is used for loading certificates from secrets directly.
1675+ **
1676+ * @return role for the Kafka Cluster
1677+ */
1678+ public Role generateRole () {
1679+ Set <String > certSecretNames = new HashSet <>();
1680+ certSecretNames .add (KafkaResources .clusterCaCertificateSecretName (cluster ));
1681+ certSecretNames .addAll (nodes ().stream ().map (NodeRef ::podName ).toList ());
1682+
1683+ for (GenericKafkaListener listener : listeners ) {
1684+ if (listener .isTls ()) {
1685+ if (listener .getConfiguration () != null && listener .getConfiguration ().getBrokerCertChainAndKey () != null ) {
1686+ certSecretNames .add (listener .getConfiguration ().getBrokerCertChainAndKey ().getSecretName ());
1687+ }
1688+ }
1689+
1690+ if (listener .getAuth () instanceof KafkaListenerAuthenticationTls ) {
1691+ certSecretNames .add (KafkaResources .clientsCaCertificateSecretName (cluster ));
1692+ }
1693+ }
1694+
1695+ List <PolicyRule > rules = List .of (new PolicyRuleBuilder ()
1696+ .withApiGroups ("" )
1697+ .withResources ("secrets" )
1698+ .withVerbs ("get" )
1699+ .withResourceNames (certSecretNames .stream ().toList ())
1700+ .build ());
1701+
1702+ return RbacUtils .createRole (componentName , namespace , rules , labels , ownerReference , null );
1703+ }
1704+
1705+ /**
1706+ * Generates the Kafka Cluster Role Binding
1707+ *
1708+ * @return Role Binding for the Kafka Cluster
1709+ */
1710+ public RoleBinding generateRoleBindingForRole () {
1711+ Subject subject = new SubjectBuilder ()
1712+ .withKind ("ServiceAccount" )
1713+ .withName (componentName )
1714+ .withNamespace (namespace )
1715+ .build ();
1716+
1717+ RoleRef roleRef = new RoleRefBuilder ()
1718+ .withName (componentName )
1719+ .withApiGroup ("rbac.authorization.k8s.io" )
1720+ .withKind ("Role" )
1721+ .build ();
1722+
1723+ return RbacUtils
1724+ .createRoleBinding (KafkaResources .kafkaRoleBindingName (cluster ), namespace , roleRef , List .of (subject ), labels , ownerReference , null );
1725+ }
1726+
17021727 /**
17031728 * Generates the NetworkPolicies relevant for Kafka brokers
17041729 *
@@ -1828,7 +1853,6 @@ private String generatePerBrokerConfiguration(NodeRef node, KafkaPool pool, Map<
18281853 .withKRaftMetadataLogDir (VolumeUtils .kraftMetadataPath (pool .storage ))
18291854 .withLogDirs (VolumeUtils .createVolumeMounts (pool .storage , false ))
18301855 .withListeners (cluster ,
1831- kafkaVersion ,
18321856 namespace ,
18331857 listeners ,
18341858 listenerId -> advertisedHostnames .get (node .nodeId ()).get (listenerId ),
@@ -1896,6 +1920,18 @@ public List<ConfigMap> generatePerBrokerConfigurationConfigMaps(MetricsAndLoggin
18961920 return configMaps ;
18971921 }
18981922
1923+ /**
1924+ * Generates a Secret with the given name and data in Kafka Cluster's namespace
1925+ *
1926+ * @param secretData Secret data
1927+ * @param secretName Secret name
1928+ *
1929+ * @return Secret that is generated
1930+ */
1931+ public Secret generateSecret (Map <String , String > secretData , String secretName ) {
1932+ return ModelUtils .createSecret (secretName , namespace , labels , ownerReference , secretData , Map .of (), Map .of ());
1933+ }
1934+
18991935 /**
19001936 * @return Kafka version
19011937 */
0 commit comments