Wallaby 0.16.0, which updates the Wallaby API version to 20101031.6, includes support for authorizing broker users with various roles that can interact with Wallaby in different ways. This post will explain how the authorization support works and show how to get started using it. If you just want to get started using Wallaby with authorization support as quickly as possible, skip ahead to the section titled “Getting Started” below. Detailed information about which role is required for each Wallaby API method is after the jump.

## Overview

Users must authenticate to the AMQP broker before using Wallaby (although some installations may allow users to authenticate as “anonymous”), but previous versions of Wallaby implicitly authorized any user who had authenticated to the broker to perform any action. Wallaby now includes a database mapping from user names to roles, which allows installations to define how each broker user can interact with Wallaby. Each method is annotated with the role required to invoke it, and each method invocation is checked to ensure that the currently-authenticated user is authorized to assume the role required by the method. The roles Wallaby recognizes are NONE, READ, WRITE, or ADMIN, where each role includes all of the capabilities of the role that preceded it.

If WALLABY_USERDB_NAME is set in the Wallaby agent’s environment upon startup and represents a valid pathname, Wallaby will use that as the location of the user-role database. If this variable is set to a valid pathname but no file exists at that pathname, the Wallaby user-role database will be created upon agent startup. If WALLABY_USERDB_NAME is not set, the user-role database will be initialized in memory only and thus will not persist across agent restarts.

### Standard authorization

When Wallaby is about to service an API request, it:

1. checks the role required to invoke the method.
2. checks the authorization level specified for the user. There are several possibilities under which a user could be authorized to invoke a method:
• the user is explicitly authorized for a role that includes the required role (e.g. the user has an ADMIN role but the method only requires READ);
• the user is implicitly authorized for a role that includes the required role (e.g. there is an entry for the wildcard user * giving it READ access and the method requires READ access)
• the role database is empty, in which case all authenticated users are implicitly authorized for all actions (this is the same behavior as in older versions of Wallaby)
• the invocation is of a user-role database maintenance method and the client is authorized via shared secret (see below)
3. if none of the conditions of the above step hold, the method invocation is unauthorized and fails with an API-level error. If the API method is invoked over the Ruby client library, it will raise an exception. If it is invoked via a wallaby shell command-line tool, it will print a human-readable error message and exit with a nonzero exit status.
4. if the user is authorized to invoke the method, invocation proceeds normally.

### Authorization with secret-based authentication

This version of the Wallaby API introduces three new methods: Store#set_user_privs, Store#del_user, and Store#users. These enable updating and reading the user-role database; the first two require ADMIN access, while the last requires READ access. Because changes in the user-role database may result in an administrator inadvertently removing administrator rights from his or her broker user, Wallaby provides another mechanism to authorize access to these methods. Each of these three methods supports a special secret option in its options argument. When the Wallaby service starts up, it loads a secret string from a file. Clients that supply the correct secret as an option to one of these calls will be authorized to invoke these calls, even if the broker user making the invocation is not authorized by the user-role database.

The pathname to the secret file is given by the environment variable WALLABY_SECRET_FILE. If this variable is unset upon agent startup, Wallaby will not use a shared secret (and secret-based authorization will not be available to API clients). It this variable is set and names an existing file that the Wallaby agent user can read, the Wallaby shared secret will be set to the entire contents of this file. If this variable is set and names a nonexistent file in a path that does exist, Wallaby will create a file at this path upon startup with a randomly-generated secret (consisting of a digest hash of some data read from /dev/urandom). If this variable is set to a pathname that includes nonexistent directory components, the Wallaby agent will raise an error. If you create your own secret file, ensure that it is only readable by the UNIX user that the Wallaby agent runs as (typically wallaby).

### Caveats

The Wallaby agent’s authorization support is designed to prevent broker users from altering Condor pool configurations in excess of their authority. It is not intended to keep all configuration data strictly confidential. (This is not as bad as it might sound, since Wallaby-generated configurations are available for inspection by Condor users.) Furthermore, due to technical limitations, it is not possible to protect object property accesses over the API with the same authorization support that we use for API method invocations. Therefore, if concealing configuration data from some subset of users is important for your installation, you should prevent these users from authenticating to the broker that the Wallaby agent runs on.

## Getting started

Here is a quick overview of how to get started with auth-enabled Wallaby:

1. Stop your running Wallaby and restart your broker before starting the new Wallaby (this is necessary to pick up the new API methods). Set WALLABY_USERDB_NAME in your environment to a path where you can store the user-role database. Install and start your new Wallaby.
2. If you’re using the RPM package, it will create a “secret file” for you in /var/lib/wallaby/secret. If not, you will need to set WALLABY_SECRET_FILE in the environment to specify a location for this secret file and then restart Wallaby. The Wallaby secret is a special token that can be passed to certain API methods (specifically, those related to user database management) in order to authorize users who aren’t authorized in the user database.
3. Try using some of the new shell commands: wallaby set-user-role, wallaby list-users, and wallaby delete-user.
4. Make sure that you have a secret in your secret file. Make a note of it. Try setting the role for your current broker user to READ or NONE (e.g. “wallaby set-user-role anonymous NONE”) and then see what happens when you try and run some other Wallaby shell commands. You can recover from this by passing the Wallaby secret to “wallaby set-user-role”; see its online help for details.

