Author: bobby
Date: Thu Mar 17 02:16:31 2016
New Revision: 1735361

URL: http://svn.apache.org/viewvc?rev=1735361&view=rev
Log:
Added in the Security and REST API Documentation

Added:
    storm/branches/bobby-versioned-site/releases/0.10.0/SECURITY.md
    storm/branches/bobby-versioned-site/releases/0.10.0/STORM-UI-REST-API.md
Modified:
    storm/branches/bobby-versioned-site/releases/0.10.0/index.md

Added: storm/branches/bobby-versioned-site/releases/0.10.0/SECURITY.md
URL: 
http://svn.apache.org/viewvc/storm/branches/bobby-versioned-site/releases/0.10.0/SECURITY.md?rev=1735361&view=auto
==============================================================================
--- storm/branches/bobby-versioned-site/releases/0.10.0/SECURITY.md (added)
+++ storm/branches/bobby-versioned-site/releases/0.10.0/SECURITY.md Thu Mar 17 
02:16:31 2016
@@ -0,0 +1,479 @@
+---
+title: Running Apache Storm Securely
+layout: documentation
+documentation: true
+version: v0.10.0
+---
+
+# Running Apache Storm Securely
+
+Apache Storm offers a range of configuration options when trying to secure
+your cluster.  By default all authentication and authorization is disabled but 
+can be turned on as needed.
+
+## Firewall/OS level Security
+
+You can still have a secure storm cluster without turning on formal
+Authentication and Authorization. But to do so usually requires 
+configuring your Operating System to restrict the operations that can be done.
+This is generally a good idea even if you plan on running your cluster with 
Auth.
+
+The exact detail of how to setup these precautions varies a lot and is beyond
+the scope of this document.
+
+It is generally a good idea to enable a firewall and restrict incoming network
+connections to only those originating from the cluster itself and from trusted
+hosts and services, a complete list of ports storm uses are below. 
+
+If the data your cluster is processing is sensitive it might be best to setup
+IPsec to encrypt all traffic being sent between the hosts in the cluster.
+
+### Ports
+
+| Default Port | Storm Config | Client Hosts/Processes | Server |
+|--------------|--------------|------------------------|--------|
+| 2181 | `storm.zookeeper.port` | Nimbus, Supervisors, and Worker processes | 
Zookeeper |
+| 6627 | `nimbus.thrift.port` | Storm clients, Supervisors, and UI | Nimbus |
+| 8080 | `ui.port` | Client Web Browsers | UI |
+| 8000 | `logviewer.port` | Client Web Browsers | Logviewer |
+| 3772 | `drpc.port` | External DRPC Clients | DRPC |
+| 3773 | `drpc.invocations.port` | Worker Processes | DRPC |
+| 3774 | `drpc.http.port` | External HTTP DRPC Clients | DRPC |
+| 670{0,1,2,3} | `supervisor.slots.ports` | Worker Processes | Worker 
Processes |
+
+
+### UI/Logviewer
+
+The UI and logviewer processes provide a way to not only see what a cluster is
+doing, but also manipulate running topologies.  In general these processes 
should
+not be exposed except to users of the cluster.
+
+Some form of Authentication is typically required, with using java servlet 
filters 
+
+```yaml
+ui.filter: "filter.class"
+ui.filter.params: "param1":"value1"
+```
+or by restricting the UI/log viewers ports to only accept connections from 
local
+hosts, and then front them with another web server, like Apache httpd, that can
+authenticate/authorize incoming connections and
+proxy the connection to the storm process.  To make this work the ui process 
must have
+logviewer.port set to the port of the proxy in its storm.yaml, while the 
logviewers
+must have it set to the actual port that they are going to bind to.
+
+The servlet filters are preferred because it allows individual topologies to
+specificy who is and who is not allowed to access the pages associated with
+them.  
+
+Storm UI can be configured to use AuthenticationFilter from hadoop-auth.
+```yaml
+ui.filter: 
"org.apache.hadoop.security.authentication.server.AuthenticationFilter"
+ui.filter.params:
+   "type": "kerberos"
+   "kerberos.principal": "HTTP/nimbus.witzend.com"
+   "kerberos.keytab": "/vagrant/keytabs/http.keytab"
+   "kerberos.name.rules": 
"RULE:[2:$1@$0]([jt]t@.*EXAMPLE.COM)s/.*/$MAPRED_USER/ 
RULE:[2:$1@$0]([nd]n@.*EXAMPLE.COM)s/.*/$HDFS_USER/DEFAULT"
+```
+make sure to create a principal 'HTTP/{hostname}' (here hostname should be the 
one where UI daemon runs
+
+Once configured users needs to do kinit before accessing UI.
+Ex:
+curl  -i --negotiate -u:anyUser  -b ~/cookiejar.txt -c ~/cookiejar.txt  
http://storm-ui-hostname:8080/api/v1/cluster/summary
+
+1. Firefox: Goto about:config and search for 
network.negotiate-auth.trusted-uris double-click to  add value 
"http://storm-ui-hostname:8080";
+2. Google-chrome:  start from command line with: google-chrome 
--auth-server-whitelist="*storm-ui-hostname" 
--auth-negotiate-delegate-whitelist="*storm-ui-hostname"   
+3. IE:  Configure trusted websites to include "storm-ui-hostname" and allow 
negotiation for that website 
+
+**Caution**: In AD MIT Keberos setup the key size is bigger than the default 
UI jetty server request header size. Make sure you set ui.header.buffer.bytes 
to 65536 in storm.yaml. More details are on 
[STORM-633](https://issues.apache.org/jira/browse/STORM-633)
+
+
+## UI / DRPC SSL 
+
+Both UI and DRPC allows users to configure ssl .
+
+### UI
+
+For UI users needs to set following config in storm.yaml. Generating keystores 
with proper keys and certs should be taken care by the user before this step.
+
+1. ui.https.port 
+2. ui.https.keystore.type (example "jks")
+3. ui.https.keystore.path (example "/etc/ssl/storm_keystore.jks")
+4. ui.https.keystore.password (keystore password)
+5. ui.https.key.password (private key password)
+
+optional config 
+6. ui.https.truststore.path (example "/etc/ssl/storm_truststore.jks")
+7. ui.https.truststore.password (truststore password)
+8. ui.https.truststore.type (example "jks")
+
+If users want to setup 2-way auth
+9. ui.https.want.client.auth (If this set to true server requests for client 
certifcate authentication, but keeps the connection if no authentication 
provided)
+10. ui.https.need.client.auth (If this set to true server requires client to 
provide authentication)
+
+
+
+
+### DRPC
+similarly to UI , users need to configure following for DRPC
+
+1. drpc.https.port 
+2. drpc.https.keystore.type (example "jks")
+3. drpc.https.keystore.path (example "/etc/ssl/storm_keystore.jks")
+4. drpc.https.keystore.password (keystore password)
+5. drpc.https.key.password (private key password)
+
+optional config 
+6. drpc.https.truststore.path (example "/etc/ssl/storm_truststore.jks")
+7. drpc.https.truststore.password (truststore password)
+8. drpc.https.truststore.type (example "jks")
+
+If users want to setup 2-way auth
+9. drpc.https.want.client.auth (If this set to true server requests for client 
certifcate authentication, but keeps the connection if no authentication 
provided)
+10. drpc.https.need.client.auth (If this set to true server requires client to 
provide authentication)
+
+
+
+
+
+## Authentication (Kerberos)
+
+Storm offers pluggable authentication support through thrift and SASL.  This
+example only goes off of Kerberos as it is a common setup for most big data
+projects.
+
+Setting up a KDC and configuring kerberos on each node is beyond the scope of
+this document and it is assumed that you have done that already.
+
+### Create Headless Principals and keytabs
+
+Each Zookeeper Server, Nimbus, and DRPC server will need a service principal, 
which, by convention, includes the FQDN of the host it will run on.  Be aware 
that the zookeeper user *MUST* be zookeeper.  
+The supervisors and UI also need a principal to run as, but because they are 
outgoing connections they do not need to be service principals. 
+The following is an example of how to setup kerberos principals, but the
+details may vary depending on your KDC and OS.
+
+
+```bash
+# Zookeeper (Will need one of these for each box in teh Zk ensamble)
+sudo kadmin.local -q 'addprinc zookeeper/[email protected]'
+sudo kadmin.local -q "ktadd -k /tmp/zk.keytab  
zookeeper/[email protected]"
+# Nimbus and DRPC
+sudo kadmin.local -q 'addprinc storm/[email protected]'
+sudo kadmin.local -q "ktadd -k /tmp/storm.keytab 
storm/[email protected]"
+# All UI logviewer and Supervisors
+sudo kadmin.local -q 'addprinc [email protected]'
+sudo kadmin.local -q "ktadd -k /tmp/storm.keytab [email protected]"
+```
+
+be sure to distribute the keytab(s) to the appropriate boxes and set the FS 
permissions so that only the headless user running ZK, or storm has access to 
them.
+
+#### Storm Kerberos Configuration
+
+Both storm and Zookeeper use jaas configuration files to log the user in.
+Each jaas file may have multiple sections for different interfaces being used.
+
+To enable Kerberos authentication in storm you need to set the following 
storm.yaml configs
+```yaml
+storm.thrift.transport: 
"backtype.storm.security.auth.kerberos.KerberosSaslTransportPlugin"
+java.security.auth.login.config: "/path/to/jaas.conf"
+```
+
+Nimbus and the supervisor processes will also connect to ZooKeeper(ZK) and we 
want to configure them to use Kerberos for authentication with ZK. To do this 
append 
+```
+-Djava.security.auth.login.config=/path/to/jaas.conf
+```
+
+to the childopts of nimbus, ui, and supervisor.  Here is an example given the 
default childopts settings at the time of writing:
+
+```yaml
+nimbus.childopts: "-Xmx1024m 
-Djava.security.auth.login.config=/path/to/jaas.conf"
+ui.childopts: "-Xmx768m -Djava.security.auth.login.config=/path/to/jaas.conf"
+supervisor.childopts: "-Xmx256m 
-Djava.security.auth.login.config=/path/to/jaas.conf"
+```
+
+The jaas.conf file should look something like the following for the storm 
nodes.
+The StormServer section is used by nimbus and the DRPC Nodes.  It does not 
need to be included on supervisor nodes.
+The StormClient section is used by all storm clients that want to talk to 
nimbus, including the ui, logviewer, and supervisor.  We will use this section 
on the gateways as well but the structure of that will be a bit different.
+The Client section is used by processes wanting to talk to zookeeper and 
really only needs to be included with nimbus and the supervisors.
+The Server section is used by the zookeeper servers.
+Having unused sections in the jaas is not a problem.
+
+```
+StormServer {
+   com.sun.security.auth.module.Krb5LoginModule required
+   useKeyTab=true
+   keyTab="$keytab"
+   storeKey=true
+   useTicketCache=false
+   principal="$principal";
+};
+StormClient {
+   com.sun.security.auth.module.Krb5LoginModule required
+   useKeyTab=true
+   keyTab="$keytab"
+   storeKey=true
+   useTicketCache=false
+   serviceName="$nimbus_user"
+   principal="$principal";
+};
+Client {
+   com.sun.security.auth.module.Krb5LoginModule required
+   useKeyTab=true
+   keyTab="$keytab"
+   storeKey=true
+   useTicketCache=false
+   serviceName="zookeeper"
+   principal="$principal";
+};
+Server {
+   com.sun.security.auth.module.Krb5LoginModule required
+   useKeyTab=true
+   keyTab="$keytab"
+   storeKey=true
+   useTicketCache=false
+   principal="$principal";
+};
+```
+
+The following is an example based off of the keytabs generated
+```
+StormServer {
+   com.sun.security.auth.module.Krb5LoginModule required
+   useKeyTab=true
+   keyTab="/keytabs/storm.keytab"
+   storeKey=true
+   useTicketCache=false
+   principal="storm/[email protected]";
+};
+StormClient {
+   com.sun.security.auth.module.Krb5LoginModule required
+   useKeyTab=true
+   keyTab="/keytabs/storm.keytab"
+   storeKey=true
+   useTicketCache=false
+   serviceName="storm"
+   principal="[email protected]";
+};
+Client {
+   com.sun.security.auth.module.Krb5LoginModule required
+   useKeyTab=true
+   keyTab="/keytabs/storm.keytab"
+   storeKey=true
+   useTicketCache=false
+   serviceName="zookeeper"
+   principal="[email protected]";
+};
+Server {
+   com.sun.security.auth.module.Krb5LoginModule required
+   useKeyTab=true
+   keyTab="/keytabs/zk.keytab"
+   storeKey=true
+   useTicketCache=false
+   serviceName="zookeeper"
+   principal="zookeeper/[email protected]";
+};
+```
+
+Nimbus also will translate the principal into a local user name, so that other 
services can use this name.  To configure this for Kerberos authentication set
+
+```
+storm.principal.tolocal: 
"backtype.storm.security.auth.KerberosPrincipalToLocal"
+```
+
+This only needs to be done on nimbus, but it will not hurt on any node.
+We also need to inform the topology who the supervisor daemon and the nimbus 
daemon are running as from a ZooKeeper perspective.
+
+```
+storm.zookeeper.superACL: "sasl:${nimbus-user}"
+```
+
+Here *nimbus-user* is the Kerberos user that nimbus uses to authenticate with 
ZooKeeper.  If ZooKeeeper is stripping host and realm then this needs to have 
host and realm stripped too.
+
+#### ZooKeeper Ensemble
+
+Complete details of how to setup a secure ZK are beyond the scope of this 
document.  But in general you want to enable SASL authentication on each 
server, and optionally strip off host and realm
+
+```
+authProvider.1 = org.apache.zookeeper.server.auth.SASLAuthenticationProvider
+kerberos.removeHostFromPrincipal = true
+kerberos.removeRealmFromPrincipal = true
+```
+
+And you want to include the jaas.conf on the command line when launching the 
server so it can use it can find the keytab.
+```
+-Djava.security.auth.login.config=/jaas/zk_jaas.conf
+```
+
+#### Gateways
+
+Ideally the end user will only need to run kinit before interacting with 
storm.  To make this happen seamlessly we need the default jaas.conf on the 
gateways to be something like
+
+```
+StormClient {
+   com.sun.security.auth.module.Krb5LoginModule required
+   doNotPrompt=false
+   useTicketCache=true
+   serviceName="$nimbus_user";
+};
+```
+
+The end user can override this if they have a headless user that has a keytab.
+
+### Authorization Setup
+
+*Authentication* does the job of verifying who the user is, but we also need 
*authorization* to do the job of enforcing what each user can do.
+
+The preferred authorization plug-in for nimbus is The *SimpleACLAuthorizer*.  
To use the *SimpleACLAuthorizer*, set the following:
+
+```yaml
+nimbus.authorizer: 
"backtype.storm.security.auth.authorizer.SimpleACLAuthorizer"
+```
+
+DRPC has a separate authorizer configuration for it.  Do not use 
SimpleACLAuthorizer for DRPC.
+
+The *SimpleACLAuthorizer* plug-in needs to know who the supervisor users are, 
and it needs to know about all of the administrator users, including the user 
running the ui daemon. 
+
+These are set through *nimbus.supervisor.users* and *nimbus.admins* 
respectively.  Each can either be a full Kerberos principal name, or the name 
of the user with host and realm stripped off.
+
+The Log servers have their own authorization configurations.  These are set 
through *logs.users* and *logs.groups*.  These should be set to the admin users 
or groups for all of the nodes in the cluster.  
+
+When a topology is submitted, the submitting user can specify users in this 
list as well.  The users and groups specified-in addition to the users in the 
cluster-wide setting-will be granted access to the submitted topology's worker 
logs in the logviewers.
+
+### Supervisors headless User and group Setup
+
+To ensure isolation of users in multi-tenancy, there is need to run 
supervisors and headless user and group unique to execution on the supervisor 
nodes.  To enable this follow below steps.
+1. Add headlessuser to all supervisor hosts.
+2. Create unique group and make it the primary group for the headless user on 
the supervisor nodes.
+3. The set following properties on storm for these supervisor nodes.
+
+### Multi-tenant Scheduler
+
+To support multi-tenancy better we have written a new scheduler.  To enable 
this scheduler set.
+```yaml
+storm.scheduler: "backtype.storm.scheduler.multitenant.MultitenantScheduler"
+```
+Be aware that many of the features of this scheduler rely on storm 
authentication.  Without them the scheduler will not know what the user is and 
will not isolate topologies properly.
+
+The goal of the multi-tenant scheduler is to provide a way to isolate 
topologies from one another, but to also limit the resources that an individual 
user can have in the cluster.
+
+The scheduler currently has one config that can be set either through 
=storm.yaml= or through a separate config file called 
=multitenant-scheduler.yaml= that should be placed in the same directory as 
=storm.yaml=.  It is preferable to use =multitenant-scheduler.yaml= because it 
can be updated without needing to restart nimbus.
+
+There is currently only one config in =multitenant-scheduler.yaml=, 
=multitenant.scheduler.user.pools= is a map from the user name, to the maximum 
number of nodes that user is guaranteed to be able to use for their topologies.
+
+For example:
+
+```yaml
+multitenant.scheduler.user.pools: 
+    "evans": 10
+    "derek": 10
+```
+
+### Run worker processes as user who submitted the topology
+By default storm runs workers as the user that is running the supervisor.  
This is not ideal for security.  To make storm run the topologies as the user 
that launched them set.
+
+```yaml
+supervisor.run.worker.as.user: true
+```
+
+There are several files that go along with this that are needed to be 
configured properly to make storm secure.
+
+The worker-launcher executable is a special program that allows the supervisor 
to launch workers as different users.  For this to work it needs to be owned by 
root, but with the group set to be a group that only teh supervisor headless 
user is a part of.
+It also needs to have 6550 permissions.
+There is also a worker-launcher.cfg file, usually located under /etc/ that 
should look something like the following
+
+```
+storm.worker-launcher.group=$(worker_launcher_group)
+min.user.id=$(min_user_id)
+```
+where worker_launcher_group is the same group the supervisor is a part of, and 
min.user.id is set to the first real user id on the system.
+This config file also needs to be owned by root and not have world or group 
write permissions.
+
+### Impersonating a user
+A storm client may submit requests on behalf of another user. For example, if 
a `userX` submits an oozie workflow and as part of workflow execution if user 
`oozie` wants to submit a topology on behalf of `userX`
+it can do so by leveraging the impersonation feature.In order to submit 
topology as some other user , you can use `StormSubmitter.submitTopologyAs` 
API. Alternatively you can use `NimbusClient.getConfiguredClientAs` 
+to get a nimbus client as some other user and perform any nimbus action(i.e. 
kill/rebalance/activate/deactivate) using this client. 
+
+To ensure only authorized users can perform impersonation you should start 
nimbus with `nimbus.impersonation.authorizer` set to 
`backtype.storm.security.auth.authorizer.ImpersonationAuthorizer`. 
+The `ImpersonationAuthorizer` uses `nimbus.impersonation.acl` as the acl to 
authorize users. Following is a sample nimbus config for supporting 
impersonation:
+
+```yaml
+nimbus.impersonation.authorizer: 
backtype.storm.security.auth.authorizer.ImpersonationAuthorizer
+nimbus.impersonation.acl:
+    impersonating_user1:
+        hosts:
+            [comma separated list of hosts from which impersonating_user1 is 
allowed to impersonate other users]
+        groups:
+            [comma separated list of groups whose users impersonating_user1 is 
allowed to impersonate]
+    impersonating_user2:
+        hosts:
+            [comma separated list of hosts from which impersonating_user2 is 
allowed to impersonate other users]
+        groups:
+            [comma separated list of groups whose users impersonating_user2 is 
allowed to impersonate]
+```
+
+To support the oozie use case following config can be supplied:
+```yaml
+nimbus.impersonation.acl:
+    oozie:
+        hosts:
+            [oozie-host1, oozie-host2, 127.0.0.1]
+        groups:
+            [some-group-that-userX-is-part-of]
+```
+
+### Automatic Credentials Push and Renewal
+Individual topologies have the ability to push credentials (tickets and 
tokens) to workers so that they can access secure services.  Exposing this to 
all of the users can be a pain for them.
+To hide this from them in the common case plugins can be used to populate the 
credentials, unpack them on the other side into a java Subject, and also allow 
Nimbus to renew the credentials if needed.
+These are controlled by the following configs. topology.auto-credentials is a 
list of java plugins, all of which must implement IAutoCredentials interface, 
that populate the credentials on gateway 
+and unpack them on the worker side. On a kerberos secure cluster they should 
be set by default to point to backtype.storm.security.auth.kerberos.AutoTGT.  
+nimbus.credential.renewers.classes should also be set to this value so that 
nimbus can periodically renew the TGT on behalf of the user.
+
+nimbus.credential.renewers.freq.secs controls how often the renewer will poll 
to see if anything needs to be renewed, but the default should be fine.
+
+In addition Nimbus itself can be used to get credentials on behalf of the user 
submitting topologies. This can be configures using 
nimbus.autocredential.plugins.classes which is a list 
+of fully qualified class names ,all of which must implement 
INimbusCredentialPlugin.  Nimbus will invoke the populateCredentials method of 
all the configured implementation as part of topology
+submission. You should use this config with topology.auto-credentials and 
nimbus.credential.renewers.classes so the credentials can be populated on 
worker side and nimbus can automatically renew
+them. Currently there are 2 examples of using this config, AutoHDFS and 
AutoHBase which auto populates hdfs and hbase delegation tokens for topology 
submitter so they don't have to distribute keytabs
+on all possible worker hosts.
+
+### Limits
+By default storm allows any sized topology to be submitted. But ZK and others 
have limitations on how big a topology can actually be.  The following configs 
allow you to limit the maximum size a topology can be.
+
+| YAML Setting | Description |
+|------------|----------------------|
+| nimbus.slots.perTopology | The maximum number of slots/workers a topology 
can use. |
+| nimbus.executors.perTopology | The maximum number of executors/threads a 
topology can use. |
+
+### Log Cleanup
+The Logviewer daemon now is also responsible for cleaning up old log files for 
dead topologies.
+
+| YAML Setting | Description |
+|--------------|-------------------------------------|
+| logviewer.cleanup.age.mins | How old (by last modification time) must a 
worker's log be before that log is considered for clean-up. (Living workers' 
logs are never cleaned up by the logviewer: Their logs are rolled via logback.) 
|
+| logviewer.cleanup.interval.secs | Interval of time in seconds that the 
logviewer cleans up worker logs. |
+
+
+### Allowing specific users or groups to access storm
+
+ With SimpleACLAuthorizer any user with valid kerberos ticket can deploy a 
topology or do further operations such as activate, deactivate , access cluster 
information.
+ One can restrict this access by specifying nimbus.users or nimbus.groups. If 
nimbus.users configured only the users in the list can deploy a topology or 
access cluster.
+ Similarly nimbus.groups restrict storm cluster access to users who belong to 
those groups.
+ 
+ To configure specify the following config in storm.yaml
+
+```yaml
+nimbus.users: 
+   - "testuser"
+```
+
+or 
+
+```yaml
+nimbus.groups: 
+   - "storm"
+```
+ 
+
+### DRPC
+Hopefully more on this soon
+
+

Added: storm/branches/bobby-versioned-site/releases/0.10.0/STORM-UI-REST-API.md
URL: 
http://svn.apache.org/viewvc/storm/branches/bobby-versioned-site/releases/0.10.0/STORM-UI-REST-API.md?rev=1735361&view=auto
==============================================================================
--- storm/branches/bobby-versioned-site/releases/0.10.0/STORM-UI-REST-API.md 
(added)
+++ storm/branches/bobby-versioned-site/releases/0.10.0/STORM-UI-REST-API.md 
Thu Mar 17 02:16:31 2016
@@ -0,0 +1,679 @@
+---
+title: Storm REST API
+layout: documentation
+documentation: true
+version: v0.10.0
+---
+
+# Storm UI REST API
+
+The Storm UI daemon provides a REST API that allows you to interact with a 
Storm cluster, which includes retrieving
+metrics data and configuration information as well as management operations 
such as starting or stopping topologies.
+
+
+# Data format
+
+The REST API returns JSON responses and supports JSONP.
+Clients can pass a callback query parameter to wrap JSON in the callback 
function.
+
+
+# Using the UI REST API
+
+_Note: It is recommended to ignore undocumented elements in the JSON response 
because future versions of Storm may not_
+_support those elements anymore._
+
+
+## REST API Base URL
+
+The REST API is part of the UI daemon of Storm (started by `storm ui`) and 
thus runs on the same host and port as the
+Storm UI (the UI daemon is often run on the same host as the Nimbus daemon).  
The port is configured by `ui.port`,
+which is set to `8080` by default (see [defaults.yaml](conf/defaults.yaml)).
+
+The API base URL would thus be:
+
+    http://<ui-host>:<ui-port>/api/v1/...
+
+You can use a tool such as `curl` to talk to the REST API:
+
+    # Request the cluster configuration.
+    # Note: We assume ui.port is configured to the default value of 8080.
+    $ curl http://<ui-host>:8080/api/v1/cluster/configuration
+
+##Impersonating a user in secure environment
+In a secure environment an authenticated user can impersonate another user. To 
impersonate a user the caller must pass
+`doAsUser` param or header with value set to the user that the request needs 
to be performed as. Please see SECURITY.MD
+to learn more about how to setup impersonation ACLs and authorization. The 
rest API uses the same configs and acls that
+are used by nimbus.
+
+Examples:
+
+```no-highlight
+ 1. 
http://ui-daemon-host-name:8080/api/v1/topology/wordcount-1-1425844354\?doAsUser=testUSer1
+ 2. curl 
'http://localhost:8080/api/v1/topology/wordcount-1-1425844354/activate' -X POST 
-H 'doAsUser:testUSer1'
+```
+
+## GET Operations
+
+### /api/v1/cluster/configuration (GET)
+
+Returns the cluster configuration.
+
+Sample response (does not include all the data fields):
+
+```json
+  {
+    "dev.zookeeper.path": "/tmp/dev-storm-zookeeper",
+    "topology.tick.tuple.freq.secs": null,
+    "topology.builtin.metrics.bucket.size.secs": 60,
+    "topology.fall.back.on.java.serialization": true,
+    "topology.max.error.report.per.interval": 5,
+    "zmq.linger.millis": 5000,
+    "topology.skip.missing.kryo.registrations": false,
+    "storm.messaging.netty.client_worker_threads": 1,
+    "ui.childopts": "-Xmx768m",
+    "storm.zookeeper.session.timeout": 20000,
+    "nimbus.reassign": true,
+    "topology.trident.batch.emit.interval.millis": 500,
+    "storm.messaging.netty.flush.check.interval.ms": 10,
+    "nimbus.monitor.freq.secs": 10,
+    "logviewer.childopts": "-Xmx128m",
+    "java.library.path": "/usr/local/lib:/opt/local/lib:/usr/lib",
+    "topology.executor.send.buffer.size": 1024,
+    }
+```
+
+### /api/v1/cluster/summary (GET)
+
+Returns cluster summary information such as nimbus uptime or number of 
supervisors.
+
+Response fields:
+
+|Field  |Value|Description
+|---   |---    |---
+|stormVersion|String| Storm version|
+|nimbusUptime|String| Shows how long the cluster is running|
+|supervisors|Integer| Number of supervisors running|
+|topologies| Integer| Number of topologies running| 
+|slotsTotal| Integer|Total number of available worker slots|
+|slotsUsed| Integer| Number of worker slots used|
+|slotsFree| Integer |Number of worker slots available|
+|executorsTotal| Integer |Total number of executors|
+|tasksTotal| Integer |Total tasks|
+
+Sample response:
+
+```json
+   {
+    "stormVersion": "0.9.2-incubating-SNAPSHOT",
+    "nimbusUptime": "3m 53s",
+    "supervisors": 1,
+    "slotsTotal": 4,
+    "slotsUsed": 3,
+    "slotsFree": 1,
+    "executorsTotal": 28,
+    "tasksTotal": 28
+    }
+```
+
+### /api/v1/supervisor/summary (GET)
+
+Returns summary information for all supervisors.
+
+Response fields:
+
+|Field  |Value|Description|
+|---   |---    |---
+|id| String | Supervisor's id|
+|host| String| Supervisor's host name|
+|uptime| String| Shows how long the supervisor is running|
+|slotsTotal| Integer| Total number of available worker slots for this 
supervisor|
+|slotsUsed| Integer| Number of worker slots used on this supervisor|
+
+Sample response:
+
+```json
+{
+    "supervisors": [
+        {
+            "id": "0b879808-2a26-442b-8f7d-23101e0c3696",
+            "host": "10.11.1.7",
+            "uptime": "5m 58s",
+            "slotsTotal": 4,
+            "slotsUsed": 3
+        }
+    ]
+}
+```
+
+### /api/v1/topology/summary (GET)
+
+Returns summary information for all topologies.
+
+Response fields:
+
+|Field  |Value | Description|
+|---   |---    |---
+|id| String| Topology Id|
+|name| String| Topology Name|
+|status| String| Topology Status|
+|uptime| String|  Shows how long the topology is running|
+|tasksTotal| Integer |Total number of tasks for this topology|
+|workersTotal| Integer |Number of workers used for this topology|
+|executorsTotal| Integer |Number of executors used for this topology|
+
+Sample response:
+
+```json
+{
+    "topologies": [
+        {
+            "id": "WordCount3-1-1402960825",
+            "name": "WordCount3",
+            "status": "ACTIVE",
+            "uptime": "6m 5s",
+            "tasksTotal": 28,
+            "workersTotal": 3,
+            "executorsTotal": 28
+        }
+    ]
+}
+```
+
+### /api/v1/topology/:id (GET)
+
+Returns topology information and statistics.  Substitute id with topology id.
+
+Request parameters:
+
+|Parameter |Value   |Description  |
+|----------|--------|-------------|
+|id       |String (required)| Topology Id  |
+|window    |String. Default value :all-time| Window duration for metrics in 
seconds|
+|sys       |String. Values 1 or 0. Default value 0| Controls including sys 
stats part of the response|
+
+
+Response fields:
+
+|Field  |Value |Description|
+|---   |---    |---
+|id| String| Topology Id|
+|name| String |Topology Name|
+|uptime| String |How long the topology has been running|
+|status| String |Current status of the topology, e.g. "ACTIVE"|
+|tasksTotal| Integer |Total number of tasks for this topology|
+|workersTotal| Integer |Number of workers used for this topology|
+|executorsTotal| Integer |Number of executors used for this topology|
+|msgTimeout| Integer | Number of seconds a tuple has before the spout 
considers it failed |
+|windowHint| String | window param value in "hh mm ss" format. Default value 
is "All Time"|
+|topologyStats| Array | Array of all the topology related stats per time 
window|
+|topologyStats.windowPretty| String |Duration passed in HH:MM:SS format|
+|topologyStats.window| String |User requested time window for metrics|
+|topologyStats.emitted| Long |Number of messages emitted in given window|
+|topologyStats.trasferred| Long |Number messages transferred in given window|
+|topologyStats.completeLatency| String (double value returned in String 
format) |Total latency for processing the message|
+|topologyStats.acked| Long |Number of messages acked in given window|
+|topologyStats.failed| Long |Number of messages failed in given window|
+|spouts| Array | Array of all the spout components in the topology|
+|spouts.spoutId| String |Spout id|
+|spouts.executors| Integer |Number of executors for the spout|
+|spouts.emitted| Long |Number of messages emitted in given window |
+|spouts.completeLatency| String (double value returned in String format) 
|Total latency for processing the message|
+|spouts.transferred| Long |Total number of messages  transferred in given 
window|
+|spouts.tasks| Integer |Total number of tasks for the spout|
+|spouts.lastError| String |Shows the last error happened in a spout|
+|spouts.errorLapsedSecs| Integer | Number of seconds elapsed since that last 
error happened in a spout|
+|spouts.errorWorkerLogLink| String | Link to the worker log that reported the 
exception |
+|spouts.acked| Long |Number of messages acked|
+|spouts.failed| Long |Number of messages failed|
+|bolts| Array | Array of bolt components in the topology|
+|bolts.boltId| String |Bolt id|
+|bolts.capacity| String (double value returned in String format) |This value 
indicates number of messages executed * average execute latency / time window|
+|bolts.processLatency| String (double value returned in String format)  
|Average time of the bolt to ack a message after it was received|
+|bolts.executeLatency| String (double value returned in String format) 
|Average time to run the execute method of the bolt|
+|bolts.executors| Integer |Number of executor tasks in the bolt component|
+|bolts.tasks| Integer |Number of instances of bolt|
+|bolts.acked| Long |Number of tuples acked by the bolt|
+|bolts.failed| Long |Number of tuples failed by the bolt|
+|bolts.lastError| String |Shows the last error occurred in the bolt|
+|bolts.errorLapsedSecs| Integer |Number of seconds elapsed since that last 
error happened in a bolt|
+|bolts.errorWorkerLogLink| String | Link to the worker log that reported the 
exception |
+|bolts.emitted| Long |Number of tuples emitted|
+
+Examples:
+
+```no-highlight
+ 1. http://ui-daemon-host-name:8080/api/v1/topology/WordCount3-1-1402960825
+ 2. 
http://ui-daemon-host-name:8080/api/v1/topology/WordCount3-1-1402960825?sys=1
+ 3. 
http://ui-daemon-host-name:8080/api/v1/topology/WordCount3-1-1402960825?window=600
+```
+
+Sample response:
+
+```json
+ {
+    "name": "WordCount3",
+    "id": "WordCount3-1-1402960825",
+    "workersTotal": 3,
+    "window": "600",
+    "status": "ACTIVE",
+    "tasksTotal": 28,
+    "executorsTotal": 28,
+    "uptime": "29m 19s",
+    "msgTimeout": 30,
+    "windowHint": "10m 0s",
+    "topologyStats": [
+        {
+            "windowPretty": "10m 0s",
+            "window": "600",
+            "emitted": 397960,
+            "transferred": 213380,
+            "completeLatency": "0.000",
+            "acked": 213460,
+            "failed": 0
+        },
+        {
+            "windowPretty": "3h 0m 0s",
+            "window": "10800",
+            "emitted": 1190260,
+            "transferred": 638260,
+            "completeLatency": "0.000",
+            "acked": 638280,
+            "failed": 0
+        },
+        {
+            "windowPretty": "1d 0h 0m 0s",
+            "window": "86400",
+            "emitted": 1190260,
+            "transferred": 638260,
+            "completeLatency": "0.000",
+            "acked": 638280,
+            "failed": 0
+        },
+        {
+            "windowPretty": "All time",
+            "window": ":all-time",
+            "emitted": 1190260,
+            "transferred": 638260,
+            "completeLatency": "0.000",
+            "acked": 638280,
+            "failed": 0
+        }
+    ],
+    "spouts": [
+        {
+            "executors": 5,
+            "emitted": 28880,
+            "completeLatency": "0.000",
+            "transferred": 28880,
+            "acked": 0,
+            "spoutId": "spout",
+            "tasks": 5,
+            "lastError": "",
+            "errorLapsedSecs": null,
+            "failed": 0
+        }
+    ],
+        "bolts": [
+        {
+            "executors": 12,
+            "emitted": 184580,
+            "transferred": 0,
+            "acked": 184640,
+            "executeLatency": "0.048",
+            "tasks": 12,
+            "executed": 184620,
+            "processLatency": "0.043",
+            "boltId": "count",
+            "lastError": "",
+            "errorLapsedSecs": null,
+            "capacity": "0.003",
+            "failed": 0
+        },
+        {
+            "executors": 8,
+            "emitted": 184500,
+            "transferred": 184500,
+            "acked": 28820,
+            "executeLatency": "0.024",
+            "tasks": 8,
+            "executed": 28780,
+            "processLatency": "2.112",
+            "boltId": "split",
+            "lastError": "",
+            "errorLapsedSecs": null,
+            "capacity": "0.000",
+            "failed": 0
+        }
+    ],
+    "configuration": {
+        "storm.id": "WordCount3-1-1402960825",
+        "dev.zookeeper.path": "/tmp/dev-storm-zookeeper",
+        "topology.tick.tuple.freq.secs": null,
+        "topology.builtin.metrics.bucket.size.secs": 60,
+        "topology.fall.back.on.java.serialization": true,
+        "topology.max.error.report.per.interval": 5,
+        "zmq.linger.millis": 5000,
+        "topology.skip.missing.kryo.registrations": false,
+        "storm.messaging.netty.client_worker_threads": 1,
+        "ui.childopts": "-Xmx768m",
+        "storm.zookeeper.session.timeout": 20000,
+        "nimbus.reassign": true,
+        "topology.trident.batch.emit.interval.millis": 500,
+        "storm.messaging.netty.flush.check.interval.ms": 10,
+        "nimbus.monitor.freq.secs": 10,
+        "logviewer.childopts": "-Xmx128m",
+        "java.library.path": "/usr/local/lib:/opt/local/lib:/usr/lib",
+        "topology.executor.send.buffer.size": 1024,
+        "storm.local.dir": "storm-local",
+        "storm.messaging.netty.buffer_size": 5242880,
+        "supervisor.worker.start.timeout.secs": 120,
+        "topology.enable.message.timeouts": true,
+        "nimbus.cleanup.inbox.freq.secs": 600,
+        "nimbus.inbox.jar.expiration.secs": 3600,
+        "drpc.worker.threads": 64,
+        "topology.worker.shared.thread.pool.size": 4,
+        "nimbus.host": "hw10843.local",
+        "storm.messaging.netty.min_wait_ms": 100,
+        "storm.zookeeper.port": 2181,
+        "transactional.zookeeper.port": null,
+        "topology.executor.receive.buffer.size": 1024,
+        "transactional.zookeeper.servers": null,
+        "storm.zookeeper.root": "/storm",
+        "storm.zookeeper.retry.intervalceiling.millis": 30000,
+        "supervisor.enable": true,
+        "storm.messaging.netty.server_worker_threads": 1
+    }
+}
+```
+
+
+### /api/v1/topology/:id/component/:component (GET)
+
+Returns detailed metrics and executor information
+
+|Parameter |Value   |Description  |
+|----------|--------|-------------|
+|id       |String (required)| Topology Id  |
+|component |String (required)| Component Id |
+|window    |String. Default value :all-time| window duration for metrics in 
seconds|
+|sys       |String. Values 1 or 0. Default value 0| controls including sys 
stats part of the response|
+
+Response fields:
+
+|Field  |Value |Description|
+|---   |---    |---
+|id   | String | Component id|
+|name | String | Topology name|
+|componentType | String | component type: SPOUT or BOLT|
+|windowHint| String | window param value in "hh mm ss" format. Default value 
is "All Time"|
+|executors| Integer |Number of executor tasks in the component|
+|componentErrors| Array of Errors | List of component errors|
+|componentErrors.time| Long | Timestamp when the exception occurred |
+|componentErrors.errorHost| String | host name for the error|
+|componentErrors.errorPort| String | port for the error|
+|componentErrors.error| String |Shows the error happened in a component|
+|componentErrors.errorLapsedSecs| Integer | Number of seconds elapsed since 
the error happened in a component |
+|componentErrors.errorWorkerLogLink| String | Link to the worker log that 
reported the exception |
+|topologyId| String | Topology id|
+|tasks| Integer |Number of instances of component|
+|window    |String. Default value "All Time" | window duration for metrics in 
seconds|
+|spoutSummary or boltStats| Array |Array of component stats. **Please note 
this element tag can be spoutSummary or boltStats depending on the 
componentType**|
+|spoutSummary.windowPretty| String |Duration passed in HH:MM:SS format|
+|spoutSummary.window| String | window duration for metrics in seconds|
+|spoutSummary.emitted| Long |Number of messages emitted in given window |
+|spoutSummary.completeLatency| String (double value returned in String format) 
|Total latency for processing the message|
+|spoutSummary.transferred| Long |Total number of messages  transferred in 
given window|
+|spoutSummary.acked| Long |Number of messages acked|
+|spoutSummary.failed| Long |Number of messages failed|
+|boltStats.windowPretty| String |Duration passed in HH:MM:SS format|
+|boltStats..window| String | window duration for metrics in seconds|
+|boltStats.transferred| Long |Total number of messages  transferred in given 
window|
+|boltStats.processLatency| String (double value returned in String format)  
|Average time of the bolt to ack a message after it was received|
+|boltStats.acked| Long |Number of messages acked|
+|boltStats.failed| Long |Number of messages failed|
+
+Examples:
+
+```no-highlight
+1. 
http://ui-daemon-host-name:8080/api/v1/topology/WordCount3-1-1402960825/component/spout
+2. 
http://ui-daemon-host-name:8080/api/v1/topology/WordCount3-1-1402960825/component/spout?sys=1
+3. 
http://ui-daemon-host-name:8080/api/v1/topology/WordCount3-1-1402960825/component/spout?window=600
+```
+
+Sample response:
+
+```json
+{
+    "name": "WordCount3",
+    "id": "spout",
+    "componentType": "spout",
+    "windowHint": "10m 0s",
+    "executors": 5,
+    "componentErrors":[{"time": 1406006074000,
+                        "errorHost": "10.11.1.70",
+                        "errorPort": 6701,
+                        "errorWorkerLogLink": 
"http://10.11.1.7:8000/log?file=worker-6701.log";,
+                        "errorLapsedSecs": 16,
+                        "error": "java.lang.RuntimeException: 
java.lang.StringIndexOutOfBoundsException: Some Error\n\tat 
backtype.storm.utils.DisruptorQueue.consumeBatchToCursor(DisruptorQueue.java:128)\n\tat
 
backtype.storm.utils.DisruptorQueue.consumeBatchWhenAvailable(DisruptorQueue.java:99)\n\tat
 
backtype.storm.disruptor$consume_batch_when_available.invoke(disruptor.clj:80)\n\tat
 backtype...more.."
+    }],
+    "topologyId": "WordCount3-1-1402960825",
+    "tasks": 5,
+    "window": "600",
+    "spoutSummary": [
+        {
+            "windowPretty": "10m 0s",
+            "window": "600",
+            "emitted": 28500,
+            "transferred": 28460,
+            "completeLatency": "0.000",
+            "acked": 0,
+            "failed": 0
+        },
+        {
+            "windowPretty": "3h 0m 0s",
+            "window": "10800",
+            "emitted": 127640,
+            "transferred": 127440,
+            "completeLatency": "0.000",
+            "acked": 0,
+            "failed": 0
+        },
+        {
+            "windowPretty": "1d 0h 0m 0s",
+            "window": "86400",
+            "emitted": 127640,
+            "transferred": 127440,
+            "completeLatency": "0.000",
+            "acked": 0,
+            "failed": 0
+        },
+        {
+            "windowPretty": "All time",
+            "window": ":all-time",
+            "emitted": 127640,
+            "transferred": 127440,
+            "completeLatency": "0.000",
+            "acked": 0,
+            "failed": 0
+        }
+    ],
+    "outputStats": [
+        {
+            "stream": "__metrics",
+            "emitted": 40,
+            "transferred": 0,
+            "completeLatency": "0",
+            "acked": 0,
+            "failed": 0
+        },
+        {
+            "stream": "default",
+            "emitted": 28460,
+            "transferred": 28460,
+            "completeLatency": "0",
+            "acked": 0,
+            "failed": 0
+        }
+    ],
+    "executorStats": [
+        {
+            "workerLogLink": "http://10.11.1.7:8000/log?file=worker-6701.log";,
+            "emitted": 5720,
+            "port": 6701,
+            "completeLatency": "0.000",
+            "transferred": 5720,
+            "host": "10.11.1.7",
+            "acked": 0,
+            "uptime": "43m 4s",
+            "id": "[24-24]",
+            "failed": 0
+        },
+        {
+            "workerLogLink": "http://10.11.1.7:8000/log?file=worker-6703.log";,
+            "emitted": 5700,
+            "port": 6703,
+            "completeLatency": "0.000",
+            "transferred": 5700,
+            "host": "10.11.1.7",
+            "acked": 0,
+            "uptime": "42m 57s",
+            "id": "[25-25]",
+            "failed": 0
+        },
+        {
+            "workerLogLink": "http://10.11.1.7:8000/log?file=worker-6702.log";,
+            "emitted": 5700,
+            "port": 6702,
+            "completeLatency": "0.000",
+            "transferred": 5680,
+            "host": "10.11.1.7",
+            "acked": 0,
+            "uptime": "42m 57s",
+            "id": "[26-26]",
+            "failed": 0
+        },
+        {
+            "workerLogLink": "http://10.11.1.7:8000/log?file=worker-6701.log";,
+            "emitted": 5700,
+            "port": 6701,
+            "completeLatency": "0.000",
+            "transferred": 5680,
+            "host": "10.11.1.7",
+            "acked": 0,
+            "uptime": "43m 4s",
+            "id": "[27-27]",
+            "failed": 0
+        },
+        {
+            "workerLogLink": "http://10.11.1.7:8000/log?file=worker-6703.log";,
+            "emitted": 5680,
+            "port": 6703,
+            "completeLatency": "0.000",
+            "transferred": 5680,
+            "host": "10.11.1.7",
+            "acked": 0,
+            "uptime": "42m 57s",
+            "id": "[28-28]",
+            "failed": 0
+        }
+    ]
+}
+```
+
+## POST Operations
+
+### /api/v1/topology/:id/activate (POST)
+
+Activates a topology.
+
+|Parameter |Value   |Description  |
+|----------|--------|-------------|
+|id       |String (required)| Topology Id  |
+
+Sample Response:
+
+```json
+{"topologyOperation":"activate","topologyId":"wordcount-1-1420308665","status":"success"}
+```
+
+
+### /api/v1/topology/:id/deactivate (POST)
+
+Deactivates a topology.
+
+|Parameter |Value   |Description  |
+|----------|--------|-------------|
+|id       |String (required)| Topology Id  |
+
+Sample Response:
+
+```json
+{"topologyOperation":"deactivate","topologyId":"wordcount-1-1420308665","status":"success"}
+```
+
+
+### /api/v1/topology/:id/rebalance/:wait-time (POST)
+
+Rebalances a topology.
+
+|Parameter |Value   |Description  |
+|----------|--------|-------------|
+|id       |String (required)| Topology Id  |
+|wait-time |String (required)| Wait time before rebalance happens |
+|rebalanceOptions| Json (optional) | topology rebalance options |
+
+
+Sample rebalanceOptions json:
+
+```json
+{"rebalanceOptions" : {"numWorkers" : 2, "executors" : {"spout" :4, "count" : 
10}}, "callback" : "foo"}
+```
+
+Examples:
+
+```no-highlight
+curl  -i -b ~/cookiejar.txt -c ~/cookiejar.txt -X POST  
+-H "Content-Type: application/json" 
+-d  '{"rebalanceOptions": {"numWorkers": 2, "executors": { "spout" : "5", 
"split": 7, "count": 5 }}, "callback":"foo"}' 
+http://localhost:8080/api/v1/topology/wordcount-1-1420308665/rebalance/0
+```
+
+Sample Response:
+
+```json
+{"topologyOperation":"rebalance","topologyId":"wordcount-1-1420308665","status":"success"}
+```
+
+
+
+### /api/v1/topology/:id/kill/:wait-time (POST)
+
+Kills a topology.
+
+|Parameter |Value   |Description  |
+|----------|--------|-------------|
+|id       |String (required)| Topology Id  |
+|wait-time |String (required)| Wait time before rebalance happens |
+
+Caution: Small wait times (0-5 seconds) may increase the probability of 
triggering the bug reported in
+[STORM-112](https://issues.apache.org/jira/browse/STORM-112), which may result 
in broker Supervisor
+daemons.
+
+Sample Response:
+
+```json
+{"topologyOperation":"kill","topologyId":"wordcount-1-1420308665","status":"success"}
+```
+
+## API errors
+
+The API returns 500 HTTP status codes in case of any errors.
+
+Sample response:
+
+```json
+{
+  "error": "Internal Server Error",
+  "errorMessage": "java.lang.NullPointerException\n\tat 
clojure.core$name.invoke(core.clj:1505)\n\tat 
backtype.storm.ui.core$component_page.invoke(core.clj:752)\n\tat 
backtype.storm.ui.core$fn__7766.invoke(core.clj:782)\n\tat 
compojure.core$make_route$fn__5755.invoke(core.clj:93)\n\tat 
compojure.core$if_route$fn__5743.invoke(core.clj:39)\n\tat 
compojure.core$if_method$fn__5736.invoke(core.clj:24)\n\tat 
compojure.core$routing$fn__5761.invoke(core.clj:106)\n\tat 
clojure.core$some.invoke(core.clj:2443)\n\tat 
compojure.core$routing.doInvoke(core.clj:106)\n\tat 
clojure.lang.RestFn.applyTo(RestFn.java:139)\n\tat 
clojure.core$apply.invoke(core.clj:619)\n\tat 
compojure.core$routes$fn__5765.invoke(core.clj:111)\n\tat 
ring.middleware.reload$wrap_reload$fn__6880.invoke(reload.clj:14)\n\tat 
backtype.storm.ui.core$catch_errors$fn__7800.invoke(core.clj:836)\n\tat 
ring.middleware.keyword_params$wrap_keyword_params$fn__6319.invoke(keyword_params.clj:27)\n\tat
 ring.middleware.nested_params$wrap_nest
 ed_params$fn__6358.invoke(nested_params.clj:65)\n\tat 
ring.middleware.params$wrap_params$fn__6291.invoke(params.clj:55)\n\tat 
ring.middleware.multipart_params$wrap_multipart_params$fn__6386.invoke(multipart_params.clj:103)\n\tat
 ring.middleware.flash$wrap_flash$fn__6675.invoke(flash.clj:14)\n\tat 
ring.middleware.session$wrap_session$fn__6664.invoke(session.clj:43)\n\tat 
ring.middleware.cookies$wrap_cookies$fn__6595.invoke(cookies.clj:160)\n\tat 
ring.adapter.jetty$proxy_handler$fn__6112.invoke(jetty.clj:16)\n\tat 
ring.adapter.jetty.proxy$org.mortbay.jetty.handler.AbstractHandler$0.handle(Unknown
 Source)\n\tat 
org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)\n\tat 
org.mortbay.jetty.Server.handle(Server.java:326)\n\tat 
org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)\n\tat 
org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:928)\n\tat
 org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:549)\n\tat org.mortb
 ay.jetty.HttpParser.parseAvailable(HttpParser.java:212)\n\tat 
org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)\n\tat 
org.mortbay.jetty.bio.SocketConnector$Connection.run(SocketConnector.java:228)\n\tat
 
org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)\n"
+}
+```

Modified: storm/branches/bobby-versioned-site/releases/0.10.0/index.md
URL: 
http://svn.apache.org/viewvc/storm/branches/bobby-versioned-site/releases/0.10.0/index.md?rev=1735361&r1=1735360&r2=1735361&view=diff
==============================================================================
--- storm/branches/bobby-versioned-site/releases/0.10.0/index.md (original)
+++ storm/branches/bobby-versioned-site/releases/0.10.0/index.md Thu Mar 17 
02:16:31 2016
@@ -12,6 +12,7 @@ version: v0.10.0
 * [Guaranteeing message processing](Guaranteeing-message-processing.html)
 * [Fault-tolerance](Fault-tolerance.html)
 * [Command line client](Command-line-client.html)
+* [REST API](STORM-UI-REST-API.html)
 * [Understanding the parallelism of a Storm 
topology](Understanding-the-parallelism-of-a-Storm-topology.html)
 * [FAQ](FAQ.html)
 
@@ -31,6 +32,7 @@ Trident is an alternative interface to S
 * [Troubleshooting](Troubleshooting.html)
 * [Running topologies on a production 
cluster](Running-topologies-on-a-production-cluster.html)
 * [Building Storm](Maven.html) with Maven
+* [Setting up a Secure Cluster](SECURITY.html)
 
 ### Intermediate
 


Reply via email to