Chapter 20. System-Level Networking

The system-level network case study models the behavior of changing network infrastructure with respect to a constant set of access control requirements. The example is motivated by the problem of moving a portable computer from one network to another, seamlessly maintaining functionality without violating security constraints. Figure 20.1 illustrates the problem where in a portable computer is carried between an office environment that is closed and secure, a home environment that is somewhat controlled, and a completely open environment such as a coffee shop, where the environment is not known or controllable. The user of the portable computer would like to work on the same task while satisfying security requirements. In effect, a trade-off between accessibility and access control is continually being made.

System-level networking requirements.

Figure 20.1. System-level networking requirements.

This case study differs substantially from the RTL and power-aware studies in that the system implementation is not a part of the modeling process. Certainly architectural issues are addressed, but the biggest issue is developing a reasonable requirements model. Thus, we will not develop models of firewalls and routers, but models of working environments and resource access restrictions.

Although models may differ, the methodology followed by the networking case study is virtually identical to that in the previous case studies. First, decide what information must be known. Second, select domains for the basic models that are as abstract as possible. Then define basic models for components and compose models to define systems. Finally, generate analysis models from composite models by moving them to different domains.

The Basic Models

There are three types of models involved in this example, responsible for representing function, performance requirements, and operational infrastructure. The functional requirements model defines what services the network must provide to the user and what services are available. The security model defines access control requirements on various system resources and specifies constraints on how functions are provided. Finally, the infrastructure models define support provided by the various network infrastructures. If the infrastructure can provide required services while meeting system requirements, then we have an ideal system. However, modeling what the system can provide is as important as providing a binary correctness result.

Access requirements can be viewed as invariants on system state. Specifically, no network entity that is not trusted should be allowed to access private resources. Because requirements define invariants, the static domain is the most appropriate domain for an abstract specification. Functionality and infrastructure models differ from access requirements in that a need exists to specify temporal requirements. When a request is processed by the infrastructure, it must respond to that request by changing what it knows about its resources. Likewise, a requesting entity changes state when its requests are met or denied.

Because there are no timing requirements specified, the most appropriate domain here is the state_based domain, where change can be represented, but the details of that change can be avoided. The finite_state and infinite_state domains may also be appropriate, but nothing is known about the cardinality of the state set. Therefore, infrastructure and functional requirements models are written in the state_based domain.

Types, Constants, and Predicates

The network_entities package defined in Figure 20.2 defines a collection of shared types, functions, and constants that are shared across specifications. Virtually any large specification will define a package like network_entities that provides shared constructs to all models. A similar package can be found in the RTL case study in Chapter 17.

Example 20.2. Basic resource and credential entities.

package network_entities()::static is
  id ::type is constant;
  resource ::type is constant;

  secure_server :: resource is constant;
  public_server :: resource is constant;
  internal :: id is constant;
  external :: id is constant;
  public :: id is constant;
  private :: id is constant;
  firewall :: id is constant;

  message ::type is data
    request(a,b::id;r::resource)::request?
    | grant(a,b::id;r::resource)::grant?
    | revoke(a,b::id;r::resource)::revoke?
    | trust(a,b::id)::trust?
    | distrust(a,b::id)::distrust?
  end data;

  trusts_with(a,b::id;r::resource)::boolean;

  trusts(a,b::id)::boolean;

  grants(a,b::id; r::resource)::boolean;

  transitive_trust(a,b,c::id)::boolean is
    trusts(a,b) and trusts(b,c) => trusts(a,c);

  transitive_trusts_with(a,b::id; r::resource)::boolean is
    trusts(a,b) and trusts_with(b,c,r) => trusts_with(a,c,r)

  will_grant(a,b::id; r::resource)::boolean is
    trusts_with(a,b,r)and requests(a,b,r) => grants(a,b,r)

end package network_entities;

The id and resource types define uninterpreted types for entities in the network and resources they may request. These types are uninterpreted because their internal representation is not germane to what is being specified. It is sufficient to define properties for entities and resources in the specification.

Several constants are defined of type resource and id that are visible to all specifications using the package. The two server declarations represent resources that may be requested and are controlled by the secure infrastructure. The two id declarations define entities that are known in all specifications. Again, the details of entities and resources are not important, thus they are declared as constants without specific values.

