diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..c902dbaf --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,9 @@ +# Change Log + +## [v4.5.8](https://github.com/pliablepixels/zmeventnotification/tree/v4.5.8) (2019-11-06) +**Implemented enhancements:** + +- Allow for secret tokens to be used in ES and OD configs [\#167](https://github.com/pliablepixels/zmeventnotification/issues/167) + + +\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)* diff --git a/hook/objectconfig.ini b/hook/objectconfig.ini index ccdee005..5e7514c9 100644 --- a/hook/objectconfig.ini +++ b/hook/objectconfig.ini @@ -5,9 +5,14 @@ # duplicate it inside the correct [monitor-] section [general] -portal=https:/server/zm -user=admin -password=password +# This is an optional file +# If specified, you can specify tokens with secret values in that file +# and onlt refer to the tokens in your main config file +secrets=/etc/zm/secrets.ini + +portal=!ZM_PORTAL +user=!ZM_USER +password=!ZM_PASSWORD allow_self_signed=yes # if yes, last detection will be stored for monitors # and bounding boxes that match, along with labels diff --git a/hook/zmes_hook_helpers/__init__.py b/hook/zmes_hook_helpers/__init__.py index f4d3f737..6805210c 100644 --- a/hook/zmes_hook_helpers/__init__.py +++ b/hook/zmes_hook_helpers/__init__.py @@ -1,2 +1,2 @@ -__version__ = "4.4.7" +__version__ = "4.5.8" VERSION=__version__ diff --git a/hook/zmes_hook_helpers/common_params.py b/hook/zmes_hook_helpers/common_params.py index ed621778..dce25579 100644 --- a/hook/zmes_hook_helpers/common_params.py +++ b/hook/zmes_hook_helpers/common_params.py @@ -8,6 +8,11 @@ # valid config keys and defaults config_vals = { + 'secrets':{ + 'section': 'general', + 'default': None, + 'type': 'string', + }, 'portal':{ 'section': 'general', 'default': '', diff --git a/hook/zmes_hook_helpers/utils.py b/hook/zmes_hook_helpers/utils.py index 395ac419..799148ea 100644 --- a/hook/zmes_hook_helpers/utils.py +++ b/hook/zmes_hook_helpers/utils.py @@ -172,7 +172,8 @@ def process_config(args, ctx): # parse config file into a dictionary with defaults g.config = {} - + has_secrets = False + secrets_file = None def _correct_type(val,t): if t == 'int': @@ -192,6 +193,19 @@ def _correct_type(val,t): def _set_config_val(k,v): # internal function to parse all keys val = config_file[v['section']].get(k,v['default']) + + if val and val[0] == '!': # its a secret token, so replace + g.logger.debug ('Secret token found in config: {}'.format(val)); + if not has_secrets: + raise ValueError('Secret token found, but no secret file specified') + if secrets_file.has_option('secrets', val[1:]): + vn = secrets_file.get('secrets', val[1:]) + #g.logger.debug ('Replacing {} with {}'.format(val,vn)) + val = vn + else: + raise ValueError ('secret token {} not found in secrets file {}'.format(val,secrets_filename)) + + g.config[k] = _correct_type(val, v['type']) if k.find('password') == -1: dval = g.config[k] @@ -203,9 +217,28 @@ def _set_config_val(k,v): try: config_file = ConfigParser(interpolation=None) config_file.read(args['config']) + + + if config_file.has_option('general','secrets'): + secrets_filename = config_file.get('general', 'secrets') + g.logger.debug ('secret filename: {}'.format(secrets_filename)) + has_secrets = True + secrets_file = ConfigParser(interpolation = None) + try: + with open(secrets_filename) as f: + secrets_file.read_file(f) + except: + raise + else: + g.logger.debug ('No secrets file configured') # now read config values + for k,v in g.config_vals.items(): #g.logger.debug ('processing {} {}'.format(k,v)) + if k == 'secrets': + continue + + _set_config_val(k,v) #g.logger.debug ("done") diff --git a/make_changelog.sh b/make_changelog.sh new file mode 100755 index 00000000..4e2c6c0f --- /dev/null +++ b/make_changelog.sh @@ -0,0 +1,18 @@ +#!/bin/bash +if [ -z "$1" ]; then + echo "Inferring version name from hooks/zmes_hook_helpers/__init__.py" + if [[ `cat hook/zmes_hook_helpers/__init__.py` =~ ^__version__\ =\ \"(.*)\" ]]; + then + TAGVER=${BASH_REMATCH[1]} + else + echo "Bad version parsing" + exit + fi +else + TAGVER=$1 +fi +VER="${TAGVER/v/}" +read -p "Future release is v${VER}. Please press any key to confirm..." +#github_changelog_generator -u pliablepixels -p zmNinja --future-release v${VER} +github_changelog_generator --future-release v${VER} + diff --git a/make_tag.sh b/make_tag.sh new file mode 100755 index 00000000..fb60a98b --- /dev/null +++ b/make_tag.sh @@ -0,0 +1,20 @@ +#!/bin/bash +if [ -z "$1" ]; then + echo "Inferring version name from hooks/zmes_hook_helpers/__init__.py" + if [[ `cat hook/zmes_hook_helpers/__init__.py` =~ ^__version__\ =\ \"(.*)\" ]]; + then + TAGVER=${BASH_REMATCH[1]} + else + echo "Bad version parsing" + exit + fi +else + TAGVER=$1 +fi +VER="${TAGVER/v/}" +echo "Creating tag:v$VER" + +read -p "Please generate CHANGELOG and commit it BEFORE you tag. Press a key when ready..." +read -p "Press any key to create the tag or Ctrl-C to break..." -n1 +git tag -fa v$VER -m"v$VER" +git push -f --tags diff --git a/secrets.ini b/secrets.ini new file mode 100644 index 00000000..dcbd0b1a --- /dev/null +++ b/secrets.ini @@ -0,0 +1,7 @@ +# your secrets file +[secrets] +ZMES_PICTURE_URL=https://portal/zm/index.php?view=image&eid=EVENTID&fid=objdetect&width=600 +#ZMES_PICTURE_URL=https://portal/zm/index.php?view=image&eid=EVENTID&fid=snapshot&width=600 +ZM_USER=user +ZM_PASSWORD=password +ZM_PORTAL=https://portal/zm \ No newline at end of file diff --git a/zmeventnotification.ini b/zmeventnotification.ini index b2fd3cf0..049684da 100644 --- a/zmeventnotification.ini +++ b/zmeventnotification.ini @@ -1,5 +1,10 @@ # Configuration file for zmeventnotification.pl +[general] +# This is an optional file +# If specified, you can specify tokens with secret values in that file +# and onlt refer to the tokens in your main config file +secrets = /etc/zm/secrets.ini [network] # Port for Websockets connection (default: 9000). @@ -96,7 +101,7 @@ include_picture = yes # objdetect is ONLY available in ZM 1.33+ # ** DO NOT PUT PASSWORD AND USERNAME IN URL, see below ** -picture_url = https://yourportal.ddns.net/zm/index.php?view=image&eid=EVENTID&fid=BESTMATCH&width=600 +picture_url = !ZMES_PICTURE_URL #picture_url = https://yourportal.ddns.net/zm/index.php?view=image&eid=EVENTID&fid=objdetect&width=600 #picture_url = https://yourportal.ddns.net/zm/index.php?view=image&eid=EVENTID&fid=snapshot&width=600 #picture_url = https://yourportal.ddns.net/zm/index.php?view=image&eid=EVENTID&fid=alarm&width=600 @@ -104,8 +109,8 @@ picture_url = https://yourportal.ddns.net/zm/index.php?view=image&eid=EVENTID&fi # You need ot specify your ZM portal username and password here. They will be appended to the picture_url # to be able to load the image. DO NOT put the password in the URL because it may have special characters # like "&@# etc that will be considered as URL params/segments/invalid characters -picture_portal_username=yourusername -picture_portal_password=yourpassword +picture_portal_username=!ZM_USER +picture_portal_password=!ZM_PASSWORD [hook] diff --git a/zmeventnotification.pl b/zmeventnotification.pl index 0e5c99aa..ce9965cf 100755 --- a/zmeventnotification.pl +++ b/zmeventnotification.pl @@ -59,7 +59,7 @@ # ========================================================================== -my $app_version="4.4"; +my $app_version="4.5"; # ========================================================================== @@ -157,6 +157,9 @@ my $picture_portal_username; my $picture_portal_password; +my $secrets; +my $secrets_filename; + #default key. Please don't change this use constant NINJA_API_KEY => "AAAApYcZ0mA:APA91bG71SfBuYIaWHJorjmBQB3cAN7OMT7bAxKuV3ByJ4JiIGumG6cQw0Bo6_fHGaWoo4Bl-SlCdxbivTv5Z-2XPf0m86wsebNIG15pyUHojzmRvJKySNwfAHs7sprTGsA_SIR_H43h" @@ -237,6 +240,17 @@ printInfo( "No config file found, using inbuilt defaults" ) ; } +$secrets_filename //= config_get_val($config, "general", "secrets"); +if ($secrets_filename) { + printInfo( "using secrets file: $secrets_filename" ) ; + $secrets = Config::IniFiles->new( -file => $secrets_filename ) ; + unless ( $secrets ) { + Fatal( "Encountered errors while reading $secrets_filename:\n" + . join( "\n", @Config::IniFiles::errors ) ) ; + } +} + + # If an option set a value, leave it. If there's a value in the config, use # it. Otherwise, use a default value if it's available. @@ -320,6 +334,21 @@ sub config_get_val { # parity with hook config if ( lc( $final_val ) eq 'yes' ) { $final_val = 1 ; } elsif ( lc( $final_val ) eq 'no' ) { $final_val = 0 ; } + + + my $fc = substr($final_val, 0,1); + #printInfo ("Parsing $final_val with X${fc}X"); + if ($fc eq "!") { + my $token = substr($final_val, 1); + printDebug ('Got secret token !'.$token); + Fatal ('No secret file found') if (!$secrets); + my $secret_val = $secrets->val('secrets', $token); + Fatal ('Token:'.$token.' not found in secret file') if (!$secret_val); + #printInfo ('replacing with:'.$secret_val); + $final_val = $secret_val; + } + + #printInfo("RETURNING --> $final_val"); return $final_val ; } @@ -348,6 +377,8 @@ sub print_config { "Default configuration ($abs_config_file doesn't exist)" )}: +Secrets file................... ${\(value_or_undefined($secrets_filename))} + Port .......................... ${\(value_or_undefined($port))} Address ....................... ${\(value_or_undefined($address))} Event check interval .......... ${\(value_or_undefined($event_check_interval))}