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" ;
@@ -1363,9 +1363,6 @@ private List<Volume> getNonDataVolumes(boolean isOpenShift, NodeRef node, PodTem
13631363 List <Volume > volumeList = new ArrayList <>();
13641364
13651365 volumeList .add (VolumeUtils .createTempDirVolume (templatePod ));
1366- volumeList .add (VolumeUtils .createSecretVolume (CLUSTER_CA_CERTS_VOLUME , AbstractModel .clusterCaCertSecretName (cluster ), isOpenShift ));
1367- volumeList .add (VolumeUtils .createSecretVolume (BROKER_CERTS_VOLUME , node .podName (), isOpenShift ));
1368- volumeList .add (VolumeUtils .createSecretVolume (CLIENT_CA_CERTS_VOLUME , KafkaResources .clientsCaCertificateSecretName (cluster ), isOpenShift ));
13691366 volumeList .add (VolumeUtils .createConfigMapVolume (LOG_AND_METRICS_CONFIG_VOLUME_NAME , node .podName ()));
13701367 volumeList .add (VolumeUtils .createEmptyDirVolume ("ready-files" , "1Ki" , "Memory" ));
13711368
@@ -1378,25 +1375,6 @@ private List<Volume> getNonDataVolumes(boolean isOpenShift, NodeRef node, PodTem
13781375
13791376 // Listener specific volumes related to their specific authentication or encryption settings
13801377 for (GenericKafkaListener listener : listeners ) {
1381- if (listener .isTls ()
1382- && listener .getConfiguration () != null
1383- && listener .getConfiguration ().getBrokerCertChainAndKey () != null ) {
1384- CertAndKeySecretSource secretSource = listener .getConfiguration ().getBrokerCertChainAndKey ();
1385-
1386- Map <String , String > items = new HashMap <>(2 );
1387- items .put (secretSource .getKey (), "tls.key" );
1388- items .put (secretSource .getCertificate (), "tls.crt" );
1389-
1390- volumeList .add (
1391- VolumeUtils .createSecretVolume (
1392- "custom-" + ListenersUtils .identifier (listener ) + "-certs" ,
1393- secretSource .getSecretName (),
1394- items ,
1395- isOpenShift
1396- )
1397- );
1398- }
1399-
14001378 if (ListenersUtils .isListenerWithOAuth (listener )) {
14011379 KafkaListenerAuthenticationOAuth oauth = (KafkaListenerAuthenticationOAuth ) listener .getAuth ();
14021380 CertUtils .createTrustedCertificatesVolumes (volumeList , oauth .getTlsTrustedCertificates (), isOpenShift , "oauth-" + ListenersUtils .identifier (listener ));
@@ -1455,9 +1433,6 @@ private List<Volume> getPodSetVolumes(NodeRef node, Storage storage, PodTemplate
14551433 private List <VolumeMount > getVolumeMounts (Storage storage , ContainerTemplate containerTemplate , boolean isBroker ) {
14561434 List <VolumeMount > volumeMountList = new ArrayList <>(VolumeUtils .createVolumeMounts (storage , false ));
14571435 volumeMountList .add (VolumeUtils .createTempDirVolumeMount ());
1458- volumeMountList .add (VolumeUtils .createVolumeMount (CLUSTER_CA_CERTS_VOLUME , CLUSTER_CA_CERTS_VOLUME_MOUNT ));
1459- volumeMountList .add (VolumeUtils .createVolumeMount (BROKER_CERTS_VOLUME , BROKER_CERTS_VOLUME_MOUNT ));
1460- volumeMountList .add (VolumeUtils .createVolumeMount (CLIENT_CA_CERTS_VOLUME , CLIENT_CA_CERTS_VOLUME_MOUNT ));
14611436 volumeMountList .add (VolumeUtils .createVolumeMount (LOG_AND_METRICS_CONFIG_VOLUME_NAME , LOG_AND_METRICS_CONFIG_VOLUME_MOUNT ));
14621437 volumeMountList .add (VolumeUtils .createVolumeMount ("ready-files" , "/var/opt/kafka" ));
14631438
@@ -1472,12 +1447,6 @@ private List<VolumeMount> getVolumeMounts(Storage storage, ContainerTemplate con
14721447 for (GenericKafkaListener listener : listeners ) {
14731448 String identifier = ListenersUtils .identifier (listener );
14741449
1475- if (listener .isTls ()
1476- && listener .getConfiguration () != null
1477- && listener .getConfiguration ().getBrokerCertChainAndKey () != null ) {
1478- volumeMountList .add (VolumeUtils .createVolumeMount ("custom-" + identifier + "-certs" , "/opt/kafka/certificates/custom-" + identifier + "-certs" ));
1479- }
1480-
14811450 if (ListenersUtils .isListenerWithOAuth (listener )) {
14821451 KafkaListenerAuthenticationOAuth oauth = (KafkaListenerAuthenticationOAuth ) listener .getAuth ();
14831452 CertUtils .createTrustedCertificatesVolumeMounts (volumeMountList , oauth .getTlsTrustedCertificates (), TRUSTED_CERTS_BASE_VOLUME_MOUNT + "/oauth-" + identifier + "-certs/" , "oauth-" + identifier );
@@ -1621,6 +1590,7 @@ private List<EnvVar> getEnvVars(KafkaPool pool) {
16211590 varList .add (ContainerUtils .createEnvVar (ENV_VAR_KAFKA_JMX_EXPORTER_ENABLED ,
16221591 String .valueOf (metrics instanceof JmxPrometheusExporterModel )));
16231592 varList .add (ContainerUtils .createEnvVar (ENV_VAR_STRIMZI_KAFKA_GC_LOG_ENABLED , String .valueOf (pool .gcLoggingEnabled )));
1593+ varList .add (ContainerUtils .createEnvVar (ENV_VAR_KAFKA_CLUSTER_NAME , cluster ));
16241594
16251595 JvmOptionUtils .heapOptions (varList , 50 , 5L * 1024L * 1024L * 1024L , pool .jvmOptions , pool .resources );
16261596 JvmOptionUtils .jvmPerformanceOptions (varList , pool .jvmOptions );
@@ -1694,6 +1664,61 @@ public ClusterRoleBinding generateClusterRoleBinding(String assemblyNamespace) {
16941664 }
16951665 }
16961666
1667+ /**
1668+ * Creates a Role for reading TLS certificate secrets in the same namespace as the resource.
1669+ * This is used for loading certificates from secrets directly.
1670+ **
1671+ * @return role for the Kafka Cluster
1672+ */
1673+ public Role generateRole () {
1674+ Set <String > certSecretNames = new HashSet <>();
1675+ certSecretNames .add (KafkaResources .clusterCaCertificateSecretName (cluster ));
1676+ certSecretNames .addAll (nodes ().stream ().map (NodeRef ::podName ).toList ());
1677+
1678+ for (GenericKafkaListener listener : listeners ) {
1679+ if (listener .isTls ()) {
1680+ if (listener .getConfiguration () != null && listener .getConfiguration ().getBrokerCertChainAndKey () != null ) {
1681+ certSecretNames .add (listener .getConfiguration ().getBrokerCertChainAndKey ().getSecretName ());
1682+ }
1683+ }
1684+
1685+ if (listener .getAuth () instanceof KafkaListenerAuthenticationTls ) {
1686+ certSecretNames .add (KafkaResources .clientsCaCertificateSecretName (cluster ));
1687+ }
1688+ }
1689+
1690+ List <PolicyRule > rules = List .of (new PolicyRuleBuilder ()
1691+ .withApiGroups ("" )
1692+ .withResources ("secrets" )
1693+ .withVerbs ("get" )
1694+ .withResourceNames (certSecretNames .stream ().toList ())
1695+ .build ());
1696+
1697+ return RbacUtils .createRole (componentName , namespace , rules , labels , ownerReference , null );
1698+ }
1699+
1700+ /**
1701+ * Generates the Kafka Cluster Role Binding
1702+ *
1703+ * @return Role Binding for the Kafka Cluster
1704+ */
1705+ public RoleBinding generateRoleBindingForRole () {
1706+ Subject subject = new SubjectBuilder ()
1707+ .withKind ("ServiceAccount" )
1708+ .withName (componentName )
1709+ .withNamespace (namespace )
1710+ .build ();
1711+
1712+ RoleRef roleRef = new RoleRefBuilder ()
1713+ .withName (componentName )
1714+ .withApiGroup ("rbac.authorization.k8s.io" )
1715+ .withKind ("Role" )
1716+ .build ();
1717+
1718+ return RbacUtils
1719+ .createRoleBinding (KafkaResources .kafkaRoleBindingName (cluster ), namespace , roleRef , List .of (subject ), labels , ownerReference , null );
1720+ }
1721+
16971722 /**
16981723 * Generates the NetworkPolicies relevant for Kafka brokers
16991724 *
@@ -1823,7 +1848,6 @@ private String generatePerBrokerConfiguration(NodeRef node, KafkaPool pool, Map<
18231848 .withKRaftMetadataLogDir (VolumeUtils .kraftMetadataPath (pool .storage ))
18241849 .withLogDirs (VolumeUtils .createVolumeMounts (pool .storage , false ))
18251850 .withListeners (cluster ,
1826- kafkaVersion ,
18271851 namespace ,
18281852 listeners ,
18291853 listenerId -> advertisedHostnames .get (node .nodeId ()).get (listenerId ),
@@ -1881,6 +1905,18 @@ public List<ConfigMap> generatePerBrokerConfigurationConfigMaps(MetricsAndLoggin
18811905 return configMaps ;
18821906 }
18831907
1908+ /**
1909+ * Generates a Secret with the given name and data in Kafka Cluster's namespace
1910+ *
1911+ * @param secretData Secret data
1912+ * @param secretName Secret name
1913+ *
1914+ * @return Secret that is generated
1915+ */
1916+ public Secret generateSecret (Map <String , String > secretData , String secretName ) {
1917+ return ModelUtils .createSecret (secretName , namespace , labels , ownerReference , secretData , Map .of (), Map .of ());
1918+ }
1919+
18841920 /**
18851921 * @return Kafka version
18861922 */
0 commit comments