mirror of
https://github.com/Yubico/yubiadmin.git
synced 2024-12-11 09:24:18 +01:00
Writing/reading config files.
This commit is contained in:
parent
d690b94982
commit
86c45089ed
@ -79,7 +79,7 @@
|
|||||||
{%- macro render_form(fieldsets, action) -%}
|
{%- macro render_form(fieldsets, action) -%}
|
||||||
<form action="{{ action }}" method="post">
|
<form action="{{ action }}" method="post">
|
||||||
{% for fieldset in fieldsets %}
|
{% for fieldset in fieldsets %}
|
||||||
{{ form_fieldset(fieldset) }}
|
{{ form_fieldset(fieldset) }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
<div class="form-actions">
|
<div class="form-actions">
|
||||||
<input type="submit" class="btn btn-primary" value="Save">
|
<input type="submit" class="btn btn-primary" value="Save">
|
||||||
@ -88,3 +88,5 @@
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
{%- endmacro -%}
|
{%- endmacro -%}
|
||||||
|
|
||||||
|
{{ render_form(fieldsets, target) }}
|
@ -1,3 +0,0 @@
|
|||||||
<h2>Database settings</h2>
|
|
||||||
|
|
||||||
<p>This is where general settings go.</p>
|
|
@ -1,3 +0,0 @@
|
|||||||
<h2>General settings</h2>
|
|
||||||
|
|
||||||
<p>This is where general settings go.</p>
|
|
@ -1,3 +0,0 @@
|
|||||||
<h2>KSM settings</h2>
|
|
||||||
|
|
||||||
<p>This is where general settings go.</p>
|
|
@ -1,3 +0,0 @@
|
|||||||
{% from "forms.html" import render_form %}
|
|
||||||
|
|
||||||
{{ render_form(fieldsets, '/val/database') }}
|
|
@ -1,3 +0,0 @@
|
|||||||
{% from "forms.html" import render_form %}
|
|
||||||
|
|
||||||
{{ render_form(fieldsets, '/val/general') }}
|
|
@ -1,3 +0,0 @@
|
|||||||
<h2>KSM settings</h2>
|
|
||||||
|
|
||||||
<p>This is where general settings go.</p>
|
|
@ -1,3 +0,0 @@
|
|||||||
<h2>KSM settings</h2>
|
|
||||||
|
|
||||||
<p>This is where general settings go.</p>
|
|
@ -1,8 +1,8 @@
|
|||||||
import os
|
import os
|
||||||
from wsgiref.simple_server import make_server
|
from wsgiref.simple_server import make_server
|
||||||
from webob.dec import wsgify
|
from webob.dec import wsgify
|
||||||
from jinja2 import Environment, FileSystemLoader
|
|
||||||
|
|
||||||
|
from yubiadmin.util import render
|
||||||
from yubiadmin.apps import apps
|
from yubiadmin.apps import apps
|
||||||
|
|
||||||
|
|
||||||
@ -25,14 +25,8 @@ def inspect_app(app):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def render_section(app, section, template, **kwargs):
|
|
||||||
data = app.__getattribute__(section)(**kwargs)
|
|
||||||
return template.render(**data)
|
|
||||||
|
|
||||||
|
|
||||||
class YubiAdmin(object):
|
class YubiAdmin(object):
|
||||||
def __init__(self, env):
|
def __init__(self):
|
||||||
self.env = env
|
|
||||||
self.apps = {}
|
self.apps = {}
|
||||||
for app in apps:
|
for app in apps:
|
||||||
app_data = inspect_app(app)
|
app_data = inspect_app(app)
|
||||||
@ -45,38 +39,29 @@ class YubiAdmin(object):
|
|||||||
section_name = request.path_info_pop()
|
section_name = request.path_info_pop()
|
||||||
|
|
||||||
if not module_name:
|
if not module_name:
|
||||||
tmpl = self.env.get_template('index.html')
|
return render('index', modules=self.modules)
|
||||||
return tmpl.render(modules=self.modules)
|
|
||||||
|
|
||||||
app, module = self.apps[module_name]
|
app, module = self.apps[module_name]
|
||||||
if not section_name:
|
if not section_name:
|
||||||
section_name = module['sections'][0]['name']
|
section_name = module['sections'][0]['name']
|
||||||
|
|
||||||
tmpl = self.env.get_template('%s/%s.html' %
|
|
||||||
(module_name, section_name))
|
|
||||||
section = next(section for section in module['sections']
|
section = next(section for section in module['sections']
|
||||||
if section['name'] == section_name)
|
if section['name'] == section_name)
|
||||||
|
|
||||||
data = app.__getattribute__(section_name)(request)
|
return render(
|
||||||
page = tmpl.render(**data)
|
'app_base',
|
||||||
|
modules=self.modules,
|
||||||
data.update({
|
module=module,
|
||||||
'modules': self.modules,
|
section=section,
|
||||||
'module': module,
|
title='YubiAdmin - %s - %s' % (module_name, section_name),
|
||||||
'section': section,
|
page=app.__getattribute__(section_name)(request)
|
||||||
'title': '%s - %s' % (module_name, section_name),
|
)
|
||||||
'page': page
|
|
||||||
})
|
|
||||||
tmpl = env.get_template('app_base.html')
|
|
||||||
return tmpl.render(**data)
|
|
||||||
|
|
||||||
cwd = os.path.dirname(__file__)
|
cwd = os.path.dirname(__file__)
|
||||||
base_dir = os.path.abspath(os.path.join(cwd, os.pardir))
|
base_dir = os.path.abspath(os.path.join(cwd, os.pardir))
|
||||||
static_dir = os.path.join(base_dir, 'static')
|
static_dir = os.path.join(base_dir, 'static')
|
||||||
template_dir = os.path.join(base_dir, 'templates')
|
|
||||||
env = Environment(loader=FileSystemLoader(template_dir))
|
|
||||||
|
|
||||||
application = YubiAdmin(env)
|
application = YubiAdmin()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@ -17,6 +17,6 @@ class YubikeyKsm(object):
|
|||||||
"""
|
"""
|
||||||
Database Settings
|
Database Settings
|
||||||
"""
|
"""
|
||||||
return {}
|
return "Hello world"
|
||||||
|
|
||||||
app = YubikeyKsm()
|
app = YubikeyKsm()
|
||||||
|
@ -1,55 +1,107 @@
|
|||||||
from wtforms import Form
|
from wtforms.fields import StringField, IntegerField, PasswordField
|
||||||
from wtforms.fields import StringField, IntegerField
|
from wtforms.validators import NumberRange, Optional
|
||||||
from wtforms.validators import NumberRange
|
from wtforms.widgets import PasswordInput
|
||||||
|
from yubiadmin.util import App, ConfigForm, FileConfig, render
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'app'
|
'app'
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
class MiscForm(Form):
|
def yk_read_str(varname):
|
||||||
legend = 'Misc'
|
return r'\$baseParams\[\'__YKVAL_%s__\'\] = [\'"](.*)[\'"];' % varname
|
||||||
default_timeout = IntegerField('Default Timeout', [NumberRange(0)],
|
|
||||||
default=1)
|
|
||||||
|
|
||||||
def load(self):
|
|
||||||
self.default_timeout.process_data(5)
|
|
||||||
|
|
||||||
def save(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class SyncLevelsForm(Form):
|
def yk_write_str(varname):
|
||||||
|
return lambda x: '$baseParams[\'__YKVAL_%s__\'] = "%s";' % (varname, x)
|
||||||
|
|
||||||
|
|
||||||
|
def yk_read_int(varname):
|
||||||
|
return r'\$baseParams\[\'__YKVAL_%s__\'\] = (\d+);' % varname
|
||||||
|
|
||||||
|
|
||||||
|
def yk_write_int(varname):
|
||||||
|
return lambda x: '$baseParams[\'__YKVAL_%s__\'] = %s;' % (varname, x)
|
||||||
|
|
||||||
|
|
||||||
|
def db_read(varname):
|
||||||
|
return r'\$db%s=\'(.*)\';' % varname
|
||||||
|
|
||||||
|
|
||||||
|
def db_write(varname):
|
||||||
|
return lambda x: '$db%s=\'%s\';' % (varname, x)
|
||||||
|
|
||||||
|
|
||||||
|
class SyncLevelsForm(ConfigForm):
|
||||||
legend = 'Sync Levels'
|
legend = 'Sync Levels'
|
||||||
sync_default = IntegerField('Default', [NumberRange(1, 100)], default=60)
|
|
||||||
sync_secure = IntegerField('Secure', [NumberRange(1, 100)], default=40)
|
|
||||||
sync_fast = IntegerField('Fast', [NumberRange(1, 100)], default=1)
|
|
||||||
|
|
||||||
def load(self):
|
sync_default = IntegerField('Default', [NumberRange(1, 100)])
|
||||||
# TODO: Read config file
|
sync_secure = IntegerField('Secure', [NumberRange(1, 100)])
|
||||||
self.sync_default.process_data(40)
|
sync_fast = IntegerField('Fast', [NumberRange(1, 100)])
|
||||||
self.sync_secure.process_data(51)
|
|
||||||
self.sync_fast.process_data(1)
|
|
||||||
|
|
||||||
def save(self):
|
config = FileConfig(
|
||||||
# TODO: Save data t config file
|
'/home/dain/yubico/yubiadmin/ykval-config.php',
|
||||||
pass
|
[
|
||||||
|
(
|
||||||
|
'sync_default',
|
||||||
|
yk_read_int('SYNC_DEFAULT_LEVEL'),
|
||||||
|
yk_write_int('SYNC_DEFAULT_LEVEL'),
|
||||||
|
60
|
||||||
|
), (
|
||||||
|
'sync_secure',
|
||||||
|
yk_read_int('SYNC_SECURE_LEVEL'),
|
||||||
|
yk_write_int('SYNC_SECURE_LEVEL'),
|
||||||
|
40
|
||||||
|
), (
|
||||||
|
'sync_fast',
|
||||||
|
yk_read_int('SYNC_FAST_LEVEL'),
|
||||||
|
yk_write_int('SYNC_FAST_LEVEL'),
|
||||||
|
1
|
||||||
|
),
|
||||||
|
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class DatabaseForm(Form):
|
class MiscForm(ConfigForm):
|
||||||
|
legend = 'Misc'
|
||||||
|
default_timeout = IntegerField('Default Timeout', [NumberRange(0)])
|
||||||
|
|
||||||
|
config = FileConfig(
|
||||||
|
'/home/dain/yubico/yubiadmin/ykval-config.php',
|
||||||
|
[(
|
||||||
|
'default_timeout',
|
||||||
|
yk_read_int('SYNC_DEFAULT_TIMEOUT'),
|
||||||
|
yk_write_int('SYNC_DEFAULT_TIMEOUT'),
|
||||||
|
1
|
||||||
|
)]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class DatabaseForm(ConfigForm):
|
||||||
legend = 'Database'
|
legend = 'Database'
|
||||||
connection_string = StringField('Connection String', default=1)
|
dbtype = StringField('DB type')
|
||||||
attrs = {'connection_string': {'class': 'input-xxlarge'}}
|
dbserver = StringField('Host')
|
||||||
|
dbport = IntegerField('Port', [Optional(), NumberRange(1, 65535)])
|
||||||
|
dbname = StringField('DB name')
|
||||||
|
dbuser = StringField('DB username')
|
||||||
|
dbpass = PasswordField('DB password',
|
||||||
|
widget=PasswordInput(hide_value=False))
|
||||||
|
|
||||||
def load(self):
|
config = FileConfig(
|
||||||
self.connection_string.process_data(
|
'/home/dain/yubico/yubiadmin/config-db.php',
|
||||||
'mysql:dbname=ykval;host=127.0.0.1')
|
[
|
||||||
|
('dbtype', db_read('type'), db_write('type'), 'mysql'),
|
||||||
def save(self):
|
('dbserver', db_read('server'), db_write('server'), 'localhost'),
|
||||||
pass
|
('dbport', db_read('port'), db_write('port'), ''),
|
||||||
|
('dbname', db_read('name'), db_write('name'), 'ykval'),
|
||||||
|
('dbuser', db_read('user'), db_write('user'), 'ykval_verifier'),
|
||||||
|
('dbpass', db_read('pass'), db_write('pass'), ''),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class YubikeyVal(object):
|
class YubikeyVal(App):
|
||||||
"""
|
"""
|
||||||
YubiKey Validation Server
|
YubiKey Validation Server
|
||||||
|
|
||||||
@ -59,52 +111,28 @@ class YubikeyVal(object):
|
|||||||
name = 'val'
|
name = 'val'
|
||||||
sections = ['general', 'database', 'syncpool', 'ksms']
|
sections = ['general', 'database', 'syncpool', 'ksms']
|
||||||
|
|
||||||
def _populate_forms(self, forms, data):
|
|
||||||
if not data:
|
|
||||||
for form in forms:
|
|
||||||
form.load()
|
|
||||||
else:
|
|
||||||
errors = False
|
|
||||||
for form in forms:
|
|
||||||
form.process(data)
|
|
||||||
errors = form.validate() or errors
|
|
||||||
if not errors:
|
|
||||||
for form in forms:
|
|
||||||
form.save()
|
|
||||||
|
|
||||||
def general(self, request):
|
def general(self, request):
|
||||||
"""
|
"""
|
||||||
General
|
General
|
||||||
"""
|
"""
|
||||||
forms = [
|
return self.render_forms(request, [SyncLevelsForm(), MiscForm()])
|
||||||
SyncLevelsForm(),
|
|
||||||
MiscForm()
|
|
||||||
]
|
|
||||||
|
|
||||||
self._populate_forms(forms, request.params)
|
|
||||||
|
|
||||||
return {'fieldsets': forms}
|
|
||||||
|
|
||||||
def database(self, request):
|
def database(self, request):
|
||||||
"""
|
"""
|
||||||
Database Settings
|
Database Settings
|
||||||
"""
|
"""
|
||||||
forms = [DatabaseForm()]
|
return self.render_forms(request, [DatabaseForm()])
|
||||||
|
|
||||||
self._populate_forms(forms, request.params)
|
|
||||||
|
|
||||||
return {'fieldsets': forms}
|
|
||||||
|
|
||||||
def syncpool(self, request):
|
def syncpool(self, request):
|
||||||
"""
|
"""
|
||||||
Sync pool
|
Sync pool
|
||||||
"""
|
"""
|
||||||
return {}
|
return render('form', target=request.path)
|
||||||
|
|
||||||
def ksms(self, request):
|
def ksms(self, request):
|
||||||
"""
|
"""
|
||||||
Key Store Modules
|
Key Store Modules
|
||||||
"""
|
"""
|
||||||
return {}
|
return render('form', target=request.path)
|
||||||
|
|
||||||
app = YubikeyVal()
|
app = YubikeyVal()
|
||||||
|
123
yubiadmin/util.py
Normal file
123
yubiadmin/util.py
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
import os
|
||||||
|
import re
|
||||||
|
from UserDict import DictMixin
|
||||||
|
from wtforms import Form
|
||||||
|
from jinja2 import Environment, FileSystemLoader
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
'App',
|
||||||
|
'FileConfig',
|
||||||
|
'ConfigForm',
|
||||||
|
'render',
|
||||||
|
'populate_forms',
|
||||||
|
]
|
||||||
|
|
||||||
|
cwd = os.path.dirname(__file__)
|
||||||
|
base_dir = os.path.abspath(os.path.join(cwd, os.pardir))
|
||||||
|
template_dir = os.path.join(base_dir, 'templates')
|
||||||
|
env = Environment(loader=FileSystemLoader(template_dir))
|
||||||
|
|
||||||
|
|
||||||
|
def render(tmpl, **kwargs):
|
||||||
|
template = env.get_template('%s.html' % tmpl)
|
||||||
|
return template.render(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def populate_forms(forms, data):
|
||||||
|
if not data:
|
||||||
|
for form in forms:
|
||||||
|
form.load()
|
||||||
|
else:
|
||||||
|
errors = False
|
||||||
|
for form in forms:
|
||||||
|
form.process(data)
|
||||||
|
errors = not form.validate() or errors
|
||||||
|
if not errors:
|
||||||
|
for form in forms:
|
||||||
|
form.save()
|
||||||
|
else:
|
||||||
|
print 'Errors!'
|
||||||
|
|
||||||
|
|
||||||
|
class App(object):
|
||||||
|
name = None
|
||||||
|
sections = []
|
||||||
|
|
||||||
|
def render_forms(self, request, forms):
|
||||||
|
populate_forms(forms, request.params)
|
||||||
|
return render('form', target=request.path, fieldsets=forms)
|
||||||
|
|
||||||
|
|
||||||
|
class ValueHandler(object):
|
||||||
|
def __init__(self, pattern, writer, default=None, group=1):
|
||||||
|
self.pattern = re.compile(pattern)
|
||||||
|
self.writer = writer
|
||||||
|
self.default = default
|
||||||
|
self.group = group
|
||||||
|
|
||||||
|
def read(self, content):
|
||||||
|
match = self.pattern.search(content)
|
||||||
|
if match:
|
||||||
|
return match.group(self.group)
|
||||||
|
return self.default
|
||||||
|
|
||||||
|
def write(self, content, value):
|
||||||
|
if value is None:
|
||||||
|
value = ''
|
||||||
|
if self.pattern.search(content):
|
||||||
|
content = self.pattern.sub(self.writer(value), content, 1)
|
||||||
|
else:
|
||||||
|
content += os.linesep + self.writer(value)
|
||||||
|
return content
|
||||||
|
|
||||||
|
|
||||||
|
class FileConfig(DictMixin):
|
||||||
|
def __init__(self, filename, params=[]):
|
||||||
|
self.filename = filename
|
||||||
|
self.params = {}
|
||||||
|
for param in params:
|
||||||
|
self.add_param(*param)
|
||||||
|
|
||||||
|
def read(self):
|
||||||
|
try:
|
||||||
|
with open(self.filename, 'r') as file:
|
||||||
|
self.content = file.read()
|
||||||
|
except IOError as e:
|
||||||
|
print e
|
||||||
|
self.content = ''
|
||||||
|
|
||||||
|
def commit(self):
|
||||||
|
with open(self.filename, 'w+') as file:
|
||||||
|
file.write(self.content)
|
||||||
|
|
||||||
|
def add_param(self, key, pattern, writer, default=None, group=1):
|
||||||
|
self.params[key] = ValueHandler(pattern, writer, default, group)
|
||||||
|
|
||||||
|
def __getitem__(self, key):
|
||||||
|
return self.params[key].read(self.content)
|
||||||
|
|
||||||
|
def __setitem__(self, key, value):
|
||||||
|
self.content = self.params[key].write(self.content, value)
|
||||||
|
|
||||||
|
def keys(self):
|
||||||
|
return self.params.keys()
|
||||||
|
|
||||||
|
def __delitem__(self, key):
|
||||||
|
del self.params[key]
|
||||||
|
|
||||||
|
|
||||||
|
class ConfigForm(Form):
|
||||||
|
config = None
|
||||||
|
|
||||||
|
def load(self):
|
||||||
|
self.config.read()
|
||||||
|
for field in self:
|
||||||
|
if field.id in self.config:
|
||||||
|
field.process_data(self.config[field.id])
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
self.config.read()
|
||||||
|
for field in self:
|
||||||
|
if field.id in self.config:
|
||||||
|
self.config[field.id] = field.data
|
||||||
|
self.config.commit()
|
Loading…
Reference in New Issue
Block a user