A self-protecting control application base on microserevice
idea paper.pdf
A Self-protecting Control Application for IIoT
Gabriele Gualandi Department of Computer Science Sapienza University of Rome, Italy
Emiliano Casalicchio Department of Computer Science
Sapienza University of Rome, Italy and BTH, Sweden [email protected]
Abstract—Industrial control applications are today software defined and networked, making them even more vulnerable to cyber-attacks. Hence there is the need to investigate new solutions that are secure by design. In this paper, we propose a self-protecting architecture for a control application suitable for Industrial Internet-of-Things deployments. The proposed solution, by using redundancy, is capable of self-detecting cyber- attacks to its logic and to autonomously activate mitigation actions.
Index Terms—Intrusion detection, Redundancy, Systems archi- tecture, Smart factory, Control systems, Self-protecting systems
I. INTRODUCTION
This paper investigates the design of a self-protecting in-
dustrial control application conceived to be deployed on an
Industrial Internet-of-Things (IIoT) network, the backbone of
the smart factory [1]–[3].
To protect an IIoT network against cyber-attacks is ex-
tremely important and challenging. As described in [4], many
are the cyber-incidents due to malicious attacks, for example: a
worm named Zotob in 2005 disabled 13 of Daimler Chrysler’s
car manufacturing plants; Stuxnet in 2010; a sophisticated
instance of a RAT known as Duqu that in 2011 infected control
systems in Europe, Asia and North Africa; Havex/Dragonfly
that in 2014 was used to target control system used in the
energy sector. Moreover, because the complexity of an IIoT
network and the huge number of controllers in an industrial
setting, a human-assisted detection, and mitigation approach
is impractical.
For all the above reasons, in this paper, we propose a model
and the software architecture for a self-protecting control
application capable to autonomously detect cyber-attack and
to mitigate their effects.
The paper is organized as in what follow. Section 2 defines
the problem and describe, at a high level, the proposed
solution. Section 3 presents a model and the architecture for a
verifiable controller. The implementation of the deployment of
the self-protecting controller and the usage of a deployment-
based mitigation mechanism is described in section 4. Finally,
Section 5 concludes the paper.
II. PROBLEM DEFINITION AND PROPOSED SOLUTION
In this paper, we address the problem of detection and
mitigation of cyber-attacks targeting the logic of a Control
Application (CA). As a solution, we propose a self-protecting
CA architecture, based on an autonomous Intrusion Detection
Controller
Controller Replica
Controller (healed)
SystemIntrusion Detection
Mitigation
and
Prevention
Mechanism
Cloud Hypervisor
destroy
create
Platform
alert
Fig. 1. High-level representation of the proposed architecture.
System (IDS) and on a self-mitigation mechanism, that are
architected as in Figure 1. The detection of attacks is based
on a replica of the controller in the field. We assume that
cyber-attacks cannot compromise the replica, and therefore the
outputs of the replica are used as a reference for the correct
control logic. The detection mechanism compares the outputs
(i.e., actuation commands) of the replica with the output of the
controller in the field: any discrepancy may be interpreted as
the consequence of a cyber-attack. This behavior-based detec-
tion approach makes the IDS autonomous. In order to maintain
the state of controller consistent with the state of the replica,
the latter is built and continuously updated by the sequence
of control messages (i.e., sensing and actuation) exchanged
between the controller and the system under control.
In the case of detection of an attack, the mitigation mech-
anism autonomously re-deploy a new instance of the con-
troller in the field. The use of virtualization technologies, like
container, makes that operation possible in a reduced time.
The new instance (i.e., the healed controller in Figure 1) is
provisioned with a validated state.
Our solution assumes the IDS, and hence the replica is safe
from attacks, for example, it is executed in a secure remote
location like a private cloud platform. That prevents to verify
an actuation message before it is provisioned to the system,
because this introduces a delay of hundreds of milliseconds
within the control loop, possibly decreasing the performance
(or even stability) of the control system. Hence, our choice is
to perform an asynchronous detection.
III. MODEL AND ARCHITECTURE
A. Model of a verifiable Control application
We define a model for a controller representing a broad
spectrum of control schemes. Usually, a CA consists of two
components: a data store named Control Knowledge (CK), and an executable software named Control Logic (CL). From such
152
2019 IEEE 4th International Workshops on Foundations and Applications of Self* Systems (FAS*W)
978-1-7281-2406-3/19/$31.00 ©2019 IEEE DOI 10.1109/FAS-W.2019.00046
Authorized licensed use limited to: Universita degli Studi di Roma La Sapienza. Downloaded on October 20,2020 at 14:03:11 UTC from IEEE Xplore. Restrictions apply.
Control Logic
x r
t
Control Knowledge
a
query a
r Control Logic
Control Knowledge
x
clock
a) b)
Control Application
ti notif.
notif. ti+1
Fig. 2. (a) The High level architecture of the control application. (b) The interaction between CK and CL during the i-th iteration.
generic definition, we define a model that is suitable for the
verification of the outputs of the CA, i.e., actuation commands
carried by control messages. The model is composed by three
entities: the knowledge, the algorithm, and the execution state. The knowledge k is a set of control messages which models
the data store CK. It is the history of messages produced and
possibly consumed by the CA and contains the entire raw
information available to the CA for the production of actuation
messages. A query to the CK is modeled with a function q.
The algorithm represents the stateless part of the Control Logic that is, the logic used to produce actuation commands
based on i) the notion of current time and ii) the payload of control messages (i.e., sensors or actuations).
The execution state is an abstraction we use for representing the state of the execution environment which hosts the Control
Logic. In particular, the algorithm accesses data structures
holding the current estimation of the state of the system under
control, and other control parameters (e.g., desired state). The
execution state changes as a result of the processing of the
knowledge as done by the algorithm. The state of a controller is defined as the execution state and the knowledge combined.
The production of an actuation message is a recurring oper-
ation (i.e., iteration) which timing depends on the particular communication process between the controller and the system
(i.e., event-driven or time-driven). When executed, the CL
waits for a notification which initiates an iteration. Depending
on the adopted communication process, such notification may
be triggered by the fact that new messages enter the knowl-
edge, or when a periodic cont-down expires.
During an iteration, the algorithm executes the following steps:
1) it queries CK for obtaining x ⊆ k (i.e., function q), 2) it waits for the arrival of a message carrying the notion of
current time r, 3) it uses x and r for updating the execution state and for computing the payload of an actuation message
(i.e., function c).
Fig. 2 (a) represents the Control Logic taking as inputs x, r for producing an actuation a. Fig. 2 (b) shows the interaction between CK and CL during to the i-th iteration (steps 1–3), which spans the time interval [ti, ti+1), where ti is the time in which i-th iteration begins. The state of the controller changes during an iteration. We assume that: 1) the particular query
for the knowledge performed by the algorithm (i.e., the value
of parameters for q determining the selection criteria) depends
a avq c
compare
System s k x
Controller
Intrusion
Detection q c
kv xv
Replica
Fig. 3. Interaction among the controller, the replica and the controlled system. A superscript v indicates an entity belonging to the IDS.
solely on the execution state at time ti; 2) the output a and any changes on the execution state occurring during an iteration
depend exclusively on the execution state at time ti and on the inputs x, r.
We say that two instances of a controller have the same
execution state if, for each iteration: 1) CL performs the same
query to CK; 2) CL is provided with the same inputs x, r. A controller and a replica, running in two distinct hosts,
act and communicate as shown in Fig. 3. Actuation a and sensing s messages contributes both to k and kv. Actuation messages in kv are subjected to verification. The proposed solution works depending on the assumption relative to the
synchronization of the state of the controller and the replica
(i.e., execution state and knowledge). As mentioned in the
previous section, we consider an asynchronous detection i.e.,
k and kv are fed the with the same messages at different times. There is the need to define appropriate sufficient conditions for
performing an asynchronous verification.
That conditions (C1 – C3) are obtained from a formal
model of the state of the controller and of its replica (not
described here because the limitation is space). We define
τ(m) the function providing the timestamp of a message m. Considering the i-th iteration on the controller side, we define τMi = maxm∈xi τ(m) the maximum timestamp among messages used as an input xi.
C1 The controller and the replica have the same initial
control state (i.e., respectively at time t1 and t v 1)
C2 The controller and the replica uses the same ri during the i-th iteration
C3 The controller and the replica uses the same xi during the i-th iteration (hold if C4-C6 holds)
C4 Messages enter in k and kv in the order of their timestamps
C5 The max timestamp of any set of messages x ⊆ k is unique.
C6 At the time in which q selects xv on the replica side, kv contains a message with timestamp τMi
Condition C2 is realized by attaching r to each actuation message produced by the controller, which is then provisioned
to the replica. The CK implements function q as accepting time interval Δf = (ts, te] as a parameter of the selection criteria i.e., CK selects messages with timestamp in Δf . Depending on the value of te, the CK have a different behaviour: in case te = ∞, CK serves immediately the query (unbounded query) using the currently available messages in k. On the contrary, in case te is finite the query is served immediately after a
153
Authorized licensed use limited to: Universita degli Studi di Roma La Sapienza. Downloaded on October 20,2020 at 14:03:11 UTC from IEEE Xplore. Restrictions apply.
Intrusion DetectionReckoner
Dispatcher
CK CL
SW LV CKv
CLv
NS
s
x s
a
a
a
av rv xvr
m m
xv
m
Fig. 4. Architecture of the verifiable CA and the related exchange of messages between its components.
message with timestamp te is in k (bounded query). Since the algorithm is supposed to produce an actuation command
as fast as possible after new knowledge is available, CL
produces unbounded queries. Bounded queries are used to
realize condition C6 on the replica side. In particular, LV
intercepts the queries of CLv, and substitutes the te of any unbounded query (i.e., ∞) with τMi , then it forwards the obtained bounded query to CKv.
B. Architecture
The proposed architecture is composed by the Reckoner and the Dispatcher applications, interacting with a system which offers a networked interface to its actuators and sensors (NS).
The Reckoner realizes a control action driving the state of
the NS toward a desired state specified by parameters present
in the execution state. The Dispatcher provisions the payloads
of control messages both to and from the NS. The introduced
decoupling between the control logic and the system [5] allows
performing a hot swap of the Reckoner, as foreseen by our
mitigation strategy.
As shown in the left part of Fig. 4, the Reckoner is realized
by the following service components: the Control Logic (CL), that implements the function c; the Control Knowledge (CK), a data store maintaining and exposing the knowledge k trough function q; and the Stopwatch (SW), which provides to CL the notion of current time r using its clock and produces control messages for CK. A control message m is composed of three fields: the payload, the timestamp and the type. The payload contains a value of sensor reading or actuation command.
The SW assigns the timestamp using its clock. The type
could assume the values {’sen’,’act’}. As an example, a message produced by SW at time 1.25 transporting a sensor reading with value 3.4 is: m = [[3.4], 1.25, ’sen’]. The components interact using an event-based paradigm. An event
occurs when a message (i.e., not necessarily a control message
m, but also another message, e.g., r) is produced, consumed or forwarded. At the time of the instantiation of the Reckoner,
CK contains an empty set (i.e., k = ∅) hence no actuation messages are produced. In successive time instants, a flow of
messages populate k which eventually provides the sufficient set of messages x for the computation of c.
TABLE I CLASSES OF MESSAGES
Class Attributes Description Time Double value value of time (e.g., Double) Pload Double value payload of a control message
Cmsg Pload pload Time tstamp String type
implements a control message m, type is ’act’, ’sen’ or ’par’
Notif Boolean value notifies the presence of new Cmsg SetCmsg <Set>Cmsg set a set of Cmsg (e.g., xi, ki)
Query Time start Time end
time interval used to select xi ⊆ ki in an iteration of CL
Meta Time rI Time tauM
meta-data for the verification
of an iteration of CL i.e., ri, τ M i
Alert Time tsDetect alert message caused by the fail of the verification of an ’act’ with timestamp tsDetect
IV. IMPLEMENTATION AND DEPLOYMENT
For the implementation of the proposed verifiable controller,
we adopted the microservices architecture [6] where each
microservice (i.e., CL, CK, SW, LV) is deployed on a distinct
container [7] and uses a message-based producer-consumer
model. Containers, supported by frameworks like SCONE [8],
guarantee strong isolation at the operating system level. More-
over, compared to virtual machines, containers provide a lower
communication latency between microservices running on the
same host (e.g., CL, CK, SW). Finally, containers have a small
footprint, can be executed on sensors and control boards, are
portable and fast to deploy.
A. Implementation
To simplify the description of the inter-connection among
the microservice we introduce in Fig. 5 inSize input ports and outSize output ports for each component. Inter- components communication is based on the publish/subscribe
paradigm and is implemented with a message broker like Rab-
bitMQ, where messages are instances of the classes provided
by Table I. Considering a single component, mQueueIn and mQueueOut are its in/out FIFO queues realized by message broker, each one instance of a List class offring functions readL(), remL(), writeL() for respectively reading, removing and adding the last message of the queue.
Listing 1. Pseudo-code of the execution environment exenv 1 stateVars this = new stateVars() 2 WHILE True 3 BusIO[] in = new BusIO[inSize] // empty 4 FOR i = 1 TO inSize 5 in[i] = mQueueIn.readL(i) //unconsumed in 6 BusIO[] out = new BusIO[outSize] // empty 7 Bool[] consumed = new Bool[outSize] // false 8 compFunct(this, in, out, consumed) 9 FOR i = 1 TO inSize
10 if consumed[i] == True THEN 11 mQueueIn.remL(i) // consume in 12 FOR i = 1 TO outSize 13 if NOT (out[i] == Null) THEN 14 mQueueOut.writeL(out[i]) //produce out
The behaviour of the execution environment (exenv) of each of the component is described by the routine in List-
154
Authorized licensed use limited to: Universita degli Studi di Roma La Sapienza. Downloaded on October 20,2020 at 14:03:11 UTC from IEEE Xplore. Restrictions apply.
Query
SetCmsg
Meta
1
2
3
1
2
3
4
5
6
SW
Pload
Pload
Time
Notif
Query
Cmsg
Time
Pload
τMi
ri
a
s xi
CK
1
2
1
2
CL
1
2
2
3
1
a [τMi , ri]
m
Cmsg m
1
2
3
4
5
6
LV
1
2
3
4
5
6
CKv
1
2
1
2
CLv
1
2
2
3
1 Pload Notif
Time
SetCmsg
Alert
Query
Cmsg Time
SetCmsg
System
System
Controller Intrusion Detection
Fig. 5. Message exchange among microservices. Inputs ports on the left and outputs ports on the right
ing 1. The exenv perpetually invokes a component function (compFunct, line 8) which may consume (produce) a maxi- mum of one BusIO at each of the FIFO queues connected to its input (output) ports. The internal state of the component is
maintained by variable this (line 1). Before the invocation of compFunct, elements of the array in are filled with the ”first-out” BusIO objects of their respective FIFO queues (line 5), or left null. By doing so, the exenv provides to the compFunct the less recent unconsumed messages received from other components. compFunct notifies the consumption of an input by setting the correspondent element of array
consumed = True, which is then removed by the exenv (line 11). Any BusIO object created by compFunct is passed through the array out to the exenv, which produces a message in an input FIFO queue of the destination component
(line 13).
The SW (Fig. 5 and Fig. 6) executes two tasks: i) (times- tamping task) SW consumes each Pload from IN 2,3, to produce Cmsg on OUT 4,6. Moreover, each Pload from IN 2 is also forwarded to OUT 5; ii) (iteration task) SW produces a Notif on OUT 1 which initiates an iteration, during which it produces a Meta on OUT 3. Timestamping task is performed independently from iteration task i.e., messages are always
produced for CK, LV and DA. On the contrary, iteration
task may be triggered by the consumption of Pload from timestamping task (e.g., when new sensor readings arrives,
considering an event-based communication process between
the controller and the system). A single iteration is realized
by making pass each component through a certain number
of synchronization phases, starting from phase P0. Figure 6
provides an example of an interaction diagram relative to a
single iteration, also indicating the phases of the involved com-
ponents. Assuming all components in phase P0, the controller
is idle: CL is waiting for a Notif and SW is waiting for payloads at its IN 3, 4. When at least one Pload arrives (e.g., s in Fig. 6) a Notif is produced by SW for CL, and SW enters in phase P1. Upon reiceving Notif, CL produces an unbounded Query for CK and enters in phase P1 i.e., it waits for xi. CK computes function q immediately using the currently available Cmsg, and provides the obtained xi to CL by producing a SetCmsg. Moreover, CK produces τMi for SW. This ends the role of CK for the current iteration.
When SW consumes τMi , it produces Meta for LV and ri for
CK CL SW
Query
xi τMi
ri
LV
DA
NotifP0
P1
P0
P1
P2P2
s
DS
P0
P1
s′ P0
m LV
SetCmsg
Pload
Pload
Pload
CmsgNotif
Meta
a
[τMi , ri] Time
Time
Pload a
P1
Fig. 6. Interaction diagram between components of the controller
CKv CLv LV
Query
xi
NotifP0
P1
P0
P1
P2
P2
P0
Meta SW
P1
Query
xi P3
[τMi , ri]
m′
ri avi
mCmsg
Cmsg
Fig. 7. Interaction diagram among components of the IDS.
CL, then it enters in phase P2 i.e., it waits for the actuation
payload from CL. When CL consumes xi it enters in phase P2 i.e., it waits for ri. When CL consumes ri, it updates its execution state (e.g., estimates the current state of the system),
then produces a Pload (function c) carrying a for SW, and it returns to phase P0. SW forwards a to the system, produces a Cmsg carrying a for CK and LV, then returns to phase P0. In case that additional Pload was consumed by SW during the current iteration (e.g., s′ in Fig. 6) SW enters immediately in phase P1 and produces another Notif. This continues until CL have consumed any new payload.
On the IDS side, different instances of the components CK
and CL are interfaced with the LV (Fig. 5), which offers the
same interfaces of SW, CK to CLv for realizing conditions C2,
C3. The LV constantly consumes Meta and Cmsg on IN 3,4 i.e., it forwards any Cmsg to CKv, and stores in two internal FIFO queues the consumed Meta and the Pload of the consumed actuation Cmsg. A Meta-Pload couple provided by the ”first-out” elements of the two queues is used to verify
155
Authorized licensed use limited to: Universita degli Studi di Roma La Sapienza. Downloaded on October 20,2020 at 14:03:11 UTC from IEEE Xplore. Restrictions apply.
TABLE II FUNCTIONS USED BY THE THE CONTROLLER AND IDS COMPONENTS
Int chooseIn(Cmsg[] inM,Int[] inI,Int priority) inM are two inputs (possibly Null), inI are the two correspondent input ports. chooseIn returns the first element of inI having its correspondent inM not null. In case both inM are not Null, the chosen input is determined by the value of priority. SetCmsg select(SetCmsg k, Query i) Returns a selection of Cmsg from knowledge k based on their timestamp. Selects message in interval (ts, te]. ∀m in output: (m.tstamp > i.start)AND(m.tstamp <= i.end) Bool contains(SetCmsg k, Time t) Returns True if there is a message m in k : m.tstamp == t Time maxTimeStamp(SetCmsg s) Returns the max timestamp among elements in the set s updParams(params, SetCmsg s) updates the execution state (i.e., state var params of CL) Pload calcAct(params, Time t) computes an actuation given the execution state and current time Bool compare(Pload a1, Pload a2) returns True if the two actuation payloads a1,a2 are identical, or similar enough to not raise the detection of an attack Bool nonEmpty(Set e) returns True if e (i.e., a Set or a List) is non-empty Time systemTime() returns the time value as seen by the execution environment
the same iteration. Fig. 7 provides an interaction diagram for
the replica side. By consuming a Meta-Pload couple from its internal queues, LV produces a Notif for CLv and enters in phase P1. The interaction among the components is similar
to the case of the controller in the field, but LV appears to
CLv as both the SW and CK. In particular, LV intercepts the
unbounded query of CLv and uses the Meta-Pload couple to substitute te with τ
M i , which determines a bounded query
to CKv. Differently from the case of the controller on the field,
when CKv computes q it may need to wait (i.e., to enter in phase P1) for a Mes with timestamp τMi (e.g., Mes s
′ in the Figure). The LV forwards to CLv the xi as received from CK
v,
and it provides to CLv the Time ri taken from the current Meta-Pload couple. In phase P3 LV waits for the actuation Pload of CLv, which is then compared with the Pload of the Meta-Pload couple. The result of the comparison may produce a message in OUT 4 which triggers the mitigation mechanism.
Table II describes functions used by the components.
updParams and calcAct together implement function c. Function chooseIn realizes condition C5. Table III describes the variables defining the internal state of the components. For
example, CL is triggered by SW to consume new messages
depending on the values of the state variable mRecC and mRecP. mRecC is used by CL to implement unbounded queries to the control knowledge. metas and acts are FIFO queues internal to LV which provide the Meta-Pload couples used for the detection. We report the pseudo-codes of
the components functions in Listings 2– 5.
B. Deployment-based mitigation mechanism
The usage of Cloud technologies, e.g., Container as a
Service platforms [9] and orchestration layers [10] enables
TABLE III STATE VARIABLES AND RELATED COMPONENTS
C. State Var Description SW CL CK LV
Int phase Used for coordination within a single iteration, i.e., production of a single actuation Cmsg.
CK SetCmsg k entire history of Cmsg k CL SetCmsg x Set of Cmsg for current iteration CK Query pendQ query pending for current iteration SW CL
Time mRecC greatest timestamp among Cmsg ever consumed by CL
SW Time mRecP greatest timestamp among Cmsg ever produced by SW
SW Int priority value switched to serve ’sen’ and ’act’ messages equally. Init as 2
CL params data-structures for the parameters e.g., desired state, estimated state of the system
LV List<Meta> metas List<Pload> acts List<Time> tstamps
FIFO queues used for the verification of actuation messages and generation of alerts
to actuate a cyber-attack mitigation strategy based on re-
deployment of a compromised CA application.
Our proposed mitigation strategy is traduced into container
management operations, i.e., to stop, deploy and start the im-
ages of the microservice(s) involved in an attack. Considering
a set of verified messages kv with associated meta-data on the replica side, there are the following steps for the creation of
a healed controller:
1) Provisioning of the knowledge: new instances of the
components CL, CK, and LV connected as a replica.
LV is provisioned with kv and with the metadata. 2) Provisioning of the execution state: as described in the
previous Section, LV interacts with CL until LV con-
sumes all of its Meta-Pload couples. The actuation messages produced by CL are discarded by LV, as we
are only interested in updating the execution state of CL.
3) Connection with the system: CL and SW are reconfig-
ured to be connected as a controller in the field (Fig.
5), and to be connected with the Dispatcher. LV is
destroyed.
The re-deployment of the containers can be done on the same
cluster node, or on a new and clean node to prevent a new
attack in the short term. Typically, such re-deployment take a
few seconds (2-5) to start its execution.
Listing 2. Pseudo-code of the compFunct CK 1 IF NOT(in[1] == Null) 2 add(this.k,in[1]) 3 consume[1] = True 4 SetCmsg x = Null 5 IF this.phase == 0 6 IF NOT(in[2] == Null) 7 Query tempQ = new Query(in[2]) 8 IF tempQ.end == Double.MAXVALUE //unbounded 9 x = select(this.db, tempQ)
10 ELSE // bounded query (from LV) 11 this.phase = 1 12 this.pendQ = new Query(tempQ) 13 consume[2] = True 14 ELSE // phase is 1
156
Authorized licensed use limited to: Universita degli Studi di Roma La Sapienza. Downloaded on October 20,2020 at 14:03:11 UTC from IEEE Xplore. Restrictions apply.
15 IF contains(this.k,this.pendQ.end) 16 x = select(this.k, this.pendQ) 17 this.phase == 0 18 IF nonEmpty(x) 19 out[1] = maxTimeStamp(x) // tauM 20 out[2] = x
Listing 3. Pseudo-code of the compFunct SW 1 Time tNow = systemTime() 2 Mes[] arrMes = [in[2],in[3]] 3 Int fIn = chooseIn(arrMes,[2,3],this.priority) 4 IF NOT (fIn == Null) 5 String type = ’’ 6 IF fIn == 2 7 this.priority = 3 // switches priority 8 type = ’act’ 9 IF this.phase == 2
10 out[5] = new Pload(in[fIn].value) 11 this.phase = 0 12 ELSEIF fIn == 3 13 this.priority == 2 // switches priority 14 type = ’sen’ 15 Cmsg msg = new Cmsg(in[fIn].value,tNow,type) 16 consumed[fIn] = True 17 out[4] = new Cmsg(msg) // to LV 18 out[6] = new Cmsg(msg) // to CK 19 IF String.equals(kind,"sen") 20 this.mRecP = tNow 21 IF (this.phase == 0) AND (this.mRecC < this.mRecP) 22 out[1] = new Notif() // Starts iteration 23 this.phase = 1 24 ELSEIF (this.phase == 1) AND NOT(in[1] == Null) 25 Time tauM = new Time(in[1]) 26 consumed[1] = True 27 out[2] = new Time(tNow) // sends time to CL 28 out[3] = new Meta(tNow,tauM) // to LV 29 IF tauM > this.mRecC THEN 30 this.mRecC = tauM // CL vision over k 31 this.phase = 2
Listing 4. Pseudo-code of the compFunct CL 1 IF (this.phase == 0) AND (NOT(in[1] == Null)) 2 out[2] = new Query(this.mRecC,Double.MAXVALUE) 3 consumed[1] = True 4 this.phase = 1 5 ELSEIF (this.phase == 1) AND (NOT(in[3] == Null)) 6 this.x = new SetCmsg(in[3]) 7 consumed[3] = True 8 this.phase == 2 9 IF nonempty(this.x)
10 this.mRecC = maxTimeStamp(x) 11 ELSEIF (this.phase == 2) AND (NOT(in[2] == Null)) 12 IF nonempty(this.x) 13 updParams(this.params, this.x) 14 Time tNow = new Time(in[2]) 15 consumed[2] = True 16 out[1] = calcAct(this.params, tNow) 17 this.phase = 0
Listing 5. Pseudo-code of the compFunct LV 1 IF NOT (in[3] == Null) // consume metas 2 this.metas.addL(new Meta(in[3])) 3 consumed[3] = True 4 IF NOT (in[4] == Null) // forward cmsg 5 out[5] = new Cmsg(in[4]) 6 IF String.equals(in[4].type,’act’) 7 this.acts.addL(new Pload(in[4].pay)) 8 this.tstamps.addL(new Time(in[4].tstamp)) 9 consumed[4] = True
10 IF this.phase == 0
11 IF nonempty(this.meta) // starts iteration 12 out[1] = new Notif() 13 this.phase = 1 14 ELSEIF (this.phase == 1) AND (NOT(in[2] == Null)) 15 Time ts = new Time(in[2].start) 16 consumed[2] == True 17 Time te = new Time(this.meta.readL().tauM) 18 out[6] = new Query(ts, te) 19 this.phase = 2 20 ELSEIF (this.phase == 2) AND (NOT(in[6] == Null)) 21 out[3] = new SetCmsg(in[6]) \\ sends x 22 consumed[6] == True 23 out[2] = new Time(this.metas.readL().rI) 24 this.phase = 3 25 ELSEIF (this.phase == 3) AND (NOT(in[1] == Null)) 26 Bool valid = compare(in[1],this.acts.readL()) 27 consumed[1] = True 28 if NOT valid \\ Alert 29 out[4] = new Alert(this.tstamps.readL()) 30 this.metas.remL() 31 this.acts.remL() 32 this.tstamps.remL() 33 this.phase == 0
V. CONCLUDING REMARKS
In this paper, we propose a novel architecture of a self-
protecting application in which the control logic is verifiable
by design using a replica. That allows cyber-attack detection.
The controller works asynchronously to the verification pro-
cess, which is an essential feature for avoiding the introduction
of a remarkable delay in the control loop. The state of the controller is defined, and sufficient con-
ditions for its synchronization with the state of a replica are
implemented.
ACKNOWLEDGMENT
Founded by Competence center Cyber 4.0, MISE. The work of E.Casalicchio is partially founded by KKS grant n.20140032, SE.
REFERENCES
[1] H. S. Kang, J. Y. Lee, S. Choi, H. Kim, J. H. Park, J. Y. Son, B. H. Kim, and S. Do Noh, “Smart manufacturing: Past research, present findings, and future directions,” International Journal of Precision Engineering and Manufacturing-Green Technology, vol. 3, no. 1, pp. 111–128, 2016.
[2] X. Xu, “From cloud computing to cloud manufacturing,” Robotics and Computer-Integrated Manufacturing, vol. 28, no. 1, pp. 75 – 86, 2012.
[3] J. Lee, B. Bagheri, and H.-A. Kao, “A cyber-physical systems archi- tecture for industry 4.0-based manufacturing systems,” Manufacturing Letters, vol. 3, pp. 18 – 23, 2015.
[4] N. Tuptuk and S. Hailes, “Security of smart manufacturing systems,” Journal of Manufacturing Systems, vol. 47, pp. 93 – 106, 2018.
[5] R. Langmann and M. Stiller, “Cloud-based industrial control services,” in Online Engineering & Internet of Things, M. E. Auer and D. G. Zutin, Eds. Cham: Springer International Publishing, 2018, pp. 3–18.
[6] C. Richardson, Microservices Patterns. MEAP, 2018. [7] D. Merkel, “Docker: Lightweight Linux containers for consistent devel-
opment and deployment,” Linux J., vol. 2014, no. 239, Mar. 2014. [8] S. Arnautov, B. Trach, F. Gregor, T. Knauth, A. Martin, C. Priebe,
J. Lind, D. Muthukumaran, D. O’Keeffe, M. L. Stillwell, D. Goltzsche, D. Eyers, R. Kapitza, P. Pietzuch, and C. Fetzer, “Scone: Secure linux containers with intel sgx,” ser. Proceedings of the 12th USENIX Con- ference on Operating Systems Design and Implementation, Savannah, GA, USA, 2016.
[9] N. Kratzke and R. Peinl, “Clouns-a cloud-native application reference model for enterprise architects,” in Enterprise Distributed Object Com- puting Workshop (EDOCW), 2016 IEEE 20th International. IEEE, 2016, pp. 1–10.
[10] B. Burns, B. Grant, D. Oppenheimer, E. Brewer, and J. Wilkes, “Borg, omega, and kubernetes,” ACM Queue, vol. 14, pp. 70–93, 2016.
157
Authorized licensed use limited to: Universita degli Studi di Roma La Sapienza. Downloaded on October 20,2020 at 14:03:11 UTC from IEEE Xplore. Restrictions apply.
thesis.md
Topic(ASIMOV): a Self-protecting Control Application based on Microserevice 1) Intruduction - here you introduce the topicc addressed in the thesis and you present the thesis outline. The introduction is not very technical so you can mention about industry 4.0, the cyber security issues and the need for ASIMOV. 2) The research Problem - here you describe the research problem addressed (introduce some Cyber attacks, cloud computing, smart factories technology) 2.1) the ASIMOV approach 2.2) Related work: here you summarize the related work(related technology like rabbitmq as message broker in system, python code, sub-publishing method etc) 3) Microserevice architecture design for ASIMOV here you describe the microservice based design of asimov. You can first introduce the microservicce concept and then present the design of the ASIMOV architecture 4) ASIMOV implementation here you describe the implementation. 4.1) First you present the big picture, 4.2) then you describe the technology used and (docker,nameko,rabbitmq etc) 4.3) finally the detailed implementation 5) Experimental results here you describe 5.1) the experimental setting and 5.2) the planned experrimentes 5.3) the results obtained 6) Conclusion
python_asimov-master.zip
python_asimov-master/.idea/ASiMOV.iml
python_asimov-master/.idea/inspectionProfiles/profiles_settings.xml
python_asimov-master/.idea/misc.xml
python_asimov-master/.idea/modules.xml
python_asimov-master/.idea/vcs.xml
python_asimov-master/.idea/workspace.xml
1590356903317 1590356903317
python_asimov-master/CK/CK.py
from nameko.events import EventDispatcher, event_handler from Classpack import Cmsg, SetCmsg, Query, Meta, dispatch_test phase = 0 k = SetCmsg() pendQ = Query(None, None) km = [] class CK: name = "CK" # phase = 0 # k = SetCmsg() # pendQ = Query(None, None) # # FIFO of Meta maintained only in CKv and used only for state migration # km = [] dispatch = EventDispatcher() @event_handler("SW", "Cmsg to CK") def receiveCmsg(self, payload): print("###############") print("received message from SW, event type Cmsg to CK") print(payload) global k k.add(Cmsg(payload['a_Pload'], payload['a_Time'], payload['a_Type'])) # cmsg_a = self.k.a_set[0] # print("received message from SW, event type Cmsg to CK") # print("recevied pload:", str(cmsg_a.a_Pload)) # print("recevied time:", str(cmsg_a.a_Time)) # print("recevied Type:", str(cmsg_a.a_Type)) @event_handler("CL", "Query to CK") def receiveCLQuery(self, payload): print("###############") print("received message from CL, event type Query to CK") print(payload) global pendQ, phase pendQ = Query(payload['time_start'], payload['time_end']) # in CA the query is unbounded from CL phase = 2 print("current phase", phase) x = self.select() # for i in x.a_set: # print(i.a_Type) # print(i.a_Time) # print(i.a_Pload) # print(x.countType(u'sen')) if (x.countType('sen') + x.countType('par')) != 0: dispatch_test("max timestamp to SW", x.maxTimestamp()) dispatch_test("query result to CL", x) self.dispatch("max timestamp to SW", x.maxTimestamp()) self.dispatch("query result to CL", x.ObjToJson()) @event_handler("LV", "Query to CK") def receiveLVQuery(self, payload): print("###############") print("received message from LV, event type Query to CK") print(payload) global pendQ, phase pendQ = Query(payload['time_start'], payload['time_end']) phase = 1 if self.contains(): x = self.select() if x.a_set: dispatch_test("query result to CLv", x) self.dispatch("query result to CLv", x.ObjToJson()) def select(self): x = SetCmsg() global k, pendQ for i in k.a_set: if pendQ.time_start < i.a_Time <= pendQ.time_end: x.add(i) return x def contains(self): global k, pendQ for i in k.a_set: if i.a_Time == pendQ.time_end: return True return False
python_asimov-master/CK/CK.pyc
python_asimov-master/CK/Classpack.py
class Cmsg: a_Pload = None a_Time = None a_Type = None def __init__(self, a_mes, a_time, a_type): self.a_Pload = a_mes self.a_Time = a_time self.a_Type = a_type class SetCmsg: a_set = [] def __init__(self): self.a_set = [] def add(self, Cmsg): if Cmsg not in self.a_set: self.a_set.append(Cmsg) def countType(self, typename): j = 0 for i in self.a_set: if i.a_Type == typename: j+=1 return j def maxTimestamp(self): maxtime = 0 for i in self.a_set: if i.a_Time > maxtime: maxtime = i.a_Time return maxtime def ObjToJson(self): l = [] for i in self.a_set: l.append(i.__dict__) return l def JsonToObj(self, l): for i in l: self.a_set.append(Cmsg(i['a_Pload'], i['a_Time'], i['a_Type'])) class Query: time_start = None time_end = None def __init__(self, s, e): self.time_start = s self.time_end = e class Meta: time_rI = None time_tauM = None def __init__(self, rI, tauM): self.time_rI = rI self.time_tauM = tauM def dispatch_test(event_type, payload): print("event_type:", event_type) print("payload_type:", type(payload)) print(payload) if __name__ == '__main__': S = SetCmsg() dic = {u'a_Time': 1593087116.986699, u'a_Type': u'sen', u'a_Pload': 2962364.3205259433} c = Cmsg(dic['a_Pload'], dic['a_Time'], dic['a_Type']) S.add(c) c = Cmsg(1593087116.986699, 2962364.32052594, u'sen') S.add(c) a = S.ObjToJson() print(a) ss = SetCmsg() ss.JsonToObj(a) print(ss.a_set[0].a_Pload) dispatch_test("s","ssss")
python_asimov-master/CK/Classpack.pyc
python_asimov-master/CK/Dockerfile
FROM python:3.6 # 设置工作目录 RUN mkdir -p /usr/src/CK WORKDIR /usr/src/CK # 安装依赖 RUN pip install nameko # 添加应用 ADD . /usr/src/CK # 运行服务 CMD nameko run CK --broker amqp://guest:[email protected]
python_asimov-master/CKv/CKv.py
from nameko.events import EventDispatcher, event_handler from Classpack import Cmsg, SetCmsg, Query, Meta, dispatch_test phase = 0 k = SetCmsg() pendQ = Query(None, None) km = [] class CK: name = "CKv" # phase = 0 # k = SetCmsg() # pendQ = Query(None, None) # # FIFO of Meta maintained only in CKv and used only for state migration # km = [] dispatch = EventDispatcher() @event_handler("LV", "to CKv of IDS") def receiveCmsg(self, payload): print("###############") print("received message from LV, event type Cmsg to CKv") print(payload) global k k.add(Cmsg(payload['a_Pload'], payload['a_Time'], payload['a_Type'])) # cmsg_a = self.k.a_set[0] # print("received message from SW, event type Cmsg to CK") # print("recevied pload:", str(cmsg_a.a_Pload)) # print("recevied time:", str(cmsg_a.a_Time)) # print("recevied Type:", str(cmsg_a.a_Type)) @event_handler("CL", "query to CK") def receiveCLQuery(self, payload): print("###############") print("received message from LV, event type Query to CKv") print(payload) global pendQ, phase pendQ = Query(payload['time_start'], payload['time_end']) # in CA the query is unbounded from CL phase = 2 print("current phase", phase) x = self.select() # for i in x.a_set: # print(i.a_Type) # print(i.a_Time) # print(i.a_Pload) # print(x.countType(u'sen')) if (x.countType('sen') + x.countType('par')) != 0: # dispatch_test("max timestamp to SW", x.maxTimestamp()) dispatch_test("query result to CLv", x) # self.dispatch("max timestamp to SW", x.maxTimestamp()) self.dispatch("query result to CLv", x.ObjToJson()) @event_handler("LV", "query to CKv") def receiveLVQuery(self, payload): print("###############") print("received message from LV, event type Query to CK") print(payload) global pendQ, phase pendQ = Query(payload['time_start'], payload['time_end']) phase = 1 if self.contains(): x = self.select() if x.a_set: dispatch_test("query result to CLv", x) self.dispatch("query result to CLv", x.ObjToJson()) def select(self): x = SetCmsg() global k, pendQ for i in k.a_set: if pendQ.time_start < i.a_Time <= pendQ.time_end: x.add(i) return x def contains(self): global k, pendQ for i in k.a_set: if pendQ.time_start <= i.a_Time <= pendQ.time_end: return True return False
python_asimov-master/CKv/CKv.pyc
python_asimov-master/CKv/Classpack.py
class Cmsg: a_Pload = None a_Time = None a_Type = None def __init__(self, a_mes, a_time, a_type): self.a_Pload = a_mes self.a_Time = a_time self.a_Type = a_type class SetCmsg: a_set = [] def __init__(self): self.a_set = [] def add(self, Cmsg): if Cmsg not in self.a_set: self.a_set.append(Cmsg) def countType(self, typename): j = 0 for i in self.a_set: if i.a_Type == typename: j+=1 return j def maxTimestamp(self): maxtime = 0 for i in self.a_set: if i.a_Time > maxtime: maxtime = i.a_Time return maxtime def ObjToJson(self): l = [] for i in self.a_set: l.append(i.__dict__) return l def JsonToObj(self, l): for i in l: self.a_set.append(Cmsg(i['a_Pload'], i['a_Time'], i['a_Type'])) class Query: time_start = None time_end = None def __init__(self, s, e): self.time_start = s self.time_end = e class Meta: time_rI = None time_tauM = None def __init__(self, rI, tauM): self.time_rI = rI self.time_tauM = tauM def dispatch_test(event_type, payload): print("event_type:", event_type) print("payload_type:", type(payload)) print(payload) if __name__ == '__main__': S = SetCmsg() dic = {u'a_Time': 1593087116.986699, u'a_Type': u'sen', u'a_Pload': 2962364.3205259433} c = Cmsg(dic['a_Pload'], dic['a_Time'], dic['a_Type']) S.add(c) c = Cmsg(1593087116.986699, 2962364.32052594, u'sen') S.add(c) a = S.ObjToJson() print(a) ss = SetCmsg() ss.JsonToObj(a) print(ss.a_set[0].a_Pload) dispatch_test("s","ssss")
python_asimov-master/CKv/Classpack.pyc
python_asimov-master/CKv/Dockerfile
FROM python:3.6 # 设置工作目录 RUN mkdir -p /usr/src/CKv WORKDIR /usr/src/CKv # 安装依赖 RUN pip install nameko # 添加应用 ADD . /usr/src/CKv # 运行服务 CMD nameko run CKv --broker amqp://guest:[email protected]
python_asimov-master/CL/CL.py
import math import random import time from nameko.events import EventDispatcher, event_handler from Classpack import SetCmsg, Query, dispatch_test class Params: radius = 5 liquidVolume = 0 desiredLiquidVolum = None K = 1.5 previousActTime = None holdAct = 0 def __init__(self, desired): self.systemState = None self.desiredLiquidVolum = desired def updatestate(self, Pload): self.liquidVolume = Pload * self.radius**2 * math.pi def act(self): deltaW = self.desiredLiquidVolum - self.liquidVolume self.holdAct = deltaW/self.K return self.holdAct phase = 0 x = None # SetCmsg() mRecC = 0 params = Params(30000) Notif = False class CL: name = "CL" # phase = 0 # x = None # SetCmsg() # mRecC = 0 # params = Params() dispatch = EventDispatcher() @event_handler("SW", "Notif to CL") def receiveCmsg(self, payload): print("############") print("receive Notif from SW") global mRecC, phase, Notif Notif = payload # print(type(payload)) # print(payload) # use dispatch_test test dispatch_test("Query to CK", Query(mRecC, float("inf"))) # to CK self.dispatch("Query to CK", Query(mRecC, float("inf")).__dict__) phase = 1 @event_handler("CK", "query result to CL") def receiveQueryResult(self, payload): print("############") print("receive query result from CK") print(payload) global mRecC, phase, x x = SetCmsg() x.JsonToObj(payload) # for i in self.x.a_set: # print(i.a_Pload) @event_handler("SW", "current time to CL") def receiveCurrentTime(self, payload): print("############") print("current time to CL") print(payload) global mRecC, phase, x, Notif while phase != 1 or x is None: time.sleep(0.1) if phase == 1 and x is not None: time_r = payload self.updParams(time_r) actuation =self.calcAct(time_r) dispatch_test("produces a to SW", actuation) # return pload a to SW, type double self.dispatch("produces a to SW", actuation) mRecC = x.maxTimestamp() phase = 0 x = None # get last Cmsg's Pload(type is "sen" ) as systemState(lastSensingReiceved) def updParams(self, r): global mRecC, phase, x, params Cmsg_l = x.a_set while Cmsg_l: msg = Cmsg_l.pop() if msg.a_Type == "sen": params.updatestate(msg.a_Pload) break # systemState add a random(1-100) number as actuation def calcAct(self, r): global params # return pload type double if random.random() > 0.5: # Simulate actuation after being attacked params.act() return 0 else: # normal actuation return params.act()
python_asimov-master/CL/CL.pyc
python_asimov-master/CL/Classpack.py
class Cmsg: a_Pload = None a_Time = None a_Type = None def __init__(self, a_mes, a_time, a_type): self.a_Pload = a_mes self.a_Time = a_time self.a_Type = a_type class SetCmsg: a_set = [] def __init__(self): self.a_set = [] def add(self, Cmsg): if Cmsg not in self.a_set: self.a_set.append(Cmsg) def countType(self, typename): j = 0 for i in self.a_set: if i.a_Type == typename: j+=1 return j def maxTimestamp(self): maxtime = 0 for i in self.a_set: if i.a_Time > maxtime: maxtime = i.a_Time return maxtime def ObjToJson(self): l = [] for i in self.a_set: l.append(i.__dict__) return l def JsonToObj(self, l): for i in l: self.a_set.append(Cmsg(i['a_Pload'], i['a_Time'], i['a_Type'])) class Query: time_start = None time_end = None def __init__(self, s, e): self.time_start = s self.time_end = e class Meta: time_rI = None time_tauM = None def __init__(self, rI, tauM): self.time_rI = rI self.time_tauM = tauM def dispatch_test(event_type, payload): print("event_type:", event_type) print("payload_type:", type(payload)) print(payload) if __name__ == '__main__': S = SetCmsg() dic = {u'a_Time': 1593087116.986699, u'a_Type': u'sen', u'a_Pload': 2962364.3205259433} c = Cmsg(dic['a_Pload'], dic['a_Time'], dic['a_Type']) S.add(c) c = Cmsg(1593087116.986699, 2962364.32052594, u'sen') S.add(c) a = S.ObjToJson() print(a) ss = SetCmsg() ss.JsonToObj(a) print(ss.a_set[0].a_Pload) dispatch_test("s","ssss")
python_asimov-master/CL/Classpack.pyc
python_asimov-master/CL/Dockerfile
FROM python:3.6 # 设置工作目录 RUN mkdir -p /usr/src/CL WORKDIR /usr/src/CL # 安装依赖 RUN pip install nameko # 添加应用 ADD . /usr/src/CL # 运行服务 CMD nameko run CL --broker amqp://guest:[email protected]
python_asimov-master/CLv/CLv.py
from nameko.events import EventDispatcher, event_handler import random, time, math from Classpack import Cmsg, SetCmsg, Query, Meta, dispatch_test class Params: radius = 5 liquidVolume = 0 desiredLiquidVolum = None K = 1.5 previousActTime = None holdAct = 0 def __init__(self, desired): self.systemState = None self.desiredLiquidVolum = desired def updatestate(self, Pload): self.liquidVolume = Pload * self.radius**2 * math.pi def act(self): deltaW = self.desiredLiquidVolum - self.liquidVolume self.holdAct = deltaW/self.K return self.holdAct phase = 0 x = None # SetCmsg() mRecC = 0 params = Params(30000) Notif = False class CL: name = "CLv" # phase = 0 # x = None # SetCmsg() # mRecC = 0 # params = Params() dispatch = EventDispatcher() @event_handler("LV", "Notif to CLv") def receiveCmsg(self, payload): print("############") print("receive Notif from LV") global mRecC, phase, Notif Notif = payload # print(type(payload)) # print(payload) # use dispatch_test test dispatch_test("unbounded query to LV", Query(mRecC, float("inf"))) # to CK self.dispatch("unbounded query to LV", Query(mRecC, float("inf")).__dict__) phase = 1 @event_handler("CKv", "query result to CLv") def receiveQueryResult(self, payload): print("############") print("receive query result from CK") print(payload) global mRecC, phase, x, Notif x = SetCmsg() x.JsonToObj(payload) while phase != 1: time.sleep(0.1) if phase == 1: time_r = payload self.updParams(time_r) actuation = self.calcAct(time_r) dispatch_test("trust actuation to LV", actuation) # return pload a to SW, type double self.dispatch("trust actuation to LV", actuation) mRecC = x.maxTimestamp() phase = 0 x = None # for i in self.x.a_set: # print(i.a_Pload) @event_handler("LV", "current time to CL") def receiveCurrentTime(self, payload): print("############") print("current time to CL") print(payload) global mRecC, phase, x, Notif while phase != 1 or x is None: time.sleep(0.1) if phase == 1 and x is not None: time_r = payload self.updParams(time_r) actuation = self.calcAct(time_r) dispatch_test("trust actuation to LV", actuation) # return pload a to SW, type double self.dispatch("trust actuation to LV", actuation) mRecC = x.maxTimestamp() phase = 0 x = None # get last Cmsg's Pload(type is "sen" ) as systemState(lastSensingReiceved) def updParams(self, r): global mRecC, phase, x, params Cmsg_l = x.a_set while Cmsg_l: msg = Cmsg_l.pop() if msg.a_Type == "sen": params.updatestate(msg.a_Pload) break # systemState add a random(1-100) number as actuation def calcAct(self, r): global params # return pload type double return params.act()
python_asimov-master/CLv/CLv.pyc
python_asimov-master/CLv/Classpack.py
class Cmsg: a_Pload = None a_Time = None a_Type = None def __init__(self, a_mes, a_time, a_type): self.a_Pload = a_mes self.a_Time = a_time self.a_Type = a_type class SetCmsg: a_set = [] def __init__(self): self.a_set = [] def add(self, Cmsg): if Cmsg not in self.a_set: self.a_set.append(Cmsg) def countType(self, typename): j = 0 for i in self.a_set: if i.a_Type == typename: j+=1 return j def maxTimestamp(self): maxtime = 0 for i in self.a_set: if i.a_Time > maxtime: maxtime = i.a_Time return maxtime def ObjToJson(self): l = [] for i in self.a_set: l.append(i.__dict__) return l def JsonToObj(self, l): for i in l: self.a_set.append(Cmsg(i['a_Pload'], i['a_Time'], i['a_Type'])) class Query: time_start = None time_end = None def __init__(self, s, e): self.time_start = s self.time_end = e class Meta: time_rI = None time_tauM = None def __init__(self, rI, tauM): self.time_rI = rI self.time_tauM = tauM def dispatch_test(event_type, payload): print("event_type:", event_type) print("payload_type:", type(payload)) print(payload) if __name__ == '__main__': S = SetCmsg() dic = {u'a_Time': 1593087116.986699, u'a_Type': u'sen', u'a_Pload': 2962364.3205259433} c = Cmsg(dic['a_Pload'], dic['a_Time'], dic['a_Type']) S.add(c) c = Cmsg(1593087116.986699, 2962364.32052594, u'sen') S.add(c) a = S.ObjToJson() print(a) ss = SetCmsg() ss.JsonToObj(a) print(ss.a_set[0].a_Pload) dispatch_test("s","ssss")
python_asimov-master/CLv/Classpack.pyc
python_asimov-master/CLv/Dockerfile
FROM python:3.6 # 设置工作目录 RUN mkdir -p /usr/src/CLv WORKDIR /usr/src/CLv # 安装依赖 RUN pip install nameko # 添加应用 ADD . /usr/src/CLv # 运行服务 CMD nameko run CLv --broker amqp://guest:[email protected]
python_asimov-master/Classpack.py
class Cmsg: a_Pload = None a_Time = None a_Type = None def __init__(self, a_mes, a_time, a_type): self.a_Pload = a_mes self.a_Time = a_time self.a_Type = a_type class SetCmsg: a_set = [] def __init__(self): self.a_set = [] def add(self, Cmsg): if Cmsg not in self.a_set: self.a_set.append(Cmsg) def countType(self, typename): j = 0 for i in self.a_set: if i.a_Type == typename: j+=1 return j def maxTimestamp(self): maxtime = 0 for i in self.a_set: if i.a_Time > maxtime: maxtime = i.a_Time return maxtime def ObjToJson(self): l = [] for i in self.a_set: l.append(i.__dict__) return l def JsonToObj(self, l): for i in l: self.a_set.append(Cmsg(i['a_Pload'], i['a_Time'], i['a_Type'])) class Query: time_start = None time_end = None def __init__(self, s, e): self.time_start = s self.time_end = e class Meta: time_rI = None time_tauM = None def __init__(self, rI, tauM): self.time_rI = rI self.time_tauM = tauM def dispatch_test(event_type, payload): print("event_type:", event_type) print("payload_type:", type(payload)) print(payload) if __name__ == '__main__': S = SetCmsg() dic = {u'a_Time': 1593087116.986699, u'a_Type': u'sen', u'a_Pload': 2962364.3205259433} c = Cmsg(dic['a_Pload'], dic['a_Time'], dic['a_Type']) S.add(c) c = Cmsg(1593087116.986699, 2962364.32052594, u'sen') S.add(c) a = S.ObjToJson() print(a) ss = SetCmsg() ss.JsonToObj(a) print(ss.a_set[0].a_Pload) dispatch_test("s","ssss")
python_asimov-master/Factory/Dockerfile
FROM python:3.6 # 设置工作目录 RUN mkdir -p /usr/src/SW WORKDIR /usr/src/SW # 安装依赖 RUN pip install nameko # 添加应用 ADD . /usr/src/SW # 运行服务 # CMD python factory.py CMD nameko shell --broker amqp://guest:[email protected]
python_asimov-master/Factory/system.py
from nameko.standalone.rpc import ClusterRpcProxy from threading import Thread import random import time CONFIG = {'AMQP_URI': "amqp://guest:[email protected]"} def send(): with ClusterRpcProxy(CONFIG) as rpc: message = random.uniform(-382.0, 500) rpc.SW.receiveMsg(message) def receive(): with ClusterRpcProxy(CONFIG) as rpc: return rpc.SW.sendPload() def receiveLV(): with ClusterRpcProxy(CONFIG) as rpc: return rpc.LV.sendresult() def sendSense(): while True: time.sleep(50) send() def receiveActuation(): while True: time.sleep(10) l = receive() print("##############") while l: print("recivied actuation:", l.pop()) def receiveLVres(): while True: time.sleep(20) l = receiveLV() print("##############") while l: print(l.pop()) if __name__ == '__main__': thread_01 = Thread(target=sendSense) thread_02 = Thread(target=receiveActuation) thread_03 = Thread(target=receiveLVres) thread_01.start() thread_02.start() thread_03.start()
python_asimov-master/LV/Classpack.py
class Cmsg: a_Pload = None a_Time = None a_Type = None def __init__(self, a_mes, a_time, a_type): self.a_Pload = a_mes self.a_Time = a_time self.a_Type = a_type class SetCmsg: a_set = [] def __init__(self): self.a_set = [] def add(self, Cmsg): if Cmsg not in self.a_set: self.a_set.append(Cmsg) def countType(self, typename): j = 0 for i in self.a_set: if i.a_Type == typename: j+=1 return j def maxTimestamp(self): maxtime = 0 for i in self.a_set: if i.a_Time > maxtime: maxtime = i.a_Time return maxtime class Query: time_start = None time_end = None def __init__(self, s, e): self.time_start = s self.time_end = e class Meta: time_rI = None time_tauM = None def __init__(self, rI, tauM): self.time_rI = rI self.time_tauM = tauM def dispatch_test(event_type, payload): print("event_type:", event_type) print("payload_type:", type(payload)) print(payload) if __name__ == '__main__': S = SetCmsg() dic = {u'a_Time': 1593087116.986699, u'a_Type': u'sen', u'a_Pload': 2962364.3205259433} c = Cmsg(dic['a_Pload'],dic['a_Time'],dic['a_Type'],) S.add(c) print(type(c)) dispatch_test("s","ssss")
python_asimov-master/LV/Classpack.pyc
python_asimov-master/LV/Dockerfile
FROM python:3.6 # 设置工作目录 RUN mkdir -p /usr/src/LV WORKDIR /usr/src/LV # 安装依赖 RUN pip install nameko # 添加应用 ADD . /usr/src/LV # 运行服务 CMD nameko run LV --broker amqp://guest:[email protected]
python_asimov-master/LV/LV.py
import time from nameko.rpc import rpc from nameko.events import EventDispatcher, event_handler from Classpack import Cmsg, SetCmsg, Query, Meta, dispatch_test phase = 0 acts = [] metas = [] res_list = [] class LV: name = "LV" # phase = 0 # metas = [] # acts = [] dispatch = EventDispatcher() @event_handler("SW", "Cmsg to LV") def receivedCmsg(self, payload): print("###############") print("Received Cmsg from SW") print(payload) global acts, phase, metas newCmsg = Cmsg(payload['a_Pload'], payload['a_Time'], payload['a_Type']) dispatch_test("to CKv of IDS", newCmsg) self.dispatch("to CKv of IDS", newCmsg.__dict__) if payload['a_Type'] == "act": acts.append(newCmsg) # while phase == 0 or len(metas) == 0: while len(metas) == 0: time.sleep(0.1) # if phase == 0: # if len(acts) > 0: Notif = True dispatch_test("Notif to CLv", Notif) self.dispatch("Notif to CLv", Notif) phase = 1 @event_handler("SW", "Meta to LV of IDS") def receivedMeta(self, payload): print("###############") print("Received Meta from SW") print(payload) global acts, metas, phase metas.append(Meta(payload['time_rI'], payload['time_tauM'])) # while phase == 0 or len(acts)==0: # time.sleep(0.1) # if phase == 0: # if len(acts) > 0: # Notif = True # dispatch_test("Notif to CLv", Notif) # self.dispatch("Notif to CLv", Notif) # phase = 1 @event_handler("CLv", "unbounded query to LV") def receivedQuery(self, payload): print("###############") print("Received unbounded query from CLv") print(payload) global acts, metas, phase # if phase == 1: ts = payload["time_start"] while len(metas) == 0: time.sleep(0.1) te = metas[0].time_tauM # te = 0 # for i in metas: # if i.time_tauM > te: # te = i.time_tauM dispatch_test("query to CKv", Query(ts, te)) self.dispatch("query to CKv", Query(ts, te).__dict__) # phase = 2 @event_handler("CLv", "trust actuation to LV") def receivedTrustActuation(self, payload): print("###############") print("Received trust actuation from CLv") print(payload) global acts, metas, phase, res_list # if phase == 2: if len(acts) > 0: trust_Pload = payload untrust_mesg = acts[0] untrust_Pload = untrust_mesg.a_Pload print(untrust_mesg.a_Pload) print(untrust_mesg.a_Time) if self.compare(trust_Pload, untrust_Pload): print("Pload is trust") res_list.append("Pload \""+str(untrust_Pload)+"\" is trust") self.rem() # phase = 0 else: res_list.append("Pload \"" + str(untrust_Pload) + "\" is attack, New Alert to DMAN") self.rem() # Begin state mitigation operations print("New Alert to DMAN") # phase = 0 @rpc def sendresult(self): global res_list res = [] while res_list: res.append(res_list.pop()) return res # actuation is sen + number(1-100), trust minus untrust should between (-201,201) def compare(self, trust, untrust): if trust == untrust: return True else: return False def rem(self): global acts, metas, phase del acts[0] del metas[0]
python_asimov-master/LV/LV.pyc
python_asimov-master/README.md
# ASIMOV ## CA CA part include Folder: CK, CL, SW ## IDS IDS part include Folder: CKv, CLv, LV ## System System code in Factory folder ## Classpack Cmsg, SetCmsg, Query, Meta data structure are inside Classpack file. I create these data structure as class ## Dockerfile In each folder include a dockerfile. it will use create a docker image. ## Control logic for Tank System The Control logic in CL.py file. I create all function in class Params. based on w = s * π r2 formula and a = K(w(desired) - w) the system send sensing number is s. it can calculate w. the desired w is defined, Use desired W minus W then divide K(define value is 1.5), the result is actuation a.
python_asimov-master/SW/Classpack.py
class Cmsg: a_Pload = None a_Time = None a_Type = None def __init__(self, a_mes, a_time, a_type): self.a_Pload = a_mes self.a_Time = a_time self.a_Type = a_type class SetCmsg: a_set = [] def __init__(self): self.a_set = [] def add(self, Cmsg): if Cmsg not in self.a_set: self.a_set.append(Cmsg) def countType(self, typename): j = 0 for i in self.a_set: if i.a_Type == typename: j+=1 return j def maxTimestamp(self): maxtime = 0 for i in self.a_set: if i.a_Time > maxtime: maxtime = i.a_Time return maxtime class Query: time_start = None time_end = None def __init__(self, s, e): self.time_start = s self.time_end = e class Meta: time_rI = None time_tauM = None def __init__(self, rI, tauM): self.time_rI = rI self.time_tauM = tauM def dispatch_test(event_type, payload): print("event_type:", event_type) print("payload_type:", type(payload)) print(payload) if __name__ == '__main__': S = SetCmsg() dic = {u'a_Time': 1593087116.986699, u'a_Type': u'sen', u'a_Pload': 2962364.3205259433} c = Cmsg(dic['a_Pload'],dic['a_Time'],dic['a_Type'],) S.add(c) print(type(c)) dispatch_test("s","ssss")
python_asimov-master/SW/Classpack.pyc
python_asimov-master/SW/Dockerfile
FROM python:3.6 # 设置工作目录 RUN mkdir -p /usr/src/SW WORKDIR /usr/src/SW # 安装依赖 RUN pip install nameko # 添加应用 ADD . /usr/src/SW # 运行服务 CMD nameko run SW --broker amqp://guest:[email protected]
python_asimov-master/SW/SW.py
from nameko.rpc import rpc, RpcProxy from nameko.events import EventDispatcher, event_handler import time from Classpack import Cmsg, SetCmsg, Query, Meta, dispatch_test phase = 0 timestamp = None last_timestamp = None mRecC = 0 mRecP = 0 a_list = [] class SW: name = "SW" # timestamp = None # last_timestamp = None # define SW variables # Pload_a = None # Pload_s = None # greatest timestamp among Cmsg ever consumed by CL # mRecC = 0 # greatest timestamp among Cmsg ever produced by SW # mRecP = 0 # define dispatch to dispatch to other service dispatch = EventDispatcher() # receive message from system @rpc def receiveMsg(self, Pload_s): print("############") print("receive message from system") global phase, timestamp, mRecP, mRecC self.setTimestamp() # while self.timestamp == self.last_timestamp: # time.sleep(0.000001) # self.timestamp = time.time() time_r = timestamp type = "sen" # self.last_timestamp = time_r newMes = Cmsg(Pload_s, time_r, type) # use dispatch_test test dispatch_test("Cmsg to CK/LV", newMes) # to CK self.dispatch("Cmsg to CK", newMes.__dict__) # to LV self.dispatch("Cmsg to LV", newMes.__dict__) mRecP = time_r # and phase == 0 if mRecC < mRecP: Notif = True # use dispatch_test test dispatch_test("Notif to CL", Notif) # to CL self.dispatch("Notif to CL", Notif) phase = 1 print(phase) @rpc def sendPload(self): global a_list res = [] while a_list: res.append(a_list.pop()) return res @event_handler("CK", "max timestamp to SW") def receiveMaxTimstamp(self, payload): print("############") print("receive max timestamp from CK") print(payload) global phase, timestamp, mRecC # time = timestamp self.setTimestamp() print(phase) if phase == 1: dispatch_test("current time to CL", timestamp) self.dispatch("current time to CL", timestamp) tauM = payload dispatch_test("Meta to LV of IDS", Meta(timestamp, tauM)) self.dispatch("Meta to LV of IDS", Meta(timestamp, tauM).__dict__) if tauM > mRecC: mRecC = tauM phase = 2 print(phase) @event_handler("CL", "produces a to SW") def receiveAction(self, payload): print("############") print("receive produces a from CL") print(payload) global phase, timestamp, a_list # self.setTimestamp() type = 'act' if phase == 2: phase = 0 # todo send action to system print("send action to system") a_list.append(payload) time_r = timestamp Pload_a = payload newMes = Cmsg(Pload_a, time_r, type) # use dispatch_test test dispatch_test("Cmsg to CK/LV", newMes) # to CK self.dispatch("Cmsg to CK", newMes.__dict__) # to LV self.dispatch("Cmsg to LV", newMes.__dict__) def setTimestamp(self): global timestamp, last_timestamp current_time = time.time() while current_time == last_timestamp: time.sleep(0.000001) current_time = time.time() timestamp = current_time last_timestamp = current_time
python_asimov-master/SW/SW.pyc
python_asimov-master/__pycache__/Classpack.cpython-36.pyc
python_asimov-master/test.py
import time from threading import Thread def senda(): while True: time.sleep(20) print(time.time()) def receivea(): while True: time.sleep(12) print("received") if __name__ == "__main__": thread_01 = Thread(target=senda) thread_02 = Thread(target=receivea) thread_01.start() thread_02.start()