The default user database is empty, which will result in the same behavior as in older versions of Wallaby (viz., all actions are available to all broker users), but only until a user role is added, at which point all actions must be explicitly or implicitly authorized.

## Permissions required for API methods

• Feature#annotation requires at least READ access
• Feature#clearParams requires at least WRITE access
• Feature#explain requires at least READ access
• Feature#modifyConflicts requires at least WRITE access
• Feature#modifyDepends requires at least WRITE access
• Feature#modifyIncludedFeatures requires at least WRITE access
• Feature#modifyParams requires at least WRITE access
• Feature#setAnnotation requires at least WRITE access
• Feature#setName requires at least WRITE access
• Group#addFeature requires at least WRITE access
• Group#annotation requires at least READ access
• Group#clearFeatures requires at least WRITE access
• Group#clearParams requires at least WRITE access
• Group#explain requires at least READ access
• Group#getConfig requires at least READ access
• Group#membership requires at least READ access
• Group#modifyFeatures requires at least WRITE access
• Group#modifyParams requires at least WRITE access
• Group#removeFeature requires at least WRITE access
• Group#setAnnotation requires at least WRITE access
• Group#setName requires at least WRITE access
• Node#annotation requires at least READ access
• Node#checkConfigVersion requires at least READ access
• Node#checkin requires at least READ access
• Node#explain requires at least READ access
• Node#getConfig requires at least READ access
• Node#makeProvisioned requires at least WRITE access
• Node#makeUnprovisioned requires at least WRITE access
• Node#modifyMemberships requires at least WRITE access
• Node#setAnnotation requires at least WRITE access
• Node#whatChanged requires at least READ access
• Parameter#annotation requires at least READ access
• Parameter#modifyConflicts requires at least WRITE access
• Parameter#modifyDepends requires at least WRITE access
• Parameter#setAnnotation requires at least WRITE access
• Parameter#setDefault requires at least WRITE access
• Parameter#setDescription requires at least WRITE access
• Parameter#setKind requires at least WRITE access
• Parameter#setMustChange requires at least WRITE access
• Parameter#setRequiresRestart requires at least WRITE access
• Parameter#setVisibilityLevel requires at least WRITE access
• Store#activateConfiguration requires at least ADMIN access
• Store#addExplicitGroup requires at least WRITE access
• Store#addFeature requires at least WRITE access
• Store#addNode requires at least WRITE access
• Store#addNodeWithOptions requires at least WRITE access
• Store#addParam requires at least WRITE access
• Store#addSubsys requires at least WRITE access
• Store#affectedEntities requires at least READ access
• Store#affectedNodes requires at least READ access
• Store#checkFeatureValidity requires at least READ access
• Store#checkGroupValidity requires at least READ access
• Store#checkNodeValidity requires at least READ access
• Store#checkParameterValidity requires at least READ access
• Store#checkSubsystemValidity requires at least READ access
• Store#getDefaultGroup requires at least READ access
• Store#getFeature requires at least READ access
• Store#getGroup requires at least WRITE access
• Store#getGroupByName requires at least READ access
• Store#getMustChangeParams requires at least READ access
• Store#getNode requires at least READ access
• Store#getParam requires at least READ access
• Store#getSkeletonGroup requires at least READ access
• Store#getSubsys requires at least READ access
• Store#loadSnapshot requires at least WRITE access
• Store#makeSnapshot requires at least WRITE access
• Store#makeSnapshotWithOptions requires at least WRITE access
• Store#removeFeature requires at least WRITE access
• Store#removeGroup requires at least WRITE access
• Store#removeNode requires at least WRITE access
• Store#removeParam requires at least WRITE access
• Store#removeSnapshot requires at least ADMIN access
• Store#removeSubsys requires at least WRITE access
• Store#storeinit requires at least ADMIN access
• Store#validateConfiguration requires at least READ access
• Subsystem#annotation requires at least READ access
• Subsystem#modifyParams requires at least WRITE access
• Subsystem#setAnnotation requires at least WRITE access

## Permissions required for Wallaby shell commands

### Commands available to any broker user

• apropos: Provides a list of parameters that contain KEYWORD in their descriptions.
• console: Provides an interactive wallaby environment. (N.B.: individual API methods invoked from within the console environment may still fail if the user is not authorized.)
• help: Provides brief documentation for wallaby shell commands.
• inventory: Lists a (non-strict) subset of wallaby-managed nodes.
• list-features: Lists all the feature names in the store.
• list-groups: Lists all the group names in the store.
• list-nodes: Lists all the node names in the store.
• list-params: Lists all the parameter names in the store.
• list-snapshots: Lists snapshots in the store.
• list-subsystems: Lists all the subsystem names in the store.
• new-command: Generates Ruby files containing templates for new wallaby shell commands
• sanitize: Obfuscates potentially-sensitive entity names in a wallaby database dump.
• shebang: Provides an interpreter for wallaby scripts. (N.B.: individual API methods invoked from within the script environment may still fail if the user is not authorized.)
• show-feature: Displays the properties of a feature.
• show-node: Displays the properties of a node.
• show-param: Displays metadata about a parameter in the store.
• show-subsystem: Displays the properties of a subsystem.

