Parser for plays to be stored in a Playbook. The grammar is
straightforward with the exception of ranges and range lists.
Basic Syntax
Each play consists of an if clause (predicate) and one or more
constraint phrases. These are all separated by colons and
terminated with a semi-colon. For example:
<if clause>:<constraint>:...<constraint>;
The <if clause> is an expression involving
Condition s and
constants that must evaluate to true or false. A constraint
consists of an
OperatingMode following by a
ConstraintOperator and a range list and signifies that the
OperatingMode will be constrained so as to satisfy the relation
specified by the operator to the range list. For example:
FooPlugin.MODE < 5;
FooPlugin.MODE in {1 to 7};
FooPlugin.SPEED = "FAST";
Note that both relational and range operators (==, not it, etc.) as
well as assignment may be used. Assignment explicitly specifies the
allowed values. Relational and range operators implicitly specify
the allowed values by specifying the test that any such value must
satisfy. The operators =, ==, and in are all equivalent as are !=
and not in. The other relational operators are usually used with
single valued range lists (constants).
Comments
Comments are ignored by the parser. Both slash-slash and slash-star
comments are recognized. The former beging with two adjacent
slashes and terminate at the end of line. The latter terminate with
a star-slash sequence.
Numeric Constants
Numeric constants are interpreted as floating point numbers
(doubles). When necessary, numbers will be automatically cast to integers or
longs. A consequence of this is that plays may not use the full
precision offered by longs (64 bits) and are restricted to the 56
bits of precision in a double.
Ranges
A range is written as two numbers separated by the keyword "to" or
"thru". The former excludes the end point and the latter includes
the end point. A point range (a range having exactly one value) may
be written as a single number; 7 is equivalent to 7 thru 7. 7 to 7,
on the other hand, is an empty range; it allows no values.
Range Lists
A range list is a sequence of ranges enclosed in braces. The
elements of a range list may be separated by commas, but they are
not required; white space is sufficient. A range
list consisting of exactly one range my omit the braces.
Consequently, a numeric constant is also a range list. Range lists
frequently have elements that are point ranges and express list of
descrete values rather than a continuum. Range lists
may appear only as the right-hand operand of relational operators
(see below). Numeric constants may appear in arithmetic expressions.
to the written value. In general the context makes it clear which
should be used, but for example:
Foo < {11 to 20, 25 thru 30, 1 to 3};
is true if Foo is less than 1 (the minimum of the ranges). This
characteristic is an artifact of the parser and probably
insignificant to the playbook writer.
As implied above, a range list consists of one or more ranges
enclosed in braces. The comma between the ranges is optional (white
space is sufficient). The braces are also optional if the list has
a single range. Each range consists of either one number or string
or two numbers or strings separated by either "to" or "thru". "To"
signifies a range that does not include the end point whereas
"thru" signifies a range that does include the end point. If the
number is floating point, only the exact value given by the end
point is excluded. The next smaller value that can be represented
is always included. This characteristic can be used to insure there
are no gaps in the coverage of a series of predicates. For
example:
x in {1 to 3, 5 to 10}:...;
x in {3 to 5}:...;
x >= 10:...; insures that exactly one of the predicates
is true for any
value of x from 1 to infinity. There is no value of x that can fall
into a crack in the vicinity of 3 or 5 or 10 nor is there any value of x
in those same regions that can cause two predicates to
fire. Numbers are parsed as doubles and coerced to other
numeric typs as needed. This means that long values cannot be
written with their entire range. (Doubles can exactly represent
only 56 bits of precision.)
StringsStrings are used as constants (range limits),
Condition names and OperatingMode names. The interpretation depends
on context (see below). Strings do not need to be quoted unless
they contain characters (such as spaces) that have syntactic
meaning to the parser. In particular, strings need not be quoted
when they contain . (period) and [] (brackets). All other
punctuation and special characters should be quoted.
String constants can be used in range lists and arithmetic
expressions using the + operator. Strings cannot be used in other
arithmetic expressions. String comparisons are usually
confined to equality and inequality tests, but the other operators
have a defined meaning (alphabetic comparison using the default
collation sequence). String ranges are rare, but if used, have a
slightly different meaning when "to" ranges are specified because
the highest value included in a "to" range would be infinitely
long. For example, the last string in the range "bar" to "foo"
would be "fon\uffff\uffff\uffff\uffff...". It is hard to conceive of
a use for a "to" range involving strings, so the infinite string is
truncated after the first "\uffff".
Strings that name Conditions can be used in arithmetic
expressions if the named Condition has a numeric value. If the
named Condition has a String value, then only the + operator is
allowed.
If Clause Operators
Arithmetic Operators (+, -, *, /)
These have their standard meanings. The parser treats these with
standard precedence so parentheses are needed in the usual places.
When in doubt, parenthesize. There is no modulus operator (%).
Relational Operators (< <= == != >= >)
Relational operators compare two quantities and yield a boolean
(true or false) result. Relational operators are not
commutative; the interpretation of the left hand operand is
different from the right hand operand. Strings in the left hand
operand always name Conditions in if clauses or OperatingModes in
constraints. Strings in the right hand operand are always values
(or range limits). So, for example, in the play:
FOO == HIGH: HIGH = FOO; The first FOO is the name of a
Condition, the second FOO is a value to be stored in the
OperatingMode named HIGH when the Condition named FOO has a value
equal to HIGH. For clarity, it is a good practice to quote strings
used as values and not quote strings that denote Conditions and
Operating Modes.
Comparison of strings uses the default
collation sequence for characters.
Range Operators (in and not in)
Range operators test for inclusion in (or exclusion from) a range
list. The meaning is straightforward:
x in {1 thru 7, 10} is true iff
x has a value between 1 and 7 inclusive or has the value 10. A
range list is just a shorthand for a combination of less than and
greater than terms, but is easier to write and process.
Boolean ConstantsThe boolean constants true and false
may be used in an if clause. This is useful when developing a
playbook before the details are worked out or to deactivate certain
plays.
Constraints
Constraints specify an allowed list of ranges to which an
OperatingMode can be set. The constraints from all the
plays (including those manufactured from policies) are combined
(intersected) to form the final constraint. Often this final
constraint is a single value, but when it has multiple values, the
minimum of the first range in the list is used. The constraint can
be viewed either as an expression that must be true or as an
assignment of a range list to the OperatingMode . For
example:
Opmode1 = 3
Opmode1 in {3 thru 3}
Opmode1 == 3
are all equivalent. The first assigns the single valued range {3
thru 3} to Opmode1. The second requires that Opmode1 have the value
3 so that is in the range 3 thru 3. The third requires that Opmode1
be exactly equal to 3. All forms of constraints are rewritten
as an assignment of a range list to the OperatingMode .
For example:
Opmode < 3
is rewritten as:
Opmode = {<negative infinity> to 3}
The process of intersecting the constraints from several plays may
not be clear. For example, if the if clauses of two places yielded
these two constraints:
opmode in {56, 128, 256, 1024}
opmode >= 128 The combined constraint would be:
opmode in {128, 256, 1024} Another example:
opmode in 1 thru 10
opmode in 5 to 20 The combined result would be:
opmode in 5 thru 10 For a value to be included in the
combined range list, it must be included by the range lists of all
the selected plays. It is a playbook-writing error to allow plays
to be simultaneously active for which the combined range list is
empty. For example:
opmode in {56, 128, 256}
opmode < 56 would be an error. Such errors are not detected
until they occur. When they do occur, they are logged and the later
constraint is ignored. OperatingModeConditions
OperatingModeConditions are intermediate variables the act as
OperatingModes in some plays and Conditions in later plays. This
allows certain plays such as those that result from policies
received from other agents to set the value of an agent-wide
OperatingMode that is then translated into component-specific
OperatingModes by using the agent-wide mode as a Condition in other
plays. For example, assume the following plays resulting from
inter-agent operating mode policies:
Threatcon > 3: DefensePosture = 2;
Threatcon <= 3: DefensePosture = 1;
and the following plays from the local playbook:
DefensePosture < 2: FooPlugin.keyLength = 56: AdaptivePlugin.fidelity = high;
DefensePosture >= 2: FooPlugin.keylength = 128: AdaptivePlugin.fidelity = medium;
The allows the outside agent to be unaware of the details of the
makeup of the agent by expressing its policy in terms of a
"DefensePosture" concept. However, the local playbook is developed with an
awareness of the agent makeup so it can contain plays to set the
operating modes of its plugins based on this
DefensePosture value. OperatingModePolicy
An OperatingModePolicy has the same syntax as a Play except that it
is prefixed with a name.
|