Module: check_mk
Branch: master
Commit: 0c23bb363179c789ca21d6073eaad8fa29e2b190
URL:
http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=0c23bb363179c7…
Author: Óscar Nájera <on(a)mathias-kettner.de>
Date: Tue Oct 30 09:51:03 2018 +0100
6647 Enable use of Passwordstore for Slack's Webhook-URL
It is now possible to configure Slack's notification plugin using values
stored in Check_MK Password store. In this way the Webhook URL is not shown
in the Notifications Parameters but is just recovered from the password
store vault.
CMK-989
Change-Id: I3fc443a6f28a21227bd75056a0640f7b2a924a1d
---
.werks/6647 | 13 ++++++
cmk/gui/plugins/wato/__init__.py | 1 +
cmk/gui/plugins/wato/notifications.py | 76 ++++++++++++++++++++--------------
cmk/gui/plugins/wato/utils/__init__.py | 15 ++++---
cmk/notification_plugins/slack.py | 8 +++-
cmk/password_store.py | 4 ++
6 files changed, 76 insertions(+), 41 deletions(-)
diff --git a/.werks/6647 b/.werks/6647
new file mode 100644
index 0000000..7a4a66e
--- /dev/null
+++ b/.werks/6647
@@ -0,0 +1,13 @@
+Title: Enable use of Passwordstore for Slack's Webhook-URL
+Level: 1
+Component: notifications
+Compatible: compat
+Edition: cre
+Version: 1.6.0i1
+Date: 1540910427
+Class: feature
+
+It is now possible to configure Slack's notification plugin using values
+stored in Check_MK Password store. In this way the Webhook URL is not shown
+in the Notifications Parameters but is just recovered from the password
+store vault.
diff --git a/cmk/gui/plugins/wato/__init__.py b/cmk/gui/plugins/wato/__init__.py
index 054bf6b..6d3a469 100644
--- a/cmk/gui/plugins/wato/__init__.py
+++ b/cmk/gui/plugins/wato/__init__.py
@@ -64,6 +64,7 @@ from cmk.gui.plugins.wato.utils import (
home_button,
HostnameTranslation,
IndividualOrStoredPassword,
+ passwordstore_choices,
IPMIParameters,
is_wato_slave_site,
Levels,
diff --git a/cmk/gui/plugins/wato/notifications.py
b/cmk/gui/plugins/wato/notifications.py
old mode 100755
new mode 100644
index 6df8133..7da9207
--- a/cmk/gui/plugins/wato/notifications.py
+++ b/cmk/gui/plugins/wato/notifications.py
@@ -33,23 +33,25 @@ from cmk.gui.i18n import _
from cmk.gui.globals import html
from cmk.gui.valuespec import (
- DropdownChoice,
- FixedValue,
- Tuple,
Age,
- TextAscii,
CascadingDropdown,
- Transform,
- TextAreaUnicode,
- TextUnicode,
- ListChoice,
Dictionary,
- Password,
- IPv4Address,
+ DropdownChoice,
EmailAddress,
+ FixedValue,
+ HTTPUrl,
+ IPv4Address,
+ ListChoice,
+ Password,
+ TextAreaUnicode,
+ TextAscii,
+ TextUnicode,
+ Transform,
+ Tuple,
)
-from cmk.gui.plugins.wato import register_notification_parameters
+from cmk.gui.plugins.wato import (register_notification_parameters,
passwordstore_choices)
+
# We have to transform because 'add_to_event_context'
# in modules/events.py can't handle complex data structures
@@ -208,9 +210,9 @@ def html_email_parameter_elements():
register_notification_parameters(
"mail",
Dictionary(
- elements = html_email_parameter_elements, # must be called at run time!!
- )
-)
+ elements=html_email_parameter_elements, # must be called at run time!!
+ ))
+
register_notification_parameters(
"slack",
@@ -218,20 +220,26 @@ register_notification_parameters(
optional_keys=["url_prefix"],
elements=[
("webhook_url",
- TextAscii(
+ CascadingDropdown(
title=_("Slack Webhook-URL"),
- size=80,
- allow_empty=False,
- help=_(
- "URL from Slack Webhook. Setup one <a
href=\"https://my.slack.com/services/new/incoming-webhook/\"
target=\"_blank\"> here </a>"),
-
regex="^https://hooks.slack.com/services/.+"s/.+",
- regex_error=_("The Webhook-URL must begin with "
-
"<tt>https://hooks.slack.com/services/</tt>"),
- )
- ),
+ help=_("URL from Slack Webhook. Setup one "+
+ "<a
href=\"https://my.slack.com/services/new/incoming-webhook/\"
target=\"_blank\"> here </a>"
+ "<br />This URL can also be collected from the
Password Store from Check_MK."),
+ choices=[
+ ("webhook_url", _("Webhook URL"), HTTPUrl(
+ size=80,
+ allow_empty=False,
+
regex="^https://hooks.slack.com/services/.+"s/.+",
+ regex_error=_("The Webhook-URL must begin with "
+
"<tt>https://hooks.slack.com/services/</tt>")),),
+ ("store", _("URL from password store"),
DropdownChoice(
+ sorted = True,
+ choices=passwordstore_choices,
+ ))
+ ]
+ )),
("url_prefix",
Transform(CascadingDropdown(
- style="dropdown",
title=_("URL prefix for links to Check_MK"),
help=_("If you use <b>Automatic HTTP/s</b> the URL
prefix for "
"host and service links within the notification mail
"
@@ -303,7 +311,7 @@ register_notification_parameters(
cols = 58,
monospaced = True,
default_value =
-"""Host: $HOSTNAME$
+ """Host: $HOSTNAME$
Alias: $HOSTALIAS$
Address: $HOSTADDRESS$
""",
@@ -316,7 +324,7 @@ Address: $HOSTADDRESS$
cols = 58,
monospaced = True,
default_value =
-"""Event: $EVENT_TXT$
+ """Event: $EVENT_TXT$
Output: $HOSTOUTPUT$
Perfdata: $HOSTPERFDATA$
$LONGHOSTOUTPUT$
@@ -330,7 +338,7 @@ $LONGHOSTOUTPUT$
cols = 58,
monospaced = True,
default_value =
-"""Service: $SERVICEDESC$
+ """Service: $SERVICEDESC$
Event: $EVENT_TXT$
Output: $SERVICEOUTPUT$
Perfdata: $SERVICEPERFDATA$
@@ -417,16 +425,20 @@ register_notification_parameters(
)
)
+
# We have to transform because 'add_to_event_context'
# in modules/events.py can't handle complex data structures
def transform_back_pushover_priority(params):
if type(params) == tuple:
- return {"priority" : "2",
- "retry" : params[1][0],
- "expire" : params[1][1],
- "receipts" : params[1][2]}
+ return {
+ "priority": "2",
+ "retry": params[1][0],
+ "expire": params[1][1],
+ "receipts": params[1][2]
+ }
return params
+
def transform_forth_pushover_priority(params):
if type(params) == dict:
return (params['priority'], (params["retry"],
params["expire"], params["receipts"]))
diff --git a/cmk/gui/plugins/wato/utils/__init__.py
b/cmk/gui/plugins/wato/utils/__init__.py
index 5736d99..9fe4777 100644
--- a/cmk/gui/plugins/wato/utils/__init__.py
+++ b/cmk/gui/plugins/wato/utils/__init__.py
@@ -544,6 +544,11 @@ class GroupSelection(ElementSelection):
return dict(elements)
+def passwordstore_choices():
+ return [
+ (ident, pw["title"]) for ident, pw in
watolib.PasswordStore().usable_passwords().items()
+ ]
+
class PasswordFromStore(CascadingDropdown):
def __init__(self, *args, **kwargs):
@@ -552,7 +557,7 @@ class PasswordFromStore(CascadingDropdown):
allow_empty = kwargs.get("allow_empty", True),
)),
("store", _("Stored password"), DropdownChoice(
- choices = self._password_choices,
+ choices = passwordstore_choices,
sorted = True,
invalid_choice = "complain",
invalid_choice_title = _("Password does not exist or using not
permitted"),
@@ -566,16 +571,10 @@ class PasswordFromStore(CascadingDropdown):
CascadingDropdown.__init__(self, *args, **kwargs)
- def _password_choices(self):
- return [ (ident, pw["title"]) for ident, pw
- in watolib.PasswordStore().usable_passwords().items() ]
-
-
-
def IndividualOrStoredPassword(*args, **kwargs):
return Transform(
PasswordFromStore(*args, **kwargs),
- forth = lambda v: ("password", v) if type(v) != tuple else v,
+ forth=lambda v: ("password", v) if type(v) != tuple else v,
)
diff --git a/cmk/notification_plugins/slack.py b/cmk/notification_plugins/slack.py
index 5f82560..de6098b 100644
--- a/cmk/notification_plugins/slack.py
+++ b/cmk/notification_plugins/slack.py
@@ -34,6 +34,7 @@ import sys
import requests
from cmk.notification_plugins import utils
+import cmk.password_store
COLORS = {
"CRITICAL": "#EE0000",
@@ -89,7 +90,12 @@ def construct_message(context):
def main():
context = utils.collect_context()
- url = context.get("PARAMETER_WEBHOOK_URL")
+ url = context.get("PARAMETER_WEBHOOK_URL").split()
+
+ if url[0] == 'store':
+ url = cmk.password_store.extract(url[1])
+ else:
+ url = url[1]
r = requests.post(url=url, json=construct_message(context))
diff --git a/cmk/password_store.py b/cmk/password_store.py
index 408557c..4adc92b 100644
--- a/cmk/password_store.py
+++ b/cmk/password_store.py
@@ -106,3 +106,7 @@ def load():
ident, password = line.strip().split(":", 1)
passwords[ident] = password
return passwords
+
+
+def extract(password_id):
+ return load().get(password_id)