### Commands requiring READ access

• dump: Dumps a wallaby snapshot to a file.
• explain: Outputs an annotated display of a node’s current configuration.
• http-server: Provides a HTTP service gateway to wallaby node configurations.
• list-users: Lists Wallaby roles for broker users.
• show-group: Displays the properties of a group. (N.B.: unlike the other show-* commands, this invokes an API method and not merely API object property accessors)

### Commands requiring WRITE access

• add-conflicts-to-feature: Add conflicts to a feature in the store.
• add-conflicts-to-param: Add conflicts to a parameter in the store.
• add-dependencies-to-feature: Add dependencies to a feature in the store.
• add-dependencies-to-param: Add dependencies to a parameter in the store.
• add-feature: Adds a feature to the store.
• add-features-to-group: Add features to a group in the store.
• add-features-to-node: Add features to a node in the store.
• add-group: Adds a group to the store.
• add-includes-to-feature: Add includes to a feature in the store.
• add-node: Adds a node to the store.
• add-node-memberships: Add group memberships to a node in the store.
• add-nodes-to-group: Add nodes to a group in the store.
• add-param: Adds a parameter to the store.
• add-params-to-feature: Add parameters to a feature in the store.
• add-params-to-group: Add parameters to a group in the store.
• add-params-to-node: Add parameters to a node in the store.
• add-params-to-subsystem: Add parameters to a subsystem in the store.
• add-subsystem: Adds a subsystem to the store.
• feature-import: Imports a wallaby feature from a Condor configuration file.
• make-snapshot: Makes a snapshot with a given name.
• modify-feature: Alters metadata for a feature in the store.
• modify-group: Alters metadata for a group in the store.
• modify-param: Alters metadata for a parameter in the store.
• remove-conflicts-from-feature: Remove conflicts from a feature in the store.
• remove-conflicts-from-param: Remove conflicts from a parameter in the store.
• remove-dependencies-from-feature: Remove dependencies from a feature in the store.
• remove-dependencies-from-param: Remove dependencies from a parameter in the store.
• remove-feature: Deletes a feature from the store.
• remove-features-from-group: Remove features from a group in the store.
• remove-features-from-node: Remove features from a node in the store.
• remove-group: Deletes a group from the store.
• remove-includes-from-feature: Remove includes from a feature in the store.
• remove-node: Deletes a node from the store.
• remove-node-memberships: Remove group memberships from a node in the store.
• remove-nodes-from-group: Remove nodes from a group in the store.
• remove-param: Deletes a parameter from the store.
• remove-params-from-feature: Remove parameters from a feature in the store.
• remove-params-from-group: Remove parameters from a group in the store.
• remove-params-from-node: Remove parameters from a node in the store.
• remove-params-from-subsystem: Remove parameters from a subsystem in the store.
• remove-snapshot: Removes a snapshot with a given name.
• remove-subsystem: Deletes a subsystem from the store.
• replace-conflicts-on-feature: Replace the conflicts on a feature in the store with a new set of conflicts.
• replace-conflicts-on-param: Replace the conflicts on a parameter in the store with a new set of conflicts.
• replace-dependencies-on-feature: Replace the dependencies on a feature in the store with a new set of dependencies.
• replace-dependencies-on-param: Replace the dependencies on a parameter in the store with a new set of dependencies.
• replace-features-on-group: Replace the features on a group in the store with a new set of features.
• replace-features-on-node: Replace the features on a node in the store with a new set of features.
• replace-includes-on-feature: Replace the includes on a feature in the store with a new set of includes.
• replace-node-memberships: Replace group memberships on a node in the store with a new set of group memberships.
• replace-params-on-feature: Replace the parameters on a feature in the store with a new set of parameters.
• replace-params-on-group: Replace the parameters on a group in the store with a new set of parameters.
• replace-params-on-node: Replace the parameters on a node in the store with a new set of parameters.
• replace-params-on-subsystem: Replace the parameters on a subsystem in the store with a new set of parameters.
• upgrade-db: Upgrade the wallaby database.

### Commands requiring ADMIN access

• activate: Activates pending changes to the pool configuration.
• delete-user: Deletes Wallaby role information for a broker user. (N.B. Can also be authorized via shared secret)
• force-pull: Force a configuration pull
• force-restart: Force all daemons to restart
• load: Loads a wallaby snapshot from a file or from standard input (N.B. ADMIN access required if --activate option supplied)
• load-snapshot: Loads the snapshot with a given name.
• set-user-role: Defines or modifies Wallaby roles for broker users. (N.B. Can also be authorized via shared secret)