Using Security Tagging to Control Access to Data

Security tagging is a facility that enables you to mark every tuple arriving on a specified data source with a special, immutable security field. As input arrives from different data sources, the associated security values are accumulated in predictable ways by each of the application's operators and data constructs. For example, some operators simply pass through security level of each tuple received; others can aggregate security levels from multiple tuples.

Security tagging is implemented in two phases: configuration and application design.

Configuration

In the sbconf file for the StreamBase Server that will run the application, you must enable security tagging and define the tags to be used at specified inputs. You can also define rules that test the security level of tuples at specified outputs: these cause exceptions upon failure.

Detection

When running applications with security tagging enabled, you can detect the current security level of any component at any point in the flow, and respond in some way. To to this, use the special securitytag function in your application. For example, you might use the securitytag function in a Map operator expression to filter tuples whose security level is beyond a specified threshhold.

This distinction supports a separation of roles: an administrator may have exclusive control over configuration, which is not accessible to developers in the deployed application.

Configuring Security Tagging

Configuration is done entirely in the StreamBase Server configuration file. The valid fields and syntax are described in StreamBase Server Configuration XML. The general procedure is as follows:

  1. Create a security-tagging section. Include a param element to enable security tagging, as shown in the example below:

    <security-tagging>
      <param name="enabled" value="true"/>
      <tag path="default.SomeInputStream" value="3"/>
      <tag path="default.SomeAdapter" value="12"/>
      <rule path="container1.OutputStream"
            value="3"/>
    </security-tagging>
    

    If set to false, security tagging is turned off at run time (the default behavior), and any child elements in the section are ignored.

  2. Define a tag element for each input stream or input adapter that you want to have a security value, and assign a positive integer value to each tag. The range of values should express the relative security ranking you want among the inputs. In the example just shown, the second data source has a higher security ranking than the first.

  3. Optionally, you can also define one or more rules. A rule defines a maximum security level for the tuples allowed to travel to that output. At run time, the server checks whether the data arriving on an output stream or output adapter is in compliance with the defined rules. A tuple with a security value higher than a rule is considered to be an exceptional error condition.

    When a rule finds a tuple with too high of a security value, a SecurityTaggingException is thrown. The tuple will not pass through the stream, although it may continue on other streams where it does comply with any security predicates. The exception can be logged and managed in the same way as other runtime errors, as described in StreamBase Runtime Error Logging.

As the example shows, path values must include the container name. This provides maximum flexibility in using different levels in different situations.

Detecting Security Levels

If your application will be run with security tagging, you can design the application to detect security levels at any point in the flow. This section first describes the runtime behavior you should expect of security tags, and then how to detect and respond to them.

When an application receives input from a stream or adapter that has been configured at a certain security level, each tuple contains, in addition to its schema fields, a security field with the assigned value. As the tuple flows through components in the application, its security tag can be handled in several different but predictable ways:is either passed through unchanged, or stored in the component, where it may be aggregated with security tags from other tuples. For example:

  • When a component such as a Map or Filter operator accepts a single stream, each tuple's security tag is passed through unchanged. Similarly, a Union operator passes through tuples from multiple streams without merging them, so the security tags are passed through unchanged.

  • Other components can aggregate security tags from multiple tuples, including the Aggregate, Merge, Join, and Gather operators. Security tag aggregation means that security tags are stored in the operator. When the operator emits output, the highest security value received during the operation is passed through on the output tuples represents the component's security tag value.

    Similarly, Materialized Windows aggregate security tags received on the their input streams (Their associated Query operators are read-only, and cannot contribute security tagging.)

  • Data constructs (except for Materialized Windows) store and aggregate security tags through tuple they receive from their associated Query operators. For example, if a Query operator writes a tuple to an associated Query Table, the Query Table stores the tuple's security tag. If the table is updated, the Query Table's security level is also updated: the aggregated value is the highest level received to date. No security tagging is contributed through a Query operator read operation.

You can detect the security level of any component in your application by using the securitytag function in an expression. If a component does not accept expresions, you can insert a Map operator downstream to detect the security level.

For example, suppose you want to display the security level of a Map operator in an EventFlow:

  1. Open the Map operator's Properties view.

  2. In the Output Settings tab, after specifying which input fields to include in the output, add one more field to display the security level. If you selected the option to pass through all input fields, your Output Fields table might look like this:

    Action Field Name Expression
    Add Security Flag securitytag()

An analogous StreamSQL application might contain the following code fragment:

CREATE  STREAM out_Map_1;
SELECT Symbol AS Symbol,
       Name AS Name,
       Description AS Description,
       Volume AS Volume,
       Price AS Price,
       securitytag() AS SecurityFlag
FROM   StockIn
INTO   out_Map_1;

In addition to simply displaying security levels, the securitytag function can be used in more complex expressions to act on the result. For example, the following filtering expression excludes tuples whose security level is 5 or greater.

Symbol_R ==Symbol_C && securitytag() < 5