diff --git a/services/univention-admin-diary/python/admindiary/de.po b/services/univention-admin-diary/python/admindiary/de.po new file mode 100644 index 0000000000..b39742535a --- /dev/null +++ b/services/univention-admin-diary/python/admindiary/de.po @@ -0,0 +1,41 @@ +# This file is auto-generated by the dh-umc tools and should not be edited! +msgid "" +msgstr "" +"Project-Id-Version: univention-admin-diary\n" +"Report-Msgid-Bugs-To: packages@univention.de\n" +"POT-Creation-Date: Mon, 10 Jan 2019 18:22:31 +0100\n" +"PO-Revision-Date: \n" +"Last-Translator: Univention GmbH \n" +"Language-Team: Univention GmbH \n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: python/admindiary/events.py:53 +#, python-format +msgid "User %s created" +msgstr "Benutzer %s angelegt" + +#: python/admindiary/events.py:55 +#, python-format +msgid "App %s: Start of %s" +msgstr "App %s: Start von %s" + +#: python/admindiary/events.py:56 +#, python-format +msgid "App %s (%s): Success" +msgstr "App %s (%s): Erfolg" + +#: python/admindiary/events.py:57 +#, python-format +msgid "App %s (%s): Failure. Error %s" +msgstr "App %s (%s): Fehlschlag. Fehler %s" + +#: python/admindiary/events.py:59 +msgid "Machine account password changed successfully" +msgstr "Maschinenpasswort erfolgreich geändert" + +#: python/admindiary/events.py:60 +msgid "Machine account password change failed" +msgstr "Änderung des Maschinenpassworts fehlgeschlagen" diff --git a/management/univention-appcenter/python/appcenter/actions/install_base.py b/management/univention-appcenter/python/appcenter/actions/install_base.py index 5014122b8b..194df55be8 100644 --- a/management/univention-appcenter/python/appcenter/actions/install_base.py +++ b/management/univention-appcenter/python/appcenter/actions/install_base.py @@ -88,7 +88,7 @@ class InstallRemoveUpgrade(Register): app = args.app status = 200 status_details = None - diary_id = write_event(APP_ACTION_START, [app, self.get_action_name()]) + context_id = write_event(APP_ACTION_START, [app, self.get_action_name()]) try: action = self.get_action_name() self.log('Going to %s %s (%s)' % (action, app.name, app.version)) @@ -149,9 +149,9 @@ class InstallRemoveUpgrade(Register): pass else: if status == 200: - write_event(APP_ACTION_SUCCESS, [app, self.get_action_name()], diary_id=diary_id) + write_event(APP_ACTION_SUCCESS, [app, self.get_action_name()], context_id=context_id) else: - write_event(APP_ACTION_FAILURE, [app, self.get_action_name(), status], diary_id=diary_id) + write_event(APP_ACTION_FAILURE, [app, self.get_action_name(), status], context_id=context_id) if status != 200: self._revert(app, args) if args.send_info: diff --git a/services/univention-admin-diary/60univention-admin-diary-client.inst b/services/univention-admin-diary/60univention-admin-diary-client.inst index c530eaa074..e680b54cb3 100755 --- a/services/univention-admin-diary/60univention-admin-diary-client.inst +++ b/services/univention-admin-diary/60univention-admin-diary-client.inst @@ -44,8 +44,9 @@ set_admin_diary_backend() { local cn_list local fqdn_list - ldif=$(univention-ldapsearch univentionService="Admin Diary Backend" cn) + ldif=$(univention-ldapsearch -LLL -o ldif-wrap=no univentionService="Admin Diary Backend" cn) cn_list=( "$(sed -n 's/^cn: //p' <<<"$ldif")" ) + [ -n "$cn_list" ] || return fqdn_list=( "${cn_list[@]/%/".$domainname"}" ) univention-config-registry set \ diff --git a/services/univention-admin-diary/debian/univention-admin-diary-backend.postinst b/services/univention-admin-diary/debian/univention-admin-diary-backend.postinst index 292da3f0ea..0bb8f19038 100644 --- a/services/univention-admin-diary/debian/univention-admin-diary-backend.postinst +++ b/services/univention-admin-diary/debian/univention-admin-diary-backend.postinst @@ -31,26 +31,40 @@ #DEBHELPER# -SECRET_FILE="/etc/admin-diary.secret" -if [ ! -e "$SECRET_FILE" ]; then - touch "$SECRET_FILE" - chmod 0700 "$SECRET_FILE" - PASSWORD="$(< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c20)" - echo "$PASSWORD" > "$SECRET_FILE" -fi +eval "$(ucr shell admin/diary/db.*)" +if [ -z "$admin_diary_dbhost" ] \ + || [ "$admin_diary_dbhost" = "localhost" ]; then + + SECRET_FILE="/etc/admin-diary.secret" + if [ ! -e "$SECRET_FILE" ]; then + install -m 0700 "$SECRET_FILE" + touch "$SECRET_FILE" + chmod 0700 "$SECRET_FILE" + PASSWORD="$(< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c20)" + echo -n "$PASSWORD" > "$SECRET_FILE" + fi -which psql -if [ "$?" -eq "0" ]; then - ucr set admin/diary/dbms?postgresql -else - ucr set admin/diary/dbms?mysql + if command -v psql >/dev/null; then + ucr set admin/diary/dbms?postgresql + else + ucr set admin/diary/dbms?mysql + fi +elif [ -z "$admin_diary_dbms" ]; then + echo "ERROR: admin/diary/dbhost is set in UCR but admin/diary/dbms is not" 2>&1 + exit 1 fi -univention-config-registry set \ - security/packetfilter/package/univention-admin-diary/tcp/10514/all=ACCEPT \ - security/packetfilter/package/univention-admin-diary/tcp/10514/all/en="rsyslog relp+TLS" -invoke-rc.d univention-firewall restart +case "$1" in + configure) + if [ -z "$2" ]; then # Installation + univention-config-registry set \ + security/packetfilter/package/univention-admin-diary/tcp/10514/all=ACCEPT \ + security/packetfilter/package/univention-admin-diary/tcp/10514/all/en="rsyslog relp+TLS" + invoke-rc.d univention-firewall restart -invoke-rc.d rsyslog try-restart + invoke-rc.d rsyslog try-restart + fi + ;; +esac exit 0 diff --git a/services/univention-admin-diary/python/admindiary/__init__.py b/services/univention-admin-diary/python/admindiary/__init__.py index 5fb00427f7..b2bd0ed3f1 100644 --- a/services/univention-admin-diary/python/admindiary/__init__.py +++ b/services/univention-admin-diary/python/admindiary/__init__.py @@ -45,7 +45,7 @@ class _ShortNameFormatter(logging.Formatter): return super(_ShortNameFormatter, self).format(record) -def _setup_logger(): +def _setup_logger(loglevel): base_logger = logging.getLogger('univention.admindiary') if not _setup_logger._setup: log_format = '%(process)6d %(short_name)-12s %(asctime)s [%(levelname)8s]: %(message)s' @@ -54,26 +54,26 @@ def _setup_logger(): handler = logging.FileHandler(LOG_FILE) handler.setFormatter(formatter) base_logger.addHandler(handler) - base_logger.setLevel(logging.DEBUG) + base_logger.setLevel(loglevel) _setup_logger._setup = True return base_logger _setup_logger._setup = False -def get_logger(name): - base_logger = _setup_logger() +def get_logger(name, loglevel=logging.WARNING): + base_logger = _setup_logger(loglevel) return base_logger.getChild(name) class DiaryEntry(object): - def __init__(self, username, message, args, tags, diary_id, event_name): + def __init__(self, username, message, args, tags, context_id, event_name): self.username = username self.hostname = getfqdn() self.message = message self.args = [str(arg) for arg in args] - self.issued = datetime.now() + self.timestamp = datetime.now() self.tags = tags - self.diary_id = diary_id + self.context_id = context_id self.event_name = event_name def assert_types(self): @@ -85,11 +85,11 @@ class DiaryEntry(object): raise TypeError('Message has to be "string"') if not isinstance(self.args, list) or not all(isinstance(arg, basestring) for arg in self.args): raise TypeError('Args have to be "list of string"') - if not isinstance(self.issued, datetime): - raise TypeError('Issued has to be "datetime"') + if not isinstance(self.timestamp, datetime): + raise TypeError('timestamp has to be "datetime"') if not isinstance(self.tags, list) or not all(isinstance(tag, basestring) for tag in self.tags): raise TypeError('Tags have to be "list of string"') - if not isinstance(self.diary_id, basestring): + if not isinstance(self.context_id, basestring): raise TypeError('Diary ID has to be "string"') if not isinstance(self.event_name, basestring): raise TypeError('Event name has to be "string"') @@ -100,9 +100,9 @@ class DiaryEntry(object): 'hostname': self.hostname, 'message': self.message, 'args': self.args, - 'issued': self.issued.strftime('%Y-%m-%d %H:%M:%S%z'), + 'timestamp': self.timestamp.strftime('%Y-%m-%d %H:%M:%S%z'), 'tags': self.tags, - 'diary_id': self.diary_id, + 'context_id': self.context_id, 'event': self.event_name, } return json.dumps(attrs) @@ -110,8 +110,8 @@ class DiaryEntry(object): @classmethod def from_json(cls, body): json_body = json.loads(body) - entry = cls(json_body['username'], json_body['message'], json_body['args'], json_body['tags'], json_body['diary_id'], json_body['event']) - entry.issued = datetime.strptime(json_body['issued'], '%Y-%m-%d %H:%M:%S') + entry = cls(json_body['username'], json_body['message'], json_body['args'], json_body['tags'], json_body['context_id'], json_body['event']) + entry.timestamp = datetime.strptime(json_body['timestamp'], '%Y-%m-%d %H:%M:%S') entry.hostname = json_body['hostname'] entry.assert_types() return entry diff --git a/services/univention-admin-diary/python/admindiary/backend.py b/services/univention-admin-diary/python/admindiary/backend.py index eec14b01f1..7107ee3be3 100644 --- a/services/univention-admin-diary/python/admindiary/backend.py +++ b/services/univention-admin-diary/python/admindiary/backend.py @@ -42,15 +42,16 @@ ucr.load() password = open('/etc/admin-diary.secret').read().strip() dbms = ucr.get('admin/diary/dbms') +dbhost = ucr.get('admin/diary/dbhost', 'localhost') get_logger = partial(get_logger, 'backend') @contextmanager def connection(module): if dbms == 'mysql': - conn = module.connect(db='admindiary', user='admindiary', host='localhost', passwd=password) + conn = module.connect(db='admindiary', user='admindiary', host=dbhost, passwd=password) elif dbms == 'postgresql': - conn = module.connect(dbname='admindiary', user='admindiary', host='localhost', password=password) + conn = module.connect(dbname='admindiary', user='admindiary', host=dbhost, password=password) yield conn conn.commit() conn.close() @@ -68,12 +69,12 @@ if ucr.get('admin/diary/dbms') == 'postgresql': def _postgresql_add(entry): with cursor(psycopg2) as cur: - cur.execute("INSERT INTO entries (username, hostname, message, args, issued, tags, diary_id, event_name) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)", (entry.username, entry.hostname, entry.message, entry.args, entry.issued, entry.tags, entry.diary_id, entry.event_name)) - get_logger().info('Successfully added %s to postgresql. (%s)' % (entry.diary_id, entry.event_name)) + cur.execute("INSERT INTO entries (username, hostname, message, args, timestamp, tags, context_id, event_name) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)", (entry.username, entry.hostname, entry.message, entry.args, entry.timestamp, entry.tags, entry.context_id, entry.event_name)) + get_logger().info('Successfully added %s to postgresql. (%s)' % (entry.context_id, entry.event_name)) def _postgresql_query(): with cursor(psycopg2) as cur: - args = ['id', 'username', 'hostname', 'message', 'args', 'issued', 'tags', 'diary_id', 'event_name'] + args = ['id', 'username', 'hostname', 'message', 'args', 'timestamp', 'tags', 'context_id', 'event_name'] cur.execute("SELECT %s FROM entries" % ', '.join(args)) rows = cur.fetchall() res = [dict(zip(args, row)) for row in rows] @@ -90,17 +91,17 @@ elif ucr.get('admin/diary/dbms') == 'mysql': def _mysql_add(entry): with cursor(MySQLdb) as cur: - cur.execute("INSERT INTO entries (username, hostname, message, issued, diary_id, event_name) VALUES (%s, %s, %s, %s, %s, %s)", (entry.username, entry.hostname, entry.message, entry.issued, entry.diary_id, entry.event_name)) + cur.execute("INSERT INTO entries (username, hostname, message, timestamp, context_id, event_name) VALUES (%s, %s, %s, %s, %s, %s)", (entry.username, entry.hostname, entry.message, entry.timestamp, entry.context_id, entry.event_name)) entry_id = cur.lastrowid for arg in entry.args: cur.execute("INSERT INTO arguments (log_entry_id, arg) VALUES (%s, %s)", (entry_id, arg)) for tag in entry.tags: cur.execute("INSERT INTO tags (log_entry_id, tag) VALUES (%s, %s)", (entry_id, tag)) - get_logger().info('Successfully added %s to mysql. (%s)' % (entry.diary_id, entry.event_name)) + get_logger().info('Successfully added %s to mysql. (%s)' % (entry.context_id, entry.event_name)) def _mysql_query(): with cursor(MySQLdb) as cur: - args = ['id', 'username', 'hostname', 'message', 'issued', 'diary_id', 'event_name'] + args = ['id', 'username', 'hostname', 'message', 'timestamp', 'context_id', 'event_name'] cur.execute("SELECT %s FROM entries" % ', '.join(args)) rows = cur.fetchall() res = [dict(zip(args, row)) for row in rows] diff --git a/services/univention-admin-diary/python/admindiary/client.py b/services/univention-admin-diary/python/admindiary/client.py index 337ca71e8d..edf2891273 100644 --- a/services/univention-admin-diary/python/admindiary/client.py +++ b/services/univention-admin-diary/python/admindiary/client.py @@ -39,7 +39,7 @@ from functools import partial, wraps get_logger = partial(get_logger, 'client') -def safe(f): +def exceptionlogging(f): @wraps(f) def wrapper(*args, **kwds): try: @@ -63,41 +63,41 @@ class RsyslogEmitter(object): emitter = RsyslogEmitter() -@safe -def add_comment(message, diary_id, username=None): +@exceptionlogging +def add_comment(message, context_id, username=None): event = Event('COMMENT', message) - return write_event(event, username=username, diary_id=diary_id) + return write_event(event, username=username, context_id=context_id) -@safe -def write_event(event, args=None, username=None, diary_id=None): +@exceptionlogging +def write_event(event, args=None, username=None, context_id=None): args = args or [] if not isinstance(args, (list, tuple)): raise TypeError('"args" must be a list') if len(args) != len(event.args): raise ValueError('Writing "%s" needs %d argument(s) (%s). %d given' % (event.message, len(event.args), ', '.join(event.args), len(args))) - return write(event.message, args, username, event.tags, diary_id, event.name) + return write(event.message, args, username, event.tags, context_id, event.name) -@safe -def write(message, args=None, username=None, tags=None, diary_id=None, event_name=None): +@exceptionlogging +def write(message, args=None, username=None, tags=None, context_id=None, event_name=None): if username is None: username = getuser() if args is None: args = [] if tags is None: tags = [] - if diary_id is None: - diary_id = str(uuid.uuid4()) + if context_id is None: + context_id = str(uuid.uuid4()) if event_name is None: event_name = 'CUSTOM' - entry = DiaryEntry(username, message, args, tags, diary_id, event_name) + entry = DiaryEntry(username, message, args, tags, context_id, event_name) return write_entry(entry) -@safe +@exceptionlogging def write_entry(entry): body = entry.to_json() emitter.emit(body) - get_logger().info('Successfully wrote %s. (%s)' % (entry.diary_id, entry.event_name)) - return entry.diary_id + get_logger().info('Successfully wrote %s. (%s)' % (entry.context_id, entry.event_name)) + return entry.context_id diff --git a/services/univention-admin-diary/python/admindiary/events.py b/services/univention-admin-diary/python/admindiary/events.py index 5860a4a001..7280f810fc 100644 --- a/services/univention-admin-diary/python/admindiary/events.py +++ b/services/univention-admin-diary/python/admindiary/events.py @@ -46,11 +46,15 @@ class Event(object): self.tags = tags or [] self._all_events[self.name] = self -USER_CREATED = Event('USER_CREATED', 'User %s created', ['username']) +def _(msg): + """dummy for xgettext""" + return msg -APP_ACTION_START = Event('APP_ACTION_START', 'App %s: Starting to %s', ['app', 'action']) -APP_ACTION_SUCCESS = Event('APP_ACTION_SUCCESS', 'App %s (%s): Success', ['app', 'action']) -APP_ACTION_FAILURE = Event('APP_ACTION_FAILURE', 'App %s (%s): Failure. Error %s', ['app', 'action', 'error_code'], tags=['error']) +USER_CREATED = Event('USER_CREATED', _('User %s created'), ['username']) -SERVER_PASSWORD_CHANGED = Event('SERVER_PASSWORD_CHANGED', 'Machine account password changed successfully') -SERVER_PASSWORD_CHANGED_FAILED = Event('SERVER_PASSWORD_CHANGED_FAILED', 'Machine account password change failed!', tags=['error']) +APP_ACTION_START = Event('APP_ACTION_START', _('App %s: Start of %s'), ['app', 'action']) +APP_ACTION_SUCCESS = Event('APP_ACTION_SUCCESS', _('App %s (%s): Success'), ['app', 'action']) +APP_ACTION_FAILURE = Event('APP_ACTION_FAILURE', _('App %s (%s): Failure. Error %s'), ['app', 'action', 'error_code'], tags=['error']) + +SERVER_PASSWORD_CHANGED = Event('SERVER_PASSWORD_CHANGED', _('Machine account password changed successfully')) +SERVER_PASSWORD_CHANGED_FAILED = Event('SERVER_PASSWORD_CHANGED_FAILED', _('Machine account password change failed'), tags=['error']) diff --git a/services/univention-admin-diary/setup-dbms b/services/univention-admin-diary/setup-dbms index d55164b75b..639e113788 100755 --- a/services/univention-admin-diary/setup-dbms +++ b/services/univention-admin-diary/setup-dbms @@ -40,9 +40,9 @@ if [ "$db_backend" = "postgresql" ]; then hostname VARCHAR NOT NULL, message TEXT NOT NULL, args VARCHAR[], - issued TIMESTAMPTZ NOT NULL, + timestamp TIMESTAMPTZ NOT NULL, tags VARCHAR[], - diary_id VARCHAR NOT NULL, + context_id VARCHAR NOT NULL, event_name VARCHAR NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); @@ -55,8 +55,8 @@ elif [ "$db_backend" = "mysql" ]; then username VARCHAR(512) NOT NULL, hostname VARCHAR(512) NOT NULL, message TEXT NOT NULL, - issued TIMESTAMP NOT NULL, - diary_id VARCHAR(512) NOT NULL, + timestamp TIMESTAMP NOT NULL, + context_id VARCHAR(512) NOT NULL, event_name VARCHAR(512) NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT NOW(), PRIMARY KEY(id) diff --git a/services/univention-admin-diary/univention-admin-diary-entry-create b/services/univention-admin-diary/univention-admin-diary-entry-create index e099303e48..0848eeebe5 100755 --- a/services/univention-admin-diary/univention-admin-diary-entry-create +++ b/services/univention-admin-diary/univention-admin-diary-entry-create @@ -45,20 +45,20 @@ def main(): parser.add_argument('-u', '--username', help='Username that issues the diary entry') parser.add_argument('-t', '--tag', action='append', help='Tags added to the diary entry') parser.add_argument('-a', '--arg', action='append', help='Argument used in message') - parser.add_argument('--event', choices=Event.names(), help='Choose one from this convenience list instead of giving TAG and ') - parser.add_argument('--diary-id', help='May be given to ammend an existing diary entry, effectively grouping those together. The DIARY_ID is also returned by this program') + parser.add_argument('--event', choices=Event.names(), help='Choose one from this standard list instead of giving TAG and ') + parser.add_argument('--context-id', help='May be given to ammend an existing diary entry, effectively grouping those together. The CONTEXT_ID is also returned by this program') parser.add_argument('message', nargs=REMAINDER, help='The message') args = parser.parse_args() if args.event: event = Event.get(args.event) - diary_id = write_event(event, args.arg, args.username, args.diary_id) - if diary_id is not None: - print diary_id + context_id = write_event(event, args.arg, args.username, args.context_id) + if context_id is not None: + print context_id else: print >> sys.stderr, 'Could not write event' sys.exit(1) else: - print write(' '.join(args.message), args.arg, args.username, args.tag, args.diary_id) + print write(' '.join(args.message), args.arg, args.username, args.tag, args.context_id) if __name__ == '__main__': main()