The message data type defines messages that are exchanged between network entities. It is critical that these definitions exist in a shared package, because all component specifications must be able to send and receive messages for requests and updates to trust relationships. Specific message instances exist for requesting, granting, and revoking access as well as for establishing and removing trust relationships.

The final element of the network_entities package defines a collection of predicates that define properties of components that grant access to resources. The declarations of trusts_with, trusts, and grants define relations between entities and resources: trusts_with is true if one entity trusts another with specific resource; trusts is true if one entity trusts the assertions of another.

The transitive_trusts, transitive_trust, and will_grant predicates define how trust is established and the conditions for granting access to a resource. First, transitive_trust simply defines and names a transitive property for trust relationships; transitive_trusts_with defines a relation such that if a trusts b and b trusts c with r, then a trusts c with r. Finally, will_grant defines a property asserting when one entity will grant access to a resource.

The way these predicates establish trust and grant resource access is relatively simple. If a resource r is requested from m by n, and m trusts n with that resource, access is granted. Establishing that m trusts n with the resource may result from first-hand knowledge. However, if m trusts an entity p that trusts n with r, then m also trusts n with r. Trust is transitive, allowing the formation of chains from an initial trusted source. This is an exceptionally naive trust model, but will suffice for this case study.

Note that none of the defined properties is asserted in the package. The properties give names to relationships, but do not assert those relationships for any particular entities. For the properties to hold, they must be asserted as terms in models that use the network_entities package.

Access Control Requirements Model

The access control requirements model defines a collection of security constraints that the network infrastructure must satisfy while providing services. It defines system-level constraints on the function of every infrastructure element in the network. While the functional requirements define what the network must do, access control requirements define what the network must not do. In this sense, access control requirements define safety conditions.

Figure 20.3 defines the access control requirements model. A component representation is chosen over a facet representation to allow inclusion of usage assumptions and correctness conditions. Usage assumptions explicitly document assumptions made when defining requirements. In effect, they define conditions that the user must accept or satisfy to use this system. Implications define correctness conditions over definitions. Thus, they support specification of theorems that should hold as a result of assumptions and definitions. If the theorems do not hold, then something about the specified requirements is incorrect.

Example 20.3. Basic access control requirements model.

use network_entities();
component networkSecurity()::static is
begin
  assumptions
   forall(a::id | trusts(a,trusted_id));
  end assumptions;
  definitions
  end definitions;
  implications
 // if a grants b r, then a must trust b with r
 (forall a::id |
  (forall b::id |
   (forall r::resource | grants(a,b,r) => trusts_with(a,b,r))));
  end implications;
end component networkSecurity;

The only assumption made is that every entity trusts trusted_id. This trusted entity forms the root of all trust relationships in this system. It also serves as a potential single point of failure. If trusted_id is compromised, then the entire network may fail. Making the assumption that all entities trust trusted_id prevents this case from occurring in this analysis. In essence, the assumption is that trusted_id will never be untrusted.

The requirements model is quite simple and asserts only that if a resource is granted to an entity, then the granter must continue to trust the grantee with the resource as long as the grant is valid. If grants(a, b, r) holds, then trusts_with(a, b, r) must also hold or requirements are violated. If grants(a, b, r) does not hold, then the implication is immediately true. The static domain is used because there is no need to represent change, as requirements will be defined as an invariant that must hold in all states. Note that if trusts_with(a, b, r) holds, it is not necessary for a to grant r to b.

Note that the requirements model uses an implication to assert its correctness condition, rather than making it a requirement. This is a stylistic choice concerning the way errors will discovered. Making the condition an implication asserts that the condition must be provable from requirements. Thus, if requirements violate the condition, the inconsistency will be detected when the condition is checked. If the condition were asserted as a requirement, the inconsistency exists in the specification immediately and can be detected without checking the implication. Unfortunately, this implies that the inconsistency could be used to verify other conditions if it is not recognized. For this reason, an implication is used rather than a definition term.

Functional Requirements Model

Modeling constraints outside the context of required functionality is not useful. For example, it is quite possible to define a secure network by simply not providing connectivity. If no resources are accessed and no resources are available, the network meets ideal security requirements. Of course, this is not desirable — a network without connectivity does not meet even its basic functional requirements. Thus the functional requirements model defines a minimal set of system requirements, that must be achieved in the content of constraints.

