Add Keystone charm
[osm/devops.git] / installers / charm / osm-keystone / src / config.py
1 #!/usr/bin/env python3
2 # Copyright 2021 Canonical Ltd.
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License"); you may
5 # not use this file except in compliance with the License. You may obtain
6 # a copy of the License at
7 #
8 # http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 # License for the specific language governing permissions and limitations
14 # under the License.
15 #
16 # For those usages not covered by the Apache License, Version 2.0 please
17 # contact: legal@canonical.com
18 #
19 # To get in touch with the maintainers, please contact:
20 # osm-charmers@lists.launchpad.net
21 #
22 #
23 # This file populates the Actions tab on Charmhub.
24 # See https://juju.is/docs/some-url-to-be-determined/ for a checklist and guidance.
25
26 """Module that takes take of the charm configuration."""
27
28 import re
29 from typing import Any, Dict, Optional
30
31 from config_validator import ConfigValidator, ValidationError
32 from ops.model import ConfigData
33
34
35 class MysqlConnectionData:
36 """Mysql Connection Data class."""
37
38 _compiled_regex = re.compile(
39 r"^mysql\:\/\/{}@{}\/{}?$".format(
40 r"(?P<username>[_\w]+):(?P<password>[\w\W]+)",
41 r"(?P<host>[\-\.\w]+):(?P<port>\d+)",
42 r"(?P<database>[_\w]+)",
43 )
44 )
45
46 def __init__(self, mysql_uri: str):
47 match = self._compiled_regex.search(mysql_uri)
48 if not match:
49 raise ValidationError("mysql_uri is not properly formed")
50 mysql_data = match.groupdict()
51 self.host = mysql_data.get("host")
52 self.port = int(mysql_data.get("port"))
53 self.username = mysql_data.get("username")
54 self.password = mysql_data.get("password")
55 self.database = mysql_data.get("database")
56 self.uri = mysql_uri
57
58
59 def validate_config(config: ConfigData):
60 """Validate charm configuration.
61
62 Args:
63 config (ConfigData): Charm configuration.
64
65 Raises:
66 config_validator.ValidationError if the validation failed.
67 """
68 kwargs: Dict[str, Any] = config
69 ConfigModel(**kwargs)
70 ConfigLdapModel(**kwargs)
71
72
73 def get_environment(
74 service_name: str, config: ConfigData, mysql_data: MysqlConnectionData
75 ) -> Dict[str, Any]:
76 """Get environment variables.
77
78 Args:
79 service_name (str): Cluster IP service name.
80 config (ConfigData): Charm configuration.
81
82 Returns:
83 Dict[str, Any]: Dictionary with the environment variables for Keystone service.
84 """
85 kwargs: Dict[str, Any] = config
86 config = ConfigModel(**kwargs)
87 config_ldap = ConfigLdapModel(**kwargs)
88 environment = {
89 "DB_HOST": mysql_data.host,
90 "DB_PORT": mysql_data.port,
91 "ROOT_DB_USER": mysql_data.username,
92 "ROOT_DB_PASSWORD": mysql_data.password,
93 "REGION_ID": config.region_id,
94 "KEYSTONE_HOST": service_name,
95 "KEYSTONE_DB_PASSWORD": config.keystone_db_password,
96 "ADMIN_USERNAME": config.admin_username,
97 "ADMIN_PASSWORD": config.admin_password,
98 "ADMIN_PROJECT": config.admin_project,
99 "SERVICE_USERNAME": config.service_username,
100 "SERVICE_PASSWORD": config.service_password,
101 "SERVICE_PROJECT": config.service_project,
102 }
103 if config_ldap.ldap_enabled:
104 environment.update(
105 {
106 "LDAP_AUTHENTICATION_DOMAIN_NAME": config_ldap.ldap_authentication_domain_name,
107 "LDAP_URL": config_ldap.ldap_url,
108 "LDAP_PAGE_SIZE": str(config_ldap.ldap_page_size),
109 "LDAP_USER_OBJECTCLASS": config_ldap.ldap_user_objectclass,
110 "LDAP_USER_ID_ATTRIBUTE": config_ldap.ldap_user_id_attribute,
111 "LDAP_USER_NAME_ATTRIBUTE": config_ldap.ldap_user_name_attribute,
112 "LDAP_USER_PASS_ATTRIBUTE": config_ldap.ldap_user_pass_attribute,
113 "LDAP_USER_ENABLED_MASK": str(config_ldap.ldap_user_enabled_mask),
114 "LDAP_USER_ENABLED_DEFAULT": config_ldap.ldap_user_enabled_default,
115 "LDAP_USER_ENABLED_INVERT": str(config_ldap.ldap_user_enabled_invert),
116 "LDAP_GROUP_OBJECTCLASS": config_ldap.ldap_group_objectclass,
117 }
118 )
119 if config_ldap.ldap_use_starttls:
120 environment.update(
121 {
122 "LDAP_USE_STARTTLS": str(config_ldap.ldap_use_starttls),
123 "LDAP_TLS_CACERT_BASE64": config_ldap.ldap_tls_cacert_base64,
124 "LDAP_TLS_REQ_CERT": config_ldap.ldap_tls_req_cert,
125 }
126 )
127 optional_ldap_configs = {
128 "LDAP_BIND_USER": config_ldap.ldap_bind_user,
129 "LDAP_BIND_PASSWORD": config_ldap.ldap_bind_password,
130 "LDAP_USER_TREE_DN": config_ldap.ldap_user_tree_dn,
131 "LDAP_USER_FILTER": config_ldap.ldap_user_filter,
132 "LDAP_USER_ENABLED_ATTRIBUTE": config_ldap.ldap_user_enabled_attribute,
133 "LDAP_CHASE_REFERRALS": config_ldap.ldap_chase_referrals,
134 "LDAP_GROUP_TREE_DN": config_ldap.ldap_group_tree_dn,
135 "LDAP_TLS_CACERT_BASE64": config_ldap.ldap_tls_cacert_base64,
136 }
137 for env, value in optional_ldap_configs.items():
138 if value:
139 environment[env] = value
140 return environment
141
142
143 class ConfigModel(ConfigValidator):
144 """Keystone Configuration."""
145
146 region_id: str
147 keystone_db_password: str
148 admin_username: str
149 admin_password: str
150 admin_project: str
151 service_username: str
152 service_password: str
153 service_project: str
154 user_domain_name: str
155 project_domain_name: str
156 token_expiration: int
157 mysql_uri: Optional[str]
158
159
160 class ConfigLdapModel(ConfigValidator):
161 """LDAP Configuration."""
162
163 ldap_enabled: bool
164 ldap_authentication_domain_name: Optional[str]
165 ldap_url: Optional[str]
166 ldap_bind_user: Optional[str]
167 ldap_bind_password: Optional[str]
168 ldap_chase_referrals: Optional[str]
169 ldap_page_size: Optional[int]
170 ldap_user_tree_dn: Optional[str]
171 ldap_user_objectclass: Optional[str]
172 ldap_user_id_attribute: Optional[str]
173 ldap_user_name_attribute: Optional[str]
174 ldap_user_pass_attribute: Optional[str]
175 ldap_user_filter: Optional[str]
176 ldap_user_enabled_attribute: Optional[str]
177 ldap_user_enabled_mask: Optional[int]
178 ldap_user_enabled_default: Optional[str]
179 ldap_user_enabled_invert: Optional[bool]
180 ldap_group_objectclass: Optional[str]
181 ldap_group_tree_dn: Optional[str]
182 ldap_use_starttls: Optional[bool]
183 ldap_tls_cacert_base64: Optional[str]
184 ldap_tls_req_cert: Optional[str]