A self-protecting control application base on microserevice

profilefffinal
thesis.rar

idea paper.pdf

A Self-protecting Control Application for IIoT

Gabriele Gualandi Department of Computer Science Sapienza University of Rome, Italy

[email protected]

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()