Skip to content

Commit

Permalink
Merge remote-tracking branch 'apache/master' into ZOOKEEPER-3188
Browse files Browse the repository at this point in the history
  • Loading branch information
Mate Szalay-Beko committed Nov 13, 2019
2 parents 0f95678 + 794adf1 commit 31805e7
Show file tree
Hide file tree
Showing 59 changed files with 3,589 additions and 89 deletions.
17 changes: 17 additions & 0 deletions conf/log4j.properties
Expand Up @@ -63,3 +63,20 @@ log4j.appender.TRACEFILE.File=${zookeeper.tracelog.dir}/${zookeeper.tracelog.fil
log4j.appender.TRACEFILE.layout=org.apache.log4j.PatternLayout
### Notice we are including log4j's NDC here (%x)
log4j.appender.TRACEFILE.layout.ConversionPattern=%d{ISO8601} [myid:%X{myid}] - %-5p [%t:%C{1}@%L][%x] - %m%n
#
# zk audit logging
#
zookeeper.auditlog.file=zookeeper_audit.log
zookeeper.auditlog.threshold=INFO
audit.logger=INFO, RFAAUDIT
log4j.logger.org.apache.zookeeper.audit.Log4jAuditLogger=${audit.logger}
log4j.additivity.org.apache.zookeeper.audit.Log4jAuditLogger=false
log4j.appender.RFAAUDIT=org.apache.log4j.RollingFileAppender
log4j.appender.RFAAUDIT.File=${zookeeper.log.dir}/${zookeeper.auditlog.file}
log4j.appender.RFAAUDIT.layout=org.apache.log4j.PatternLayout
log4j.appender.RFAAUDIT.layout.ConversionPattern=%d{ISO8601} %p %c{2}: %m%n
log4j.appender.RFAAUDIT.Threshold=${zookeeper.auditlog.threshold}

# Max log file size of 10MB
log4j.appender.RFAAUDIT.MaxFileSize=10MB
log4j.appender.RFAAUDIT.MaxBackupIndex=10
3 changes: 3 additions & 0 deletions zookeeper-docs/src/main/resources/markdown/html/header.html
Expand Up @@ -104,6 +104,9 @@
</div>
<div class="menuitem">
<a href="zookeeperReconfig.html">Dynamic Reconfiguration</a>
</div>
<div class="menuitem">
<a href="zookeeperAuditLogs.html">Audit Logs</a>
</div>
</div>
<div onclick="SwitchMenu('menu_4', 'skin/')" id="menu_4Title" class="menutitle">Contributor</div>
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions zookeeper-docs/src/main/resources/markdown/index.md
Expand Up @@ -53,6 +53,7 @@ archives.
+ [ZooKeeper CLI](zookeeperCLI.html) - a guide on how to use the ZooKeeper command line interface
+ [ZooKeeper Tools](zookeeperTools.html) - a guide on how to use a series of tools for ZooKeeper
+ [ZooKeeper Monitor](zookeeperMonitor.html) - a guide on how to monitor the ZooKeeper
+ [Audit Logging](zookeeperAuditLogs.html) - a guide on how to configure audit logs in ZooKeeper Server and what contents are logged.
+ **Contributors**
Documents for Developers Contributing to the ZooKeeper Open Source Project
+ [ZooKeeper Internals](zookeeperInternals.html) - assorted topics on the inner workings of ZooKeeper
Expand Down
12 changes: 12 additions & 0 deletions zookeeper-docs/src/main/resources/markdown/zookeeperAdmin.md
Expand Up @@ -956,6 +956,18 @@ property, when available, is noted below.
and restart ZooKeeper process so ZooKeeper can continue normal data
consistency check during recovery process.
Default value is false.
* *audit.enable* :
(Java system property: **zookeeper.audit.enable**)
**New in 3.6.0:**
By default audit logs are disabled. Set to "true" to enable it. Default value is "false".
See the [ZooKeeper audit logs](zookeeperAuditLogs.html) for more information.

* *audit.impl.class* :
(Java system property: **zookeeper.audit.impl.class**)
**New in 3.6.0:**
Class to implement the audit logger. By default log4j based audit logger org.apache.zookeeper.audit
.Log4jAuditLogger is used.
See the [ZooKeeper audit logs](zookeeperAuditLogs.html) for more information.

* *largeRequestMaxBytes* :
(Java system property: **zookeeper.largeRequestMaxBytes**)
Expand Down
129 changes: 129 additions & 0 deletions zookeeper-docs/src/main/resources/markdown/zookeeperAuditLogs.md
@@ -0,0 +1,129 @@
<!--
Copyright 2002-2004 The Apache Software Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
//-->

# ZooKeeper Audit Logging

* [ZooKeeper Audit Logs](#ch_auditLogs)
* [ZooKeeper Audit Log Configuration](#ch_reconfig_format)
* [Who is taken as user in audit logs?](#ch_zkAuditUser)
<a name="ch_auditLogs"></a>

## ZooKeeper Audit Logs

Apache ZooKeeper supports audit logs from version 3.6.0. By default audit logs are disabled. To enable audit logs
configure audit.enable=true in conf/zoo.cfg. Audit logs are not logged on all the ZooKeeper servers, but logged only on the servers where client is connected as depicted in below figure.

![Audit Logs](images/zkAuditLogs.jpg)


The audit log captures detailed information for the operations that are selected to be audited. The audit information is written as a set of key=value pairs for the following keys

| Key | Value |
| ----- | ----- |
|session | client session id |
|user | comma separated list of users who are associate with a client session. For more on this, see [Who is taken as user in audit logs](#ch_zkAuditUser).
|ip | client IP address
|operation | any one of the selected operations for audit. Possible values are(serverStart, serverStop, create, delete, setData, setAcl, multiOperation, reconfig, ephemeralZNodeDeleteOnSessionClose)
|znode | path of the znode
|znode type | type of znode in case of creation operation
|acl | String representation of znode ACL like cdrwa(create, delete,read, write, admin). This is logged only for setAcl operation
|result | result of the operation. Possible values are (success/failure/invoked). Result "invoked" is used for serverStop operation because stop is logged before ensuring that server actually stopped.

Below are sample audit logs for all operations, where client is connected from 192.168.1.2, client principal is zkcli@HADOOP.COM, server principal is zookeeper/192.168.1.3@HADOOP.COM

user=zookeeper/192.168.1.3 operation=serverStart result=success
session=0x19344730000 user=192.168.1.2,zkcli@HADOOP.COM ip=192.168.1.2 operation=create znode=/a znode_type=persistent result=success
session=0x19344730000 user=192.168.1.2,zkcli@HADOOP.COM ip=192.168.1.2 operation=create znode=/a znode_type=persistent result=failure
session=0x19344730000 user=192.168.1.2,zkcli@HADOOP.COM ip=192.168.1.2 operation=setData znode=/a result=failure
session=0x19344730000 user=192.168.1.2,zkcli@HADOOP.COM ip=192.168.1.2 operation=setData znode=/a result=success
session=0x19344730000 user=192.168.1.2,zkcli@HADOOP.COM ip=192.168.1.2 operation=setAcl znode=/a acl=world:anyone:cdrwa result=failure
session=0x19344730000 user=192.168.1.2,zkcli@HADOOP.COM ip=192.168.1.2 operation=setAcl znode=/a acl=world:anyone:cdrwa result=success
session=0x19344730000 user=192.168.1.2,zkcli@HADOOP.COM ip=192.168.1.2 operation=create znode=/b znode_type=persistent result=success
session=0x19344730000 user=192.168.1.2,zkcli@HADOOP.COM ip=192.168.1.2 operation=setData znode=/b result=success
session=0x19344730000 user=192.168.1.2,zkcli@HADOOP.COM ip=192.168.1.2 operation=delete znode=/b result=success
session=0x19344730000 user=192.168.1.2,zkcli@HADOOP.COM ip=192.168.1.2 operation=multiOperation result=failure
session=0x19344730000 user=192.168.1.2,zkcli@HADOOP.COM ip=192.168.1.2 operation=delete znode=/a result=failure
session=0x19344730000 user=192.168.1.2,zkcli@HADOOP.COM ip=192.168.1.2 operation=delete znode=/a result=success
session=0x19344730001 user=192.168.1.2,zkcli@HADOOP.COM ip=192.168.1.2 operation=create znode=/ephemral znode_type=ephemral result=success
session=0x19344730001 user=zookeeper/192.168.1.3 operation=ephemeralZNodeDeletionOnSessionCloseOrExpire znode=/ephemral result=success
session=0x19344730000 user=192.168.1.2,zkcli@HADOOP.COM ip=192.168.1.2 operation=reconfig znode=/zookeeper/config result=success
user=zookeeper/192.168.1.3 operation=serverStop result=invoked

<a name="ch_auditConfig"></a>

## ZooKeeper Audit Log Configuration

By default audit logs are disabled. To enable audit logs configure audit.enable=true in conf/zoo.cfg. Audit logging is done using log4j. Following is the default log4j configuration for audit logs in conf/log4j.properties

#
# zk audit logging
#
zookeeper.auditlog.file=zookeeper_audit.log
zookeeper.auditlog.threshold=INFO
audit.logger=INFO, RFAAUDIT
log4j.logger.org.apache.zookeeper.audit.Log4jAuditLogger=${audit.logger}
log4j.additivity.org.apache.zookeeper.audit.Log4jAuditLogger=false
log4j.appender.RFAAUDIT=org.apache.log4j.RollingFileAppender
log4j.appender.RFAAUDIT.File=${zookeeper.log.dir}/${zookeeper.auditlog.file}
log4j.appender.RFAAUDIT.layout=org.apache.log4j.PatternLayout
log4j.appender.RFAAUDIT.layout.ConversionPattern=%d{ISO8601} %p %c{2}: %m%n
log4j.appender.RFAAUDIT.Threshold=${zookeeper.auditlog.threshold}

# Max log file size of 10MB
log4j.appender.RFAAUDIT.MaxFileSize=10MB
log4j.appender.RFAAUDIT.MaxBackupIndex=10

Change above configuration to customize the auditlog file, number of backups, max file size, custom audit logger etc.

<a name="ch_zkAuditUser"></a>

## Who is taken as user in audit logs?

By default there are only four authentication provider:

* IPAuthenticationProvider
* SASLAuthenticationProvider
* X509AuthenticationProvider
* DigestAuthenticationProvider

User is decided based on the configured authentication provider:

* When IPAuthenticationProvider is configured then authenticated IP is taken as user
* When SASLAuthenticationProvider is configured then client principal is taken as user
* When X509AuthenticationProvider is configured then client certificate is taken as user
* When DigestAuthenticationProvider is configured then authenticated user is user

Custom authentication provider can override org.apache.zookeeper.server.auth.AuthenticationProvider.getUserName(String id)
to provide user name. If authentication provider is not overriding this method then whatever is stored in
org.apache.zookeeper.data.Id.id is taken as user.
Generally only user name is stored in this field but it is up to the custom authentication provider what they store in it.
For audit logging value of org.apache.zookeeper.data.Id.id would be taken as user.

In ZooKeeper Server not all the operations are done by clients but some operations are done by the server itself. For example when client closes the session, ephemeral znodes are deleted by the Server. These deletion are not done by clients directly but it is done the server itself these are called system operations. For these system operations the user associated with the ZooKeeper server are taken as user while audit logging these operations. For example if in ZooKeeper server principal is zookeeper/hadoop.hadoop.com@HADOOP.COM then this becomes the system user and all the system operations will be logged with this user name.

user=zookeeper/hadoop.hadoop.com@HADOOP.COM operation=serverStart result=success


If there is no user associate with ZooKeeper server then the user who started the ZooKeeper server is taken as the user. For example if server started by root then root is taken as the system user

user=root operation=serverStart result=success


Single client can attach multiple authentication schemes to a session, in this case all authenticated schemes will taken taken as user and will be presented as comma separated list. For example if a client is authenticate with principal zkcli@HADOOP.COM and ip 127.0.0.1 then create znode audit log will be as:

session=0x10c0bcb0000 user=zkcli@HADOOP.COM,127.0.0.1 ip=127.0.0.1 operation=create znode=/a result=success


5 changes: 5 additions & 0 deletions zookeeper-docs/src/main/resources/markdown/zookeeperOver.md
Expand Up @@ -146,6 +146,11 @@ receives a packet saying that the znode has changed. If the
connection between the client and one of the ZooKeeper servers is
broken, the client will receive a local notification.

**New in 3.6.0:** Clients can also set
permanent, recursive watches on a znode that are not removed when triggered
and that trigger for changes on the registered znode as well as any children
znodes recursively.

<a name="Guarantees"></a>

### Guarantees
Expand Down
27 changes: 25 additions & 2 deletions zookeeper-docs/src/main/resources/markdown/zookeeperProgrammers.md
Expand Up @@ -32,6 +32,7 @@ limitations under the License.
* [ZooKeeper Sessions](#ch_zkSessions)
* [ZooKeeper Watches](#ch_zkWatches)
* [Semantics of Watches](#sc_WatchSemantics)
* [Persistent, Recursive Watches](#sc_WatchPersistentRecursive)
* [Remove Watches](#sc_WatchRemoval)
* [What ZooKeeper Guarantees about Watches](#sc_WatchGuarantees)
* [Things to Remember about Watches](#sc_WatchRememberThese)
Expand Down Expand Up @@ -640,6 +641,11 @@ general this all occurs transparently. There is one case where a watch
may be missed: a watch for the existence of a znode not yet created will
be missed if the znode is created and deleted while disconnected.

**New in 3.6.0:** Clients can also set
permanent, recursive watches on a znode that are not removed when triggered
and that trigger for changes on the registered znode as well as any children
znodes recursively.

<a name="sc_WatchSemantics"></a>

### Semantics of Watches
Expand All @@ -657,6 +663,21 @@ the events that a watch can trigger and the calls that enable them:
* **Child event:**
Enabled with a call to getChildren.

<a name="sc_WatchPersistentRecursive"></a>

### Persistent, Recursive Watches

**New in 3.6.0:** There is now a variation on the standard
watch described above whereby you can set a watch that does not get removed when triggered.
Additionally, these watches trigger the event types *NodeCreated*, *NodeDeleted*, and *NodeDataChanged*
and, optionally, recursively for all znodes starting at the znode that the watch is registered for. Note
that *NodeChildrenChanged* events are not triggered for persistent recursive watches as it would be redundant.

Persistent watches are set using the method *addWatch()*. The triggering semantics and guarantees
(other than one-time triggering) are the same as standard watches. The only exception regarding events is that
recursive persistent watchers never trigger child changed events as they are redundant.
Persistent watches are removed using *removeWatches()* with watcher type *WatcherType.Any*.

<a name="sc_WatchRemoval"></a>

### Remove Watches
Expand All @@ -671,6 +692,8 @@ successful watch removal.
Watcher which was added with a call to getChildren.
* **Data Remove event:**
Watcher which was added with a call to exists or getData.
* **Persistent Remove event:**
Watcher which was added with a call to add a persistent watch.

<a name="sc_WatchGuarantees"></a>

Expand All @@ -693,11 +716,11 @@ guarantees:

### Things to Remember about Watches

* Watches are one time triggers; if you get a watch event and
* Standard watches are one time triggers; if you get a watch event and
you want to get notified of future changes, you must set another
watch.

* Because watches are one time triggers and there is latency
* Because standard watches are one time triggers and there is latency
between getting the event and sending a new request to get a watch
you cannot reliably see every change that happens to a node in
ZooKeeper. Be prepared to handle the case where the znode changes
Expand Down
12 changes: 12 additions & 0 deletions zookeeper-jute/src/main/resources/zookeeper.jute
Expand Up @@ -73,6 +73,14 @@ module org.apache.zookeeper.proto {
vector<ustring>existWatches;
vector<ustring>childWatches;
}
class SetWatches2 {
long relativeZxid;
vector<ustring>dataWatches;
vector<ustring>existWatches;
vector<ustring>childWatches;
vector<ustring>persistentWatches;
vector<ustring>persistentRecursiveWatches;
}
class RequestHeader {
int xid;
int type;
Expand Down Expand Up @@ -180,6 +188,10 @@ module org.apache.zookeeper.proto {
class SetACLResponse {
org.apache.zookeeper.data.Stat stat;
}
class AddWatchRequest {
ustring path;
int mode;
}
class WatcherEvent {
int type; // event type
int state; // state of the Keeper client runtime
Expand Down
@@ -0,0 +1,67 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.zookeeper;

/**
* Modes available to {@link ZooKeeper#addWatch(String, Watcher, AddWatchMode)}
*/
public enum AddWatchMode {
/**
* <p>
* Set a watcher on the given path that does not get removed when triggered (i.e. it stays active
* until it is removed). This watcher
* is triggered for both data and child events. To remove the watcher, use
* <tt>removeWatches()</tt> with <tt>WatcherType.Any</tt>. The watcher behaves as if you placed an exists() watch and
* a getData() watch on the ZNode at the given path.
* </p>
*/
PERSISTENT(ZooDefs.AddWatchModes.persistent),

/**
* <p>
* Set a watcher on the given path that: a) does not get removed when triggered (i.e. it stays active
* until it is removed); b) applies not only to the registered path but all child paths recursively. This watcher
* is triggered for both data and child events. To remove the watcher, use
* <tt>removeWatches()</tt> with <tt>WatcherType.Any</tt>
* </p>
*
* <p>
* The watcher behaves as if you placed an exists() watch and
* a getData() watch on the ZNode at the given path <strong>and</strong> any ZNodes that are children
* of the given path including children added later.
* </p>
*
* <p>
* NOTE: when there are active recursive watches there is a small performance decrease as all segments
* of ZNode paths must be checked for watch triggering.
* </p>
*/
PERSISTENT_RECURSIVE(ZooDefs.AddWatchModes.persistentRecursive)
;

public int getMode() {
return mode;
}

private final int mode;

AddWatchMode(int mode) {
this.mode = mode;
}
}

0 comments on commit 31805e7

Please sign in to comment.