1- """Configuration management for IDP """
1+ """Configuration management for OP """
22import copy
3- import importlib
4- import json
53import logging
64import os
75from typing import Dict
86from typing import List
97from typing import Optional
10- from typing import Union
118
12- from oidcop .logging import configure_logging
9+ from oidcmsg .configure import Base
10+
1311from oidcop .scopes import SCOPE2CLAIMS
14- from oidcop .utils import load_yaml_config
1512
1613logger = logging .getLogger (__name__ )
1714
18-
19- DEFAULT_FILE_ATTRIBUTE_NAMES = [
20- "server_key" ,
21- "server_cert" ,
22- "filename" ,
23- "template_dir" ,
24- "private_path" ,
25- "public_path" ,
26- "db_file" ,
27- "jwks_file" ,
28- ]
29-
3015OP_DEFAULT_CONFIG = {
3116 "capabilities" : {
3217 "subject_types_supported" : ["public" , "pairwise" ],
10590}
10691
10792
108- def add_base_path (conf : Union [dict , str ], base_path : str , file_attributes : List [str ]):
109- if isinstance (conf , str ):
110- if conf .startswith ("/" ):
111- pass
112- elif conf == "" :
113- conf = "./" + conf
114- else :
115- conf = os .path .join (base_path , conf )
116- elif isinstance (conf , dict ):
117- for key , val in conf .items ():
118- if key in file_attributes :
119- if val .startswith ("/" ):
120- continue
121- elif val == "" :
122- conf [key ] = "./" + val
123- else :
124- conf [key ] = os .path .join (base_path , val )
125- if isinstance (val , dict ):
126- conf [key ] = add_base_path (val , base_path , file_attributes )
127-
128- return conf
129-
130-
131- def set_domain_and_port (conf : dict , uris : List [str ], domain : str , port : int ):
132- for key , val in conf .items ():
133- if key in uris :
134- if isinstance (val , list ):
135- _new = [v .format (domain = domain , port = port ) for v in val ]
136- else :
137- _new = val .format (domain = domain , port = port )
138- conf [key ] = _new
139- elif isinstance (val , dict ):
140- conf [key ] = set_domain_and_port (val , uris , domain , port )
141- return conf
142-
143-
144- def create_from_config_file (
145- cls ,
146- filename : str ,
147- base_path : str = "" ,
148- entity_conf : Optional [List [dict ]] = None ,
149- file_attributes : Optional [List [str ]] = None ,
150- domain : Optional [str ] = "" ,
151- port : Optional [int ] = 0 ,
152- ):
153- if filename .endswith (".yaml" ):
154- """Load configuration as YAML"""
155- _conf = load_yaml_config (filename )
156- elif filename .endswith (".json" ):
157- _str = open (filename ).read ()
158- _conf = json .loads (_str )
159- elif filename .endswith (".py" ):
160- head , tail = os .path .split (filename )
161- tail = tail [:- 3 ]
162- module = importlib .import_module (tail )
163- _conf = getattr (module , "OIDCOP_CONFIG" )
164- else :
165- raise ValueError ("Unknown file type" )
166-
167- return cls (
168- _conf ,
169- entity_conf = entity_conf ,
170- base_path = base_path ,
171- file_attributes = file_attributes ,
172- domain = domain ,
173- port = port ,
174- )
175-
176-
177- class Base (dict ):
178- """ Configuration base class """
179-
180- parameter = {}
181-
182- def __init__ (
183- self ,
184- conf : Dict ,
185- base_path : str = "" ,
186- file_attributes : Optional [List [str ]] = None ,
187- ):
188- dict .__init__ (self )
189-
190- if file_attributes is None :
191- file_attributes = DEFAULT_FILE_ATTRIBUTE_NAMES
192-
193- if base_path and file_attributes :
194- # this adds a base path to all paths in the configuration
195- add_base_path (conf , base_path , file_attributes )
196-
197- def __getattr__ (self , item ):
198- return self [item ]
199-
200- def __setattr__ (self , key , value ):
201- if key in self :
202- raise KeyError ("{} has already been set" .format (key ))
203- super (Base , self ).__setitem__ (key , value )
204-
205- def __setitem__ (self , key , value ):
206- if key in self :
207- raise KeyError ("{} has already been set" .format (key ))
208- super (Base , self ).__setitem__ (key , value )
209-
210-
21193class EntityConfiguration (Base ):
21294 default_config = AS_DEFAULT_CONFIG
21395 uris = ["issuer" , "base_url" ]
@@ -231,26 +113,18 @@ class EntityConfiguration(Base):
231113 }
232114
233115 def __init__ (
234- self ,
235- conf : Dict ,
236- base_path : Optional [str ] = "" ,
237- entity_conf : Optional [List [dict ]] = None ,
238- domain : Optional [str ] = "" ,
239- port : Optional [int ] = 0 ,
240- file_attributes : Optional [List [str ]] = None ,
116+ self ,
117+ conf : Dict ,
118+ base_path : Optional [str ] = "" ,
119+ entity_conf : Optional [List [dict ]] = None ,
120+ domain : Optional [str ] = "" ,
121+ port : Optional [int ] = 0 ,
122+ file_attributes : Optional [List [str ]] = None ,
123+ dir_attributes : Optional [List [str ]] = None ,
241124 ):
242125
243126 conf = copy .deepcopy (conf )
244- Base .__init__ (self , conf , base_path , file_attributes )
245-
246- if file_attributes is None :
247- file_attributes = DEFAULT_FILE_ATTRIBUTE_NAMES
248-
249- if not domain :
250- domain = conf .get ("domain" , "127.0.0.1" )
251-
252- if not port :
253- port = conf .get ("port" , 80 )
127+ Base .__init__ (self , conf , base_path , file_attributes , dir_attributes = dir_attributes )
254128
255129 for key in self .parameter .keys ():
256130 _val = conf .get (key )
@@ -263,6 +137,7 @@ def __init__(
263137 file_attributes = file_attributes ,
264138 domain = domain ,
265139 port = port ,
140+ dir_attributes = dir_attributes
266141 )
267142 else :
268143 continue
@@ -277,29 +152,6 @@ def __init__(
277152
278153 setattr (self , key , _val )
279154
280- # try:
281- # _dir = self.template_dir
282- # except AttributeError:
283- # self.template_dir = os.path.abspath("templates")
284- # else:
285- # self.template_dir =
286-
287- def format (self , conf , base_path , file_attributes , domain , port ):
288- """
289- Formats parts of the configuration. That includes replacing the strings {domain} and {port}
290- with the used domain and port and making references to files and directories absolute
291- rather then relative. The formatting is done in place.
292-
293- :param conf: The configuration part
294- :param base_path: The base path used to make file/directory refrences absolute
295- :param file_attributes: Attribute names that refer to files or directories.
296- :param domain: The domain name
297- :param port: The port used
298- """
299- add_base_path (conf , base_path , file_attributes )
300- if isinstance (conf , dict ):
301- set_domain_and_port (conf , self .uris , domain = domain , port = port )
302-
303155
304156class OPConfiguration (EntityConfiguration ):
305157 "Provider configuration"
@@ -316,13 +168,14 @@ class OPConfiguration(EntityConfiguration):
316168 )
317169
318170 def __init__ (
319- self ,
320- conf : Dict ,
321- base_path : Optional [str ] = "" ,
322- entity_conf : Optional [List [dict ]] = None ,
323- domain : Optional [str ] = "" ,
324- port : Optional [int ] = 0 ,
325- file_attributes : Optional [List [str ]] = None ,
171+ self ,
172+ conf : Dict ,
173+ base_path : Optional [str ] = "" ,
174+ entity_conf : Optional [List [dict ]] = None ,
175+ domain : Optional [str ] = "" ,
176+ port : Optional [int ] = 0 ,
177+ file_attributes : Optional [List [str ]] = None ,
178+ dir_attributes : Optional [List [str ]] = None ,
326179 ):
327180 super ().__init__ (
328181 conf = conf ,
@@ -331,21 +184,22 @@ def __init__(
331184 domain = domain ,
332185 port = port ,
333186 file_attributes = file_attributes ,
187+ dir_attributes = dir_attributes
334188 )
335- self .scopes_to_claims
336189
337190
338191class ASConfiguration (EntityConfiguration ):
339192 "Authorization server configuration"
340193
341194 def __init__ (
342- self ,
343- conf : Dict ,
344- base_path : Optional [str ] = "" ,
345- entity_conf : Optional [List [dict ]] = None ,
346- domain : Optional [str ] = "" ,
347- port : Optional [int ] = 0 ,
348- file_attributes : Optional [List [str ]] = None ,
195+ self ,
196+ conf : Dict ,
197+ base_path : Optional [str ] = "" ,
198+ entity_conf : Optional [List [dict ]] = None ,
199+ domain : Optional [str ] = "" ,
200+ port : Optional [int ] = 0 ,
201+ file_attributes : Optional [List [str ]] = None ,
202+ dir_attributes : Optional [List [str ]] = None ,
349203 ):
350204 EntityConfiguration .__init__ (
351205 self ,
@@ -355,63 +209,10 @@ def __init__(
355209 domain = domain ,
356210 port = port ,
357211 file_attributes = file_attributes ,
212+ dir_attributes = dir_attributes
358213 )
359214
360215
361- class Configuration (Base ):
362- """Server Configuration"""
363-
364- uris = ["issuer" , "base_url" ]
365-
366- def __init__ (
367- self ,
368- conf : Dict ,
369- entity_conf : Optional [List [dict ]] = None ,
370- base_path : str = "" ,
371- file_attributes : Optional [List [str ]] = None ,
372- domain : Optional [str ] = "" ,
373- port : Optional [int ] = 0 ,
374- ):
375- Base .__init__ (self , conf , base_path , file_attributes )
376-
377- log_conf = conf .get ("logging" )
378- if log_conf :
379- self .logger = configure_logging (config = log_conf ).getChild (__name__ )
380- else :
381- self .logger = logging .getLogger ("oidcop" )
382-
383- self .webserver = conf .get ("webserver" , {})
384-
385- if not domain :
386- domain = conf .get ("domain" , "127.0.0.1" )
387-
388- if not port :
389- port = conf .get ("port" , 80 )
390-
391- set_domain_and_port (conf , self .uris , domain = domain , port = port )
392-
393- if entity_conf :
394- for econf in entity_conf :
395- _path = econf .get ("path" )
396- _cnf = conf
397- if _path :
398- for step in _path :
399- _cnf = _cnf [step ]
400- _attr = econf ["attr" ]
401- _cls = econf ["class" ]
402- setattr (
403- self ,
404- _attr ,
405- _cls (
406- _cnf ,
407- base_path = base_path ,
408- file_attributes = file_attributes ,
409- domain = domain ,
410- port = port ,
411- ),
412- )
413-
414-
415216DEFAULT_EXTENDED_CONF = {
416217 "add_on" : {
417218 "pkce" : {
0 commit comments