The functional requirements model defines desired functionality from the perspective of the user. It is parameterized over the identity of the sender, allowing the analysis of requirements from the perspective of a sender, behind the firewall or outside the firewall. Specifically, the send_as design parameter can be internal, external, or another id that indicates where the requester is. Thus, correctness analysis can be performed from several perspectives. Figure 20.4 defines resources that the portable computer user would ideally like to have available.

Example 20.4. Basic functional requirements.

use network_entities();
component networkFunction
    (send_as::design id;
     i::input message;
     o::output message)::state_based is
  eventually(f::boolean)::boolean is
   not (f)implies eventually(f'),
begin
  assumptions
  end assumptions;
  definitions
    eventually(o=request(send_as,private,private_server));
    eventually(o=request(send_as,private,public_server));
  end definitions;
  implications
    case send_as of
      {internal} -> eventually(i=grant(private))
                    and eventually(i=grant(public))
      {external} -> eventually(i=grant(public))
    end case;
  end implications;
end facet networkFunction;

Infrastructure Models

Having declarations of entities and resources, and a requirements model defining system requirements, network infrastructure models must be defined. Specifically, an internal infrastructure representing the work environment, an external infrastructure representing the home and public infrastructure, and a firewall environment represent the firewall behavior will now be defined.

Each infrastructure model defines various implementations of functionality that must satisfy system-level constraints. Thus, infrastructure models must satisfy access control requirements while defining their own requirements. This will be modeled by defining trust properties for each network environment and then conjuncting system-level requirements with each environment model.

The private infrastructure defined in Figure 20.5 represents the network environment within the organization that controls computing resources private_server, and public_server, defined earlier. It represents the world behind the organization’s firewall. All infrastructure models use the state_based domain because trust relationships must change. The static domain is more appropriate for requirements because they cannot change. In effect, they define invariants on the state of network infrastructure elements.

Example 20.5. Private network infrastructure.

use network_entities();
component networkPrivateInfrastructure
  (i::input message; o::output message;
   self::design id)::state_based is
begin
  assumptions
    trusted_firewall: trusts(self,firewall)
        and forall(x:id | trusts(firewall,x) =>
                      trusts_with(firewall,x,private_server));
    trusted_internal: trusts_with(self,internal,private_server)
                      and trusts_with(self,internal,public_server);
    trusted_external: trusts_with(self,external,public_server);
  end assumptions;
  definitions
    // incoming request
    request_incoming: request?(i) and a(i)=self =>
       if trusts_with(self,b(i),r(i))
          then o'=grant(self,b(i),r(i))
               and grants(self,b(i),r(i))'
          else o'=revoke(self,b(i),r(i))
               and not(grants(self,b(i),r(i)))'
       end if;

    // incoming trust and distrust.
    trust_incoming: trust?(i) => trusts(a(i),b(i))'=true;
    distrust_incoming: distrust?(i) and trusts(a(i),b(i)) =>
       trusts(a(i),b(i))'=false;
    trust_maintenance: trusts(a,b) and not(i=distrust(a,b)) =>
       trusts(a,b)'=true;

    // maintain grants
    grant_maintenance: if grants(self,b,r)
                          and not(trusts_with(self,b,r))
         then o'=revoke(self,b,r) and not(grants(self,b,r))'
         else grants(self,b,r)'
       end if;
  end definitions;
  implications
  end implications;
end component networkPrivateInfrastructure;

The private infrastructure makes three trust assumptions: (i) it trusts the firewall and it trusts who the firewall trusts with the private server, (ii) it trusts internal entities with both servers, and (iii) it trusts external entities with only the public server. These three assumptions allow it to grant access to both servers to internal requesters and only the public server to external requesters. The firewall is trusted, thus the firewall can act as an arbiter for establishing trust.

The requirements model consists of five terms that represent processing incoming requests, processing incoming trust assertions and de-assertions, and maintaining trust and existing resource grants over state change. The first, request_incoming, processes an incoming resource request. If the node trusts the requester with the resource, a grant message is issued and the grant is maintained locally. If the node does not trust the requester, the grant is revoked and the local record of the grant is negated. It is here that we first see the use of state_based to move from one system state to the next, based on grants and revocations.

The trust_incoming and distrust_incoming terms are similar to the request_incoming term. They react to a specific input message and revise trust relations in the next state. The trust_maintenance term defines when trust is maintained over state change. When an entity is trusted in the current state, it is trusted in the next state unless a message has arrived that revokes that trust.

Finally, the grant_maintenance term maintains valid resource grants from one state to the next. It states that if the trust chain is broken and cannot be re-established, then the grant is revoked. Otherwise, the grant is kept in place in the next state. The system is thus required to recheck trust and grant relationships each time the system changes state.

Example 20.1. Internal Request for the Private Server

As an example of how the infrastructure models operate, we can examine the scenario where an internal agent requests the private server. To initiate the request, the following message arrives at the private infrastructure’s input:

request(private, internal, private_server)

Assuming that self=private, the message will cause the request_incoming term to be instantiated as follows:

request_incoming: true and self=self =>
       if trusts_with(self, internal, private_server)
          then o'=grant(self,internal,private_server)
               and grants(self, internal, private_server)'
          else o' =revoke(self,internal,private_server)
               and not(grants(self, internal, private_server))'
end if;

The implication condition is true and the assumption trusted_internal makes the if condition true. Therefore the private infrastructure sends the message:

 grant(private, internal, private_server)

and asserts:

 grants(self, internal, private_server)

in the next state.

Example 20.2. External Request for the Private Server

As an example of how the infrastructure models operate, we can examine the scenario where an external agent requests the private server. To initiate the request, the following message arrives at the private infrastructure’s input:

request(private,external,private_server)

Assuming that self=private, the message will cause the request_incoming term to be instantiated as follows:

request_incoming: true and self=self =>
       if trusts_with(self, external, private_server)
          then o'=grant(self,external,private_server)
               and grants(self,external, private_server)'
          else o' =revoke(self,external,private_server)
               and not(grants(self, external, private_server))'
end if;

The implication condition is true. However, the if condition cannot be verified — it is neither true nor false. Therefore, no message is sent and nothing is asserted in the next state. The request is ignored. If the internal infrastructure knew it did not trust the external requester, then a revoke message would have been sent.

Example 20.3. Establishing Trust with an External Requester

As a final example of the infrastructure at work, assume that an external request for the private server is made and the firewall trusts the external requester. This scenario is modeled by the following two messages:

trust(firewall,external)
request(private,external,private_server)

The first message is processed by process_trust and establishes that firewall trusts external. Combined with the assumption that private trusts firewall, it can be established that private trusts external. This would represent a situation where a VPN link is established between the firewall and the external requester.

Now the request message is processed as in the previous example. The distinction is that now it can be established that the external requester can be trusted with the private server: private trusts firewall and trusts anyone firewall trusts with private_server. The if condition is thus satisfied and the grant is processed as it was in the first example.

The firewall component in Figure 20.6 is nearly identical to the networkPrivateInfrastructure model, with the exception that it assumes initial trust only in the private infrastructure. It does not trust the external infrastructure in any way initially. Incoming requests are handled in exactly the same manner, except that initially the firewall controls no resources. Thus, requests for resources to the firewall will go unanswered. The firewall is perfectly capable of establishing trust with other agents — its primary function.

Example 20.6. Firewall infrastructure.

use network_entities();
component firewall
  (i::input message; o::output message;
   self::design id)::state_based is
begin
  assumptions
    trusted_firewall: trusts(self,private);
  end assumptions;
  requirements
     // incoming request
     request_incoming: request?(i) and a(i)=self =>
        if trusts_with(self,b(i),r(i))
           then o'=grant(self,b(i),r(i))
                and grants(self,b(i),r(i))'
           else o'=revoke(self,b(i),r(i))
                and not(grants(self,b(i),r(i)))'
        end if;

     // incoming trust and distrust. Can assert trust between
    // any nodes
    trust_incoming: trust?(i) => trusts(a(i),b(i))'=true;
    distrust_incoming: distrust?(i) and trusts(a(i),b(i)) =>
       trusts(a(i),b(i))'=false;
    trust_maintenance: trusts(a,b) and not(i=distrust(a,b)) =>
       trusts(a,b)'=true;

    // maintain grants
    grant_maintenance:if grants(self,b,r)
                         and not(trusts_with(self,b,r))
         then o'=revoke(self,b,r)and not(grants(self,b,r))'
         else grants(self,b,r)'
       end if;
  end requirements;
  implications
  end implications;
end component firewall;

The public infrastructure defined in Figure 20.7 differs from the private infrastructure in that it trusts everyone, but it has no resources to grant. Thus, the trust relationships are not particularly useful.

Example 20.7. Public network infrastructure.

use network_entities();
component networkPublicInfrastructure
  (i::input message; o::output message;
   self:: design id)::state_based is
begin
  assumptions
    trusts_all: forall(x::id | trusts(self,x));
  end assumptions;
  definitions
    // incoming request
    request_incoming: request?(i) and a(i)=self =>
       if trusts_with(self,b(i),r(i))
          then o'=grant(self,b(i),r(i))
               and grants(self,b(i),r(i))'
          else o'=revoke(self,b(i),r(i))
               and not(grants(self,b(i),r(i)))'
       end if;

    // incoming trust and distrust.
    trust_incoming: trust?(i) => trusts(a(i),b(i))'=true;
    distrust_incoming: distrust?(i) and trusts(a(i),b(i)) =>
       trusts(a(i),b(i))'=false;
    trust_maintenance: trusts(a,b) and not(i=distrust(a,b)) =>
        trusts(a,b)'=true;

    // maintain grants
    grant_maintenance: if grants(self,b,r)
                          and not(trusts_with(self,b,r))
         then o'=revoke(self,b,r) and not(grants(self,b,r))'
         else grants(self,b,r)'
       end if;
  end definitions;
  implications
  end implications;
end component networkPublicInfrastructure;

Composing System Models

Figure 20.8 defines the composition of the functional requirements model, the access control requirements model, and either the public or private infrastructure models. The parameter public selects the infrastructure model. Here inInfrastructure (true) composes the network functionality and security constraint swith the public infrastructure model. In contrast,inInfrastructure(false) composes the network functionality and security constraints with the private infrastructure model. Recall that the requirements model defines different requirements based on the location of the requesting entity.

Example 20.8. Composite system model.

use network_entities();
use static_state_based();
facet inInfrastructure(public:: design boolean) :: state_based is
  m::message;
begin
  infra: if public=true
     then networkFunction(external,m,m)
     else networkFunction(internal,m,m)
  end if;
  public: networkPublicInfrastructure(m,m,public);
  firewall: firewall (m,m,firewall);
  private: networkPrivateInfrastructure(m,m,private)
    * static_state_based.gamma(networkSecurity());
end facet inInfrastructure;

The default interaction between state_based and static domains moves the requirements specification to the state_based domain. It is then composed with the private infrastructure model to define constraints on how resources are accessed. In effect, the requirements model defines a state invariant over all states. These requirements behave like assertions, monitoring the behavior of the infrastructure.

What this specification does not concern itself with is just as important — potentially more important than what is specified. No attempt is made to coordinate messages on m, as this is outside the scope of the analysis being performed. No attempt is made to model timing issues or to model how authentication is performed. This model deals quite simply with the establishment and maintenance of trust relationships and their effects on resource access. No attempt is made to deal with implementation issues. As such, this is purely a requirements model.

Constructing the Analysis Models

The inInfrastructure model defines a configurable model that defines and composes functional models, constraints, and implementation infrastructure. Analysis of these models can be achieved using a number of techniques by moving the inInfrastructure model to a domain that supports analysis. The state_based model can be moved to a simulation domain, much like previous examples. However, this would require refinement to the discrete_time domain. More appropriate here is analysis involving model checking or theorem proving, due to the logical nature of the specifications.

Constructing the analysis model uses the same type of functor as for the power-aware example. Here, a state_based model is moved to a model-checking domain for analysis:

state_based_mc.gamma(inInfrastructure(true));

The resulting model can be analyzed using model-checking techniques to assure that the invariant is met in each state and to ensure that functional requirements involving sequences of states are satisfied.

Wrap Up

This case study represents a significant departure from digital system design and looks exclusively at requirements analysis. Previous studies examine the impacts of local design decisions on system-level behavior. Here, exploring system requirements without consideration for implementation technologies is the objective. Regardless, the impacts of local design decisions are explored in the context of system requirements.

The local design decisions explored in this case study are requirements placed on different network environments and components. Access control requirements can be varied, trust models can be altered or changed, and even models for establishing trust in the system can be changed. Here the local decisions are not implementation related but are instead requirements related.

What this case study demonstrates is a capability for modeling requirements sets before an implementation direction is chosen. System design folklore suggests that the cost of fixing an error increases by an order of magnitude for each design cycle entered prior to discovery of the error. The only thing questionable about this approximation is whether the cost should increase by only a single order of magnitude. Thus, the value of exploring requirements to detect errors and optimize requirements prior to system implementation cannot be overstated.

 

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.119.132.123