| #!/usr/bin/env python3 |
| # Copyright 2021 Canonical Ltd. |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); you may |
| # not use this file except in compliance with the License. You may obtain |
| # a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| # License for the specific language governing permissions and limitations |
| # under the License. |
| # |
| # For those usages not covered by the Apache License, Version 2.0 please |
| # contact: legal@canonical.com |
| # |
| # To get in touch with the maintainers, please contact: |
| # osm-charmers@lists.launchpad.net |
| # |
| # |
| # This file populates the Actions tab on Charmhub. |
| # See https://juju.is/docs/some-url-to-be-determined/ for a checklist and guidance. |
| |
| """Module that takes take of the charm configuration.""" |
| |
| import re |
| from typing import Any, Dict, Optional |
| |
| from config_validator import ConfigValidator, ValidationError |
| from ops.model import ConfigData |
| |
| |
| class MysqlConnectionData: |
| """Mysql Connection Data class.""" |
| |
| _compiled_regex = re.compile( |
| r"^mysql\:\/\/{}@{}\/{}?$".format( |
| r"(?P<username>[_\w]+):(?P<password>[\w\W]+)", |
| r"(?P<host>[\-\.\w]+):(?P<port>\d+)", |
| r"(?P<database>[_\w]+)", |
| ) |
| ) |
| |
| def __init__(self, mysql_uri: str): |
| match = self._compiled_regex.search(mysql_uri) |
| if not match: |
| raise ValidationError("mysql_uri is not properly formed") |
| mysql_data = match.groupdict() |
| self.host = mysql_data.get("host") |
| self.port = int(mysql_data.get("port")) |
| self.username = mysql_data.get("username") |
| self.password = mysql_data.get("password") |
| self.database = mysql_data.get("database") |
| self.uri = mysql_uri |
| |
| |
| def validate_config(config: ConfigData): |
| """Validate charm configuration. |
| |
| Args: |
| config (ConfigData): Charm configuration. |
| |
| Raises: |
| config_validator.ValidationError if the validation failed. |
| """ |
| kwargs: Dict[str, Any] = config |
| ConfigModel(**kwargs) |
| ConfigLdapModel(**kwargs) |
| |
| |
| def get_environment( |
| service_name: str, config: ConfigData, mysql_data: MysqlConnectionData |
| ) -> Dict[str, Any]: |
| """Get environment variables. |
| |
| Args: |
| service_name (str): Cluster IP service name. |
| config (ConfigData): Charm configuration. |
| |
| Returns: |
| Dict[str, Any]: Dictionary with the environment variables for Keystone service. |
| """ |
| kwargs: Dict[str, Any] = config |
| config = ConfigModel(**kwargs) |
| config_ldap = ConfigLdapModel(**kwargs) |
| environment = { |
| "DB_HOST": mysql_data.host, |
| "DB_PORT": mysql_data.port, |
| "ROOT_DB_USER": mysql_data.username, |
| "ROOT_DB_PASSWORD": mysql_data.password, |
| "REGION_ID": config.region_id, |
| "KEYSTONE_HOST": service_name, |
| "KEYSTONE_DB_PASSWORD": config.keystone_db_password, |
| "ADMIN_USERNAME": config.admin_username, |
| "ADMIN_PASSWORD": config.admin_password, |
| "ADMIN_PROJECT": config.admin_project, |
| "SERVICE_USERNAME": config.service_username, |
| "SERVICE_PASSWORD": config.service_password, |
| "SERVICE_PROJECT": config.service_project, |
| } |
| if config_ldap.ldap_enabled: |
| environment.update( |
| { |
| "LDAP_AUTHENTICATION_DOMAIN_NAME": config_ldap.ldap_authentication_domain_name, |
| "LDAP_URL": config_ldap.ldap_url, |
| "LDAP_PAGE_SIZE": str(config_ldap.ldap_page_size), |
| "LDAP_USER_OBJECTCLASS": config_ldap.ldap_user_objectclass, |
| "LDAP_USER_ID_ATTRIBUTE": config_ldap.ldap_user_id_attribute, |
| "LDAP_USER_NAME_ATTRIBUTE": config_ldap.ldap_user_name_attribute, |
| "LDAP_USER_PASS_ATTRIBUTE": config_ldap.ldap_user_pass_attribute, |
| "LDAP_USER_ENABLED_MASK": str(config_ldap.ldap_user_enabled_mask), |
| "LDAP_USER_ENABLED_DEFAULT": config_ldap.ldap_user_enabled_default, |
| "LDAP_USER_ENABLED_INVERT": str(config_ldap.ldap_user_enabled_invert), |
| "LDAP_GROUP_OBJECTCLASS": config_ldap.ldap_group_objectclass, |
| } |
| ) |
| if config_ldap.ldap_use_starttls: |
| environment.update( |
| { |
| "LDAP_USE_STARTTLS": str(config_ldap.ldap_use_starttls), |
| "LDAP_TLS_CACERT_BASE64": config_ldap.ldap_tls_cacert_base64, |
| "LDAP_TLS_REQ_CERT": config_ldap.ldap_tls_req_cert, |
| } |
| ) |
| optional_ldap_configs = { |
| "LDAP_BIND_USER": config_ldap.ldap_bind_user, |
| "LDAP_BIND_PASSWORD": config_ldap.ldap_bind_password, |
| "LDAP_USER_TREE_DN": config_ldap.ldap_user_tree_dn, |
| "LDAP_USER_FILTER": config_ldap.ldap_user_filter, |
| "LDAP_USER_ENABLED_ATTRIBUTE": config_ldap.ldap_user_enabled_attribute, |
| "LDAP_CHASE_REFERRALS": config_ldap.ldap_chase_referrals, |
| "LDAP_GROUP_TREE_DN": config_ldap.ldap_group_tree_dn, |
| "LDAP_TLS_CACERT_BASE64": config_ldap.ldap_tls_cacert_base64, |
| } |
| for env, value in optional_ldap_configs.items(): |
| if value: |
| environment[env] = value |
| return environment |
| |
| |
| class ConfigModel(ConfigValidator): |
| """Keystone Configuration.""" |
| |
| region_id: str |
| keystone_db_password: str |
| admin_username: str |
| admin_password: str |
| admin_project: str |
| service_username: str |
| service_password: str |
| service_project: str |
| user_domain_name: str |
| project_domain_name: str |
| token_expiration: int |
| mysql_uri: Optional[str] |
| |
| |
| class ConfigLdapModel(ConfigValidator): |
| """LDAP Configuration.""" |
| |
| ldap_enabled: bool |
| ldap_authentication_domain_name: Optional[str] |
| ldap_url: Optional[str] |
| ldap_bind_user: Optional[str] |
| ldap_bind_password: Optional[str] |
| ldap_chase_referrals: Optional[str] |
| ldap_page_size: Optional[int] |
| ldap_user_tree_dn: Optional[str] |
| ldap_user_objectclass: Optional[str] |
| ldap_user_id_attribute: Optional[str] |
| ldap_user_name_attribute: Optional[str] |
| ldap_user_pass_attribute: Optional[str] |
| ldap_user_filter: Optional[str] |
| ldap_user_enabled_attribute: Optional[str] |
| ldap_user_enabled_mask: Optional[int] |
| ldap_user_enabled_default: Optional[str] |
| ldap_user_enabled_invert: Optional[bool] |
| ldap_group_objectclass: Optional[str] |
| ldap_group_tree_dn: Optional[str] |
| ldap_use_starttls: Optional[bool] |
| ldap_tls_cacert_base64: Optional[str] |
| ldap_tls_req_cert: Optional[str] |