106 26th Large Installation System Administration Conference (LISA ’12) USENIX Association
“Pending Jobs” link in the “Staff Requests” dashboard
tile, which leads to a page that can show not only pend-
ing requests but also a log of all previously executed jobs.
4 Security Model
From a security standpoint, it is important to ensure that
user input is verified before it is used to make automated
system-administration decisions. This provides protec-
tion against security vulnerabilities and prevents actions
from running which would leave the server in an incon-
sistent state. This level of our security model is im-
plemented with a layer of parameter checker functions
that serve as a boundary between the interface-level code
and the server-side functions. The code as implemented
enforces our security guarantees while providing a con-
venient code interface for service programmers. It also
serves as a common repository of validators for various
data types, such as Unix users and mailing list names.
The input verification is all done on the server side.
Similar to the Linux kernel, which provides a system call
interface for userland to call into the kernel, the privi-
leged code (in Linux’s case, the kernel; in our case, the
checker functions) needs to carefully check the validity
of the parameters before doing anything. gutsd receives
job requests over the Desktop-Bus (D-Bus) interface [5],
and does not trust that input.
There are two kinds of verification which must be
performed. The first is traditional input verification for
web applications, in order to verify the input is correctly
formed and to prevent database injection attacks. These
are handled by individual parameter verifiers, which
might check the format of a Unix username or verify
that a flag coming from a dropdown list actually be-
longs to the set of legal options. After this basic verifica-
tion, there are function-level checkers, which can reason
about the relationships between parameters (for example,
“Does this user have administrative permissions on this
Git repository?”) with full confidence that the parame-
ters are valid for their individual data types.
To guarantee security, gutsd should check its inputs
whenever they come from untrusted sources, and when-
ever the underlying system state might have changed.
To this end, the verification typically happens multiple
times during the lifetime of a call into GUTS. There are
four ways to call into gutsd: (1) When an info func-
tion is invoked, the parameters are checked before the
function is executed; these functions do not change sys-
tem or database state. (2) When an action is invoked,
the parameters are checked first, then the action is tried.
If successful, the result is logged in the database, but
if not a parameter error is returned to the caller (usu-
ally gutsweb). (3) A delayed action’s parameters are
checked, and if successful the server enters the request
into the database and emails the staff. (4) Meta functions
are like info functions, except that they are allowed to
modify system state indirectly (e.g. by calling an action).
Through these four interfaces, invalid data never enters
the database, and data is verified both when originally
submitted and immediately before being used.
Figure 6 presents a code sample from the git service
(with some changes for brevity). This code demonstrates
several parameter checkers and the beginning of a func-
tion which implements a GUTS action. This particular
action can perform several functions related to the man-
agement of a Git repository (changing web visibility, de-
scriptions, and user access). One of the parameters it
must verify is a Unix user/group, so the action uses the
user-or-group data type provided by libguts (logic
within the function differentiates users and groups).
The permissions and visibility arguments are ver-
ified to belong to a limited set of possibilities, while
name verifies that a repository with the given name ex-
ists. Then, the action checker, check
user is admin,
verifies that the user attempting to execute this ac-
tion has the necessary privileges. It would be easy to
create a check
update settings function that called
check
user is admin as well as performing any other
required checks, if more checks were necessary.
The actual declaration of a GUTS action with specifi-
cation of the verifiers is implemented using the Python
function declaration syntax. A decorator provided by
libguts interprets special default arguments of type
Param to build up type information for each action
parameter. This ties into one of our major design
goals, which is to make implementing an action as
simple as writing a Python function. The function
update
settings in the code sample appears to be
declaring a Python function with default values for its ar-
guments. However, the decorators actually result in the
creation of an object that automatically decodes its ar-
guments from JSON, verifies them for correctness, and
encodes return values, raising exceptions that GUTS un-
derstands if anything goes wrong along the way. All of
this complexity is hidden from the service programmer.
Security Implications of gutsweb
Because gutsweb is a trusted client, a compromised
gutsweb process could perform tasks on behalf of any
user. However, the attack surface and potential damage
are limited by the defined functions, and a compromised
gutsweb process does not have root access. The fron-
tend does not contain logic about user privileges; this is
instead described and enforced in the validators for the
functions themselves, preventing duplication of informa-
tion and simplifying the implementation of gutsweb.