Module: check_mk
Branch: master
Commit: df61d05214b6d200bbbf9ef4c3bb759aadef3c68
URL:
http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=df61d05214b6d2…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Wed Jul 20 09:57:29 2016 +0200
Several fixex and minor improvements to current password store implementation;
---
bin/.f12 | 2 +-
bin/{pwquery.sh => pwquery} | 2 +-
checks/check_http | 7 ++---
lib/passwordstore.py | 2 +-
web/htdocs/valuespec.py | 49 +++++++++++++++++++++++----------
web/htdocs/wato.py | 3 ++
web/plugins/userdb/user_attributes.py | 21 +++++++++-----
7 files changed, 56 insertions(+), 30 deletions(-)
diff --git a/bin/.f12 b/bin/.f12
index f9f022e..5b9bf09 100644
--- a/bin/.f12
+++ b/bin/.f12
@@ -4,7 +4,7 @@ SITE=${SITE:-$(omd sites --bare | head -n 1)}
OMD_ROOT=/omd/sites/${SITE}
make
-sudo install -m 755 mkeventd mkeventd_open514 mkevent mkbackup $OMD_ROOT/bin/
+sudo install -m 755 mkeventd mkeventd_open514 mkevent mkbackup pwquery $OMD_ROOT/bin/
sudo chown root.omd $OMD_ROOT/bin/mkeventd_open514
sudo chmod 4750 $OMD_ROOT/bin/mkeventd_open514
echo "Installed to $OMD_ROOT/bin"
diff --git a/bin/pwquery.sh b/bin/pwquery
similarity index 94%
rename from bin/pwquery.sh
rename to bin/pwquery
index 86d5f36..10b6124 100755
--- a/bin/pwquery.sh
+++ b/bin/pwquery
@@ -9,7 +9,7 @@ shift
export PYTHONPATH=$OMD_ROOT/lib/python:$OMD_ROOT/local/lib/python
$OMD_ROOT/bin/python $OMD_ROOT/lib/python/cmk/passwordstore.py\
- --get $1 --user $2\
+ --get $1\
--keydir $OMD_ROOT/var/check_mk/private_keys\
--file $OMD_ROOT/var/check_mk/passwords.json
diff --git a/checks/check_http b/checks/check_http
index 0f8a4f8..7ac64b6 100644
--- a/checks/check_http
+++ b/checks/check_http
@@ -96,16 +96,13 @@ def check_http_arguments(params):
if "auth" in settings:
user, password = settings["auth"]
if password.startswith("store:"):
- group, password = password[6:].split(":", 1)
- args += ' -a %s:%s --password-store %s' %\
- (quote_shell_string(user), quote_shell_string(password),
- quote_shell_string(group))
+ args += ' -a %s --password-store' % (quote_shell_string(user +
":" + password[6:]))
else:
if password.startswith("imm:"):
password = password[4:]
# else: assume that a password that starts with neither store nor imm is from
an old
# configuration and has no prefix
- args += ' -a %s:%s' % (quote_shell_string(user),
quote_shell_string(password))
+ args += ' -a %s' % quote_shell_string(user + ":" +
password)
if "proxy_auth" in settings:
auth = settings["proxy_auth"]
diff --git a/lib/passwordstore.py b/lib/passwordstore.py
index a1b27c8..e09e6e4 100644
--- a/lib/passwordstore.py
+++ b/lib/passwordstore.py
@@ -564,7 +564,7 @@ def do_action(store, args):
logging.info("key \"%s\" set with owner
\"%s\"", args.set[0], args.user)
elif args.get is not None:
try:
- print(store.get(args.get, args.user))
+ sys.stdout.write(store.get(args.get, args.user))
except NotAuthorizedException:
logging.warn("User \"%s\" isn't authorized to retrive
\"%s\"",
args.user, args.get)
diff --git a/web/htdocs/valuespec.py b/web/htdocs/valuespec.py
index cb912e7..fce02f1 100644
--- a/web/htdocs/valuespec.py
+++ b/web/htdocs/valuespec.py
@@ -3373,6 +3373,8 @@ class PasswordSpec(TextAscii):
html.icon_button("#", _(u"Show/Hide password"),
"showhide",
onclick="vs_toggle_hidden(this);")
+
+
class PasswordFromStore(Alternative):
def __init__(self, **kwargs):
kwargs["elements"] = [
@@ -3391,6 +3393,7 @@ class PasswordFromStore(Alternative):
)
Alternative.__init__(self, **kwargs)
+
def __stored_passwords(self):
from cmk.passwordstore import CryptoBackend, PasswordStore, NonePasswordProvider
backend = CryptoBackend(defaults.var_dir + "/private_keys",
NonePasswordProvider())
@@ -3400,48 +3403,64 @@ class PasswordFromStore(Alternative):
with PasswordStore(defaults.var_dir + "/passwords.json", backend) as
store:
return store.list(with_details=True)
+
def matching_alternative(self, value):
if value.startswith("store:") and len(self._elements) > 1:
- return self._elements[1], value.split(':', 2)[2]
+ return self._elements[1], value.split(':', 1)[1]
elif value.startswith("imm:"):
return self._elements[0], value.split(':', 1)[1]
else:
return self._elements[0], value
+
def value_to_text(self, value):
return value.split(':', 1)[1]
+
def validate_datatype(self, value, varprefix):
- return Alternative.validate_datatype(self, value.split(':', 2)[2],
varprefix)
+ mvs, value = self.matching_alternative(value)
+ return Alternative.validate_datatype(self, value, varprefix)
+
- def __find_contactgroup(self, value, varprefix):
+ def __get_password_by_key(self, value, varprefix):
for pw in self.__passwords:
if pw['key'] == value:
- import config, userdb
- for group in userdb.contactgroups_of_user(config.user_id):
- if "group:" + group in pw['shared']:
- return group
- raise MKUserError(varprefix,
- _("You don't belong to a contact group with
access to "
- "password key %s") % value)
- raise MKUserError(varprefix, _("Unknown password key %s") % value)
+ return pw
+ raise MKUserError(varprefix, _("Unknown password key: %s") % value)
+
+
+ def __may_use_password(self, key, varprefix):
+ import config, userdb
+ pw = self.__get_password_by_key(key, varprefix)
+
+ if pw["owner"] == "user:" + config.user_id:
+ return # the users password
+
+ for group in userdb.contactgroups_of_user(config.user_id):
+ if "group:" + group in pw['shared']:
+ return group # is shared with a users group
+
+ raise MKUserError(varprefix, _("You don't have permission to use the
password with "
+ "the key \"%s\", shared by user %s.") % (key,
pw["owner"][5:]))
+
def validate_value(self, value, varprefix):
- prefix, group, val = value.split(':', 2)
+ prefix, val = value.split(':', 1)
if prefix == "store":
# couldn't check user permission before, but now I can
- self.__find_contactgroup(val, varprefix)
+ self.__may_use_password(val, varprefix)
else:
return Alternative.validate_value(self, val, varprefix)
+
def from_html_vars(self, varprefix):
nr = int(html.var(varprefix + "_use"))
if nr == 0:
return "imm:" + Alternative.from_html_vars(self, varprefix)
else:
key = Alternative.from_html_vars(self, varprefix)
- group = self.__find_contactgroup(key, varprefix)
- return ":".join(["store", group, key])
+ return ":".join(["store", key])
+
class FileUpload(ValueSpec):
diff --git a/web/htdocs/wato.py b/web/htdocs/wato.py
index 047eca3..f44ae87 100644
--- a/web/htdocs/wato.py
+++ b/web/htdocs/wato.py
@@ -10917,6 +10917,9 @@ def mode_edit_user(phase):
select_language(user)
custom_user_attributes('personal')
+ forms.header(_("Password Store"), isopen = False)
+ custom_user_attributes("password_store")
+
# Later we could add custom macros here, which then could be used
# for notifications. On the other hand, if we implement some check_mk
# --notify, we could directly access the data in the account with the need
diff --git a/web/plugins/userdb/user_attributes.py
b/web/plugins/userdb/user_attributes.py
index 805613a..a1a1694 100644
--- a/web/plugins/userdb/user_attributes.py
+++ b/web/plugins/userdb/user_attributes.py
@@ -87,22 +87,29 @@ declare_user_attribute(
"passwords",
ListOf(
Dictionary(
- title = _("Password Store"),
elements = [
("key", TextAscii(title=_("Key"))),
("secret", PasswordSpec(title=_("Password"),
allow_empty=True, hidden=True)),
- ('contactgroups', ListChoice(
- title = _('Share with Contact groups'),
- help = _('Specify the contact groups that may access the
password.'),
+ ("contactgroups", ListChoice(
+ title = _("Share with contact groups"),
+ help = _("By default you are the only user that can configure
checks to use "
+ "your configured passwords. It is possible to share a
password with "
+ "a group of users to make them able to use a password
in checks."),
default_value = [],
choices = list_contactgroups,
))
],
optional_keys=[]
),
- title = _("Password"),
- add_label = _("Add Password")
+ title = _("Password Store"),
+ add_label = _("Add Password"),
+ help = _("The password store is used to store multiple passwords per user
which can then "
+ "be used by Check_MK during checking. The passwords are stored in
encrypted form, "
+ "so that they can not be read by other users in clear text. They
can be decrypted "
+ "by Check_MK during monitoring to hand over them to checks for
authentification "
+ "with the monitoringed systems."),
),
- domain = "passwords"
+ domain = "multisite",
+ topic = "password_store",
)