Fix bug 1571 - Keystone charm needs to pass CA SSL certificate
[osm/devops.git] / installers / charm / keystone / src / charm.py
index 5d8d317..8300b88 100755 (executable)
@@ -80,6 +80,9 @@ class ConfigModel(ModelValidator):
     site_url: Optional[str]
     ingress_whitelist_source_range: Optional[str]
     tls_secret_name: Optional[str]
+    mysql_host: Optional[str]
+    mysql_port: Optional[int]
+    mysql_root_password: Optional[str]
 
     @validator("max_file_size")
     def validate_max_file_size(cls, v):
@@ -101,6 +104,12 @@ class ConfigModel(ModelValidator):
             ip_network(v)
         return v
 
+    @validator("mysql_port")
+    def validate_mysql_port(cls, v):
+        if v and (v <= 0 or v >= 65535):
+            raise ValueError("Mysql port out of range")
+        return v
+
 
 class ConfigLdapModel(ModelValidator):
     ldap_enabled: bool
@@ -170,11 +179,19 @@ class KeystoneCharm(CharmedOsmBase):
 
     def _check_missing_dependencies(self, config: ConfigModel):
         missing_relations = []
-        if self.mysql_client.is_missing_data_in_unit():
+        if not config.mysql_host and self.mysql_client.is_missing_data_in_unit():
             missing_relations.append("mysql")
         if missing_relations:
             raise RelationsMissing(missing_relations)
 
+    def _validate_mysql_config(self, config: ConfigModel):
+        invalid_values = []
+        if not config.mysql_root_password:
+            invalid_values.append("Mysql root password must be provided")
+
+        if invalid_values:
+            raise ValueError("Invalid values: " + ", ".join(invalid_values))
+
     def _generate_keys(self) -> Tuple[List[str], List[str]]:
         """Generating new fernet tokens.
 
@@ -229,13 +246,23 @@ class KeystoneCharm(CharmedOsmBase):
         # Validate config
         config = ConfigModel(**dict(self.config))
         config_ldap = ConfigLdapModel(**dict(self.config))
+
+        if config.mysql_host and not self.mysql_client.is_missing_data_in_unit():
+            raise Exception("Mysql data cannot be provided via config and relation")
+
+        if config.mysql_host:
+            self._validate_mysql_config(config)
+
         # Check relations
         self._check_missing_dependencies(config)
+
         # Create Builder for the PodSpec
         pod_spec_builder = PodSpecV3Builder()
+
         # Build Container
         container_builder = ContainerV3Builder(self.app.name, image_info)
         container_builder.add_port(name=self.app.name, port=PORT)
+
         # Build files
         credential_files, fernet_files = self._build_files(config)
         container_builder.add_volume_config(
@@ -246,10 +273,11 @@ class KeystoneCharm(CharmedOsmBase):
         )
         container_builder.add_envs(
             {
-                "DB_HOST": self.mysql_client.host,
-                "DB_PORT": self.mysql_client.port,
+                "DB_HOST": config.mysql_host or self.mysql_client.host,
+                "DB_PORT": config.mysql_port or self.mysql_client.port,
                 "ROOT_DB_USER": "root",
-                "ROOT_DB_PASSWORD": self.mysql_client.root_password,
+                "ROOT_DB_PASSWORD": config.mysql_root_password
+                or self.mysql_client.root_password,
                 "KEYSTONE_DB_PASSWORD": config.keystone_db_password,
                 "REGION_ID": config.region_id,
                 "KEYSTONE_HOST": self.app.name,
@@ -263,7 +291,6 @@ class KeystoneCharm(CharmedOsmBase):
         )
 
         if config_ldap.ldap_enabled:
-
             container_builder.add_envs(
                 {
                     "LDAP_AUTHENTICATION_DOMAIN_NAME": config_ldap.ldap_authentication_domain_name,
@@ -316,6 +343,11 @@ class KeystoneCharm(CharmedOsmBase):
                     {"LDAP_GROUP_TREE_DN": config_ldap.ldap_group_tree_dn}
                 )
 
+            if config_ldap.ldap_tls_cacert_base64:
+                container_builder.add_envs(
+                    {"LDAP_TLS_CACERT_BASE64": config_ldap.ldap_tls_cacert_base64}
+                )
+
             if config_ldap.ldap_use_starttls:
                 container_builder.add_envs(
                     {
@@ -325,8 +357,10 @@ class KeystoneCharm(CharmedOsmBase):
                     }
                 )
         container = container_builder.build()
+
         # Add container to pod spec
         pod_spec_builder.add_container(container)
+
         # Add ingress resources to pod spec if site url exists
         if config.site_url:
             parsed = urlparse(config.site_url)
@@ -336,6 +370,7 @@ class KeystoneCharm(CharmedOsmBase):
                     if config.max_file_size > 0
                     else config.max_file_size
                 ),
+                "kubernetes.io/ingress.class": "public",
             }
             ingress_resource_builder = IngressResourceV3Builder(
                 f"{self.app.name}-ingress", annotations