diff options
author | serena.spinoso <serena.spinoso@polito.it> | 2017-02-25 12:00:55 +0100 |
---|---|---|
committer | serena.spinoso <serena.spinoso@polito.it> | 2017-02-27 13:39:18 +0100 |
commit | 53d83244c1bf36af86e90ce5fe758a369f73563e (patch) | |
tree | f5780b3033763d6b3cd62c40f5d4a63dfac35f7a /verigraph | |
parent | f0108f26fb1f62fefbbc4d5484b87241d563737b (diff) |
Add verigraph code base
JIRA: PARSER-111
Change-Id: Ie76e14fabbb6c388ebc89d9a15dd3021b25fa892
Signed-off-by: serena.spinoso <serena.spinoso@polito.it>
Diffstat (limited to 'verigraph')
157 files changed, 20321 insertions, 0 deletions
diff --git a/verigraph/LICENSE b/verigraph/LICENSE new file mode 100644 index 0000000..79a7d4f --- /dev/null +++ b/verigraph/LICENSE @@ -0,0 +1,13 @@ +Copyright 2017 Politecnico di Torino and others. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/verigraph/README.rst b/verigraph/README.rst new file mode 100644 index 0000000..947e893 --- /dev/null +++ b/verigraph/README.rst @@ -0,0 +1,258 @@ +.. This work is licensed under a Creative Commons Attribution 4.0 International License. +.. http://creativecommons.org/licenses/by/4.0 + +| Let’s look at how to deploy **VeriGraph** on Apache Tomcat. If you’re + only interested in creating gRPC API and ``neo4jmanager`` is already + deployed, you can skip this section and go straight to the + `documentation <https://gitlab.com/serena.spinoso/DP2.2017.SpecialProject2.gRPC/tree/master/src/main/java/it/polito/grpc>`__ +| (though you might find it useful if Tomcat is not yet installed!). + +**Windows** + +- install ``jdk1.8.X_YY`` + `here <http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html>`__ +- set ambient variable ``JAVA_HOME`` to where you installed the jdk + (e.g. ``C:\Program Files\Java\jdk1.8.X_YY``) +- install Apache Tomcat 8 + `here <https://tomcat.apache.org/download-80.cgi>`__ +- install a pre-compiled distribution of Z3 from + `here <https://github.com/Z3Prover/bin/tree/master/releases>`__ + and save the ``[z3_root]/bin`` content under ``[verigraph]/service/build`` +- create the ``mcnet.jar`` of the ``mcnet.*`` packages and put into the ``[verigraph]/service/build`` directory +- download the qjutils library + `here <https://github.com/quanla/classreloading/tree/master/src/main/java/qj/util>`__ + and create a jar file (i.e. qjutils.jat) in ``[verigrap]/service/build`` +- set ambient variable ``CATALINA_HOME`` to the directory where you + installed Apache (e.g. + ``C:\Program Files\Java\apache-tomcat-8.0.30``) +- create ``shared`` folder under ``%CATALINA_HOME%`` +- add previously created folder to the Windows ``Path`` system variable + (i.e. append the following string at the end: + ``;%CATALINA_HOME%\shared``) +- copy ``[verigraph]/lib/mcnet.jar``, ``[verigraph]/service/build/com.microsoft.z3.jar`` and ``[verigraph]/service/build/qjutils.jar`` + to ``%CATALINA_HOME%\shared`` +- to correctly compile the code you have to put the path of ``com.microsoft.z3.jar`` + and the libraries it refers to as environment variable. i.e. is enough + to add the project subfolder ``build`` to the PATH environment variable (i.e., ``[verigraph]/build``) +- create custom file setenv.bat under ``%CATALINA_HOME%\bin`` with the + following content: + + .. code:: bat + + set CLASSPATH=%CLASSPATH%;%CATALINA_HOME%\shared\qjutils.jar;%CATALINA_HOME%\shared\mcnet.jar;%CATALINA_HOME%\shared\com.microsoft.z3.jar;.;%CATALINA_HOME%\webapps\verify\WEB-INF\classes\tests + +- download ``neo4jmanager.war`` from + `here <https://github.com/netgroup-polito/verigraph/tree/master/dist>`__ + and copy into into ``%CATALINA_HOME%\webapps`` +- export the ``verify.war`` file from the project and copy into ``%CATALINA_HOME%\webapps`` +- (optional) configure Tomcat Manager: +- open the file ``%CATALINA_HOME%\conf\tomcat-users.xml`` +- under the ``tomcat-users`` tag place the following content: + ``xml <role rolename="tomcat"/> <role rolename="role1"/> <user username="tomcat" password="tomcat" roles="tomcat,manager-gui"/> <user username="both" password="tomcat" roles="tomcat,role1"/> <user username="role1" password="tomcat" roles="role1"/>`` +- launch Tomcat 8 with the startup script + ``%CATALINA_HOME%\bin\startup.bat`` +- (optional) if you previously configured Tomcat Manager you can open a + browser and navigate to `this link <http://localhost:8080/manager>`__ + and login using ``tomcat/tomcat`` as username/password +- (optional) you can deploy/undeploy/redeploy the downloaded WARs + through the web interface + +**Unix** + +- install ``jdk1.8.X_YY`` from the command line: +- go to `this + link <http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html>`__ + to check the appropriate version for you OS and architecture +- copy the desired version to the clipboard (e.g. + ``http://download.oracle.com/otn-pub/java/jdk/7u79-b15/jdk-7u79-linux-x64.tar.gz``) +- open a terminal windows and paste the following command (replace + ``link`` with the previously copied link): + ``wget --no-check-certificate --no-cookies --header "Cookie: oraclelicense=accept-securebackup-cookie" 'link'`` + e.g. + ``wget --no-check-certificate --no-cookies --header "Cookie: oraclelicense=accept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jdk/7u79-b15/jdk-7u79-linux-x64.tar.gz`` +- untar the archive with the following command (replace 'jdk' to match + the name of the downloaded archive): + ``tar zxvf 'jdk'.tar.gz`` + e.g. + ``tar zxvf jdk-7u<version>-linux-x64.tar.gz`` +- delete the ``.tar.gz`` file if you want to save disk space +- install and configure Apache Tomcat 8 with the following commands: +- go to `this URL <http://it.apache.contactlab.it/tomcat/tomcat-8/>`__ + and see what the latest available version is +- download the archive (substitute every occurrence of '8.0.32' in the + following command with the latest available version): + ``wget http://it.apache.contactlab.it/tomcat/tomcat-8/v8.0.32/bin/apache-tomcat-8.0.32.tar.gz`` +- extract downloaded archive: + ``tar xvf apache-tomcat-8.0.32.tar.gz`` +- edit configuration: + ``nano ./apache-tomcat-8.0.32/conf/tomcat-users.xml`` +- under the ``tomcat-users`` tag place the following content + ``xml <role rolename="tomcat"/> <role rolename="role1"/> <user username="tomcat" password="tomcat" roles="tomcat,manager-gui"/> <user username="both" password="tomcat" roles="tomcat,role1"/> <user username="role1" password="tomcat" roles="role1"/> </tomcat-users>`` +- set a few environment variables: + ``sudo nano ~/.bashrc`` +- paste the following content at the end of the file + ``export CATALINA_HOME='/path/to/apache/tomcat/folder'`` + e.g. + ``export CATALINA_HOME=/home/mininet/apache-tomcat-8.0.33`` + ``export JRE_HOME='/path/to/jdk/folder'`` + e.g. + ``export JRE_HOME=/home/mininet/jdk1.8.0_92/jre`` + ``export JDK_HOME='/path/to/jdk/folder'`` + e.g. + ``export JDK_HOME=/home/mininet/jdk1.8.0_92`` + ``export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$CATALINA_HOME/shared`` + ``export JAVA_OPTS="-Djava.library.path=$CATALINA_HOME/shared"`` +- ``exec bash`` +- install a pre-compiled distribution of Z3 from + `here <https://github.com/Z3Prover/bin/tree/master/releases>`__ + and save [z3_root]/bin content under ``[verigraph]/service/build`` +- download the qjutils library + `here <https://github.com/quanla/classreloading/tree/master/src/main/java/qj/util>`__ + and create a jar file (i.e. qjutils.jar) in ``[verigrap]/service/build`` +- create the ``mcnet.jar`` of the ``mcnet.*`` packages and put into the ``[verigraph]/service/build`` directory +- copy ``[verigraph]/service/build/mcnet.jar``, ``[verigraph]/service/build/com.microsoft.z3.jar`` + and ``[verigraph]/service/build/qjutils.jar`` to ``$CATALINA_HOME/shared`` +- customize Tomcat classpath + ``nano $CATALINA_HOME/bin/setenv.sh`` +- paste the following content and save file: + ``bash #!/bin/sh export CLASSPATH=$CLASSPATH:$CATALINA_HOME/shared/qjutils.jar:$CATALINA_HOME/shared/mcnet.jar:$CATALINA_HOME/shared/com.microsoft.z3.jar:.:$CATALINA_HOME/webapps/verify/WEB-INF/classes/tests`` +- save and close the file (``CTRL+O``, ``CTRL+X``) + ``sudo chmod +x $CATALINA_HOME/bin/setenv.sh`` +- download ``neo4jmanager.war`` from + `here <https://github.com/netgroup-polito/verigraph/tree/master/dist>`__ + and copy into into ``%CATALINA_HOME%\webapps`` +- export the ``verify.war`` file from the project and copy into ``%CATALINA_HOME%\webapps`` +- launch Tomcat 8 with the startup script + ``$CATALINA_HOME/bin/startup.sh`` +- open a browser and navigate to `this + link <http://localhost:8080/manager>`__ and login using + ``tomcat/tomcat`` as username/password +- you can deploy/undeploy/redeploy the downloaded WARs through the web + interface + +**Eclipse** + +- clone project onto your hard drive with this command: + ``git clone git@github.com:netgroup-polito/verigraph.git`` +- Download Apache Tomcat 8 (see instructions above for Windows and + Unix) +- Download JDK (see instructions above for Windows and Unix) +- Configure runtime environment in Eclipse with `the following + incstructions <http://crunchify.com/step-by-step-guide-to-setup-and-install-apache-tomcat-server-in-eclipse-development-environment-ide/>`__ +- Add new Tomcat server on port ``8080`` +- Configure Tomcat server: + + - double-click on the newly created server in the ``Servers`` tab + - make sure under ``Server Locations`` ``Use Tomcat installation`` + is selected + - Open ``Launch Configuration``->``Classpath`` + - add the required JARS (``mcnet.jar``, ``com.microsoft.z3.jar`` and + ``qjutils.jar``) under ``User Entries`` + - Hit ``Apply`` and ``Ok`` + +- Run the server + +**How to add you own function ``<type>``** + +#. under the the ``mcnet.netobjs`` package (i.e. under + ``/verify/service/src/mcnet/netobjs``) create a new class + ``<Type>.java``, where ``<type>`` is the desired function name (i.e. + ``<type>`` will be added to the supported node functional types) + which extends ``NetworkObject`` and implement the desired logic + +#. regenerate ``mcnet.jar`` selecting the packages ``mcnet.components`` + and ``mcnet.netobjs`` and exporting the generated JAR to + ``/verify/service/build`` (overwrite the existing file) + +#. under ``/verify/src/main/webapp/json/`` create a file + ``<type>.json``. This file represents a JSON schema (see + `here <http://json-schema.org/>`__ the official documentation). For + compatibility with the other functions it is mandatory to support an + array as the root of the configuration, but feel free to specify all + the other constraints as needed. A sample of ``<type>.json`` to + describe an empty configuration could be the following: + +``json { "$schema": "http://json-schema.org/draft-04/schema#", "title": "Type", "description": "This is a generic type", "type": "array", "items": { "type": "object" }, "minItems": 0, "maxItems": 0, "uniqueItems": true }`` + +#. in the package ``it.polito.escape.verify.validation`` (i.e. under + ``src/main/java/it/polito/escape/verify/validation``) create a new + class file named ``<Type>Validator.java`` (please pay attention to + the naming convention here: ``<Type>`` is the function type used in + the previous step capitalized, followed by the suffix ``Validator``) + which implements ``ValidationInterface``. This class represents a + custom validator for the newly introduced type and allows for more + complex constraints, which is not possible to express through a JSON + schema file. The validate method that has to be implemented is given + the following objects: + +- ``Graph graph`` represents the nffg that the object node belongs to; +- ``Node node`` represents the node that the object configuration + belongs to; +- ``Configuration configuration`` represents the parsed configuration. + It is sufficient to call the method ``getConfiguration`` on the + ``configuration`` object to get a ``JsonNode`` (Jackson's class) and + iterate over the various fields. + In case a configuration is not valid please throw a new + ``ValidationException`` passing a descriptive failure message. + Adding a custom validator is not strictly necessary whenever a JSON + schema is thought to be sufficient. Note though that, other than the + mandatory validation against a schema, whenever a custom validator is + not found a default validation is triggered, i.e. the value of every + JSON property must refer to the name of an existing node in the + working graph/nffg. If this is not the desired behavior it is + suggested to write a custom validator with looser constraints. + +#. customize the class generator and add the support for the newly + introduced type: + +- open the file + ``/verify/service/src/tests/j-verigraph-generator/config.py`` and + edit the following dictionaries: + + - ``devices_to_classes`` --> add the following entry: + ``"<type>" : "<Type>"`` + if you followed these instructions carefully the name of the class + implementing the function ``<type>`` should be ``<Type>.java`` + under the package ``mcnet.netobjs``. + - ``devices_to_configuration_methods`` --> add the following entry: + ``"<type>" : "configurationMethod"`` + if ``<type>`` is a middlebox it should have a configuration method + contained in the implementation ``<Type>.java`` under the package + ``mcnet.netobjs``. + - ``devices_initialization``: add the following entry: + ``"<type>" : ["param1", "param2"]`` + if ``<type>`` requires any parameter when it gets instanciated + please enter them in the form of a list. Make sure that these + parameters refer to existing keys contained in the configuration + schema file (see step 3). For instance the type ``webclient`` + requires the name of a webserver it wants to communicate with. + This parameter is passed in the configuration of a weblient by + setting a property ``webserver`` to the name of the desired + webserver. The value of this property gets extracted and used by + the test generator automatically. + - ``convert_configuration_property_to_ip`` --> add the following + entry: ``"<type>" : ["key", "value"]`` + Note that both ``key`` and ``value`` are optional and it is + critical to set them only if needed. Since the Z3 provider used + for testing works with IP addresses in this dictionary you have to + indicate whether it is needed an automatic convertion from names + to IP addresses: + - in case the keyword ``key`` is used every key of the JSON + configuration parsed will be prepended with the string ``ip_``; + - in case the keyword ``value`` is used every value of the JSON + configuration parsed will be prepended with the string ``ip_``; + - in case the list does not contain neither ``key`` nor ``value`` + the original configuration won't be touched. + +- open the file + ``/verify/service/src/tests/j-verigraph-generator/test_class_generator.py`` + and under the "switch" case in the form of a series of ifs used to + configure middle-boxes that starts at line #239 add a branch like the + following with the logic to generate the Java code for --> + ``elif nodes_types[i] == "<type>":`` + You can take inspiration from the other branches to see how to + serialize Java code. Note that this addition to the "switch" + statement is not needed if ``<type>`` is not a middlebox or it does + not need to be configured. + +#. Restart the web service. diff --git a/verigraph/buildVeriGraph_gRPC.xml b/verigraph/buildVeriGraph_gRPC.xml new file mode 100644 index 0000000..d23daa0 --- /dev/null +++ b/verigraph/buildVeriGraph_gRPC.xml @@ -0,0 +1,210 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright (c) 2017 Politecnico di Torino and others. + + All rights reserved. This program and the accompanying materials + are made available under the terms of the Apache License, Version 2.0 + which accompanies this distribution, and is available at + http://www.apache.org/licenses/LICENSE-2.0 +--> + +<project name="gRPC-Verigraph" default="run-tests" basedir="." xmlns:artifact="antlib:org.apache.maven.artifact.ant"> + <description> + Script for gRPC-Verigraph + </description> + + <!-- The location of this assignment --> + <property name="grpc.location" location="." /> + + <!-- The location to be used for class files --> + <property name="build.dir" location="${grpc.location}/build" /> + <!-- The location for source files --> + <property name="src.dir" location="${grpc.location}/src/main/java" /> + <!-- The location for solutions --> + <property name="grpc.dir" value="src/main/java/it/polito/grpc" /> + <!-- The location for jar files --> + <property name="lib.dir" location="${grpc.location}/lib" /> + <!-- The location for jar files --> + <property name="other_lib.dir" location="${grpc.location}/service/build" /> + <!-- The location for generated files --> + <property name="generated.dir" location="${basedir}/target/generated-sources" /> + <!-- The default test class --> + <property name="test1.class" value="it.polito.grpc.test.GrpcServerTest" /> + <property name="test2.class" value="it.polito.grpc.test.GrpcTest" /> + <property name="test3.class" value="it.polito.grpc.test.MultiThreadTest" /> + <property name="test4.class" value="it.polito.grpc.test.ReachabilityTest" /> + + <!-- The name to be given to the final zip --> + <property name="sol.zip" value="grpc.zip" /> + + <!-- Java compiler settings --> + <property name="debug" value="true" /> + <property name="debuglevel" value="source,lines,vars" /> + <property name="target" value="1.8" /> + <property name="source" value="1.8" /> + + <!-- The classpath to be used for running the tests --> + <path id="test.classpath"> + <pathelement path="${build.dir}" /> + <fileset dir="${grpc.location}/lib"> + <include name="*.jar" /> + </fileset> + <fileset refid="mvn-dependencies" /> + </path> + + <!-- Here starts part for Maven --> + <path id="maven-ant-tasks.classpath" path="lib/maven-ant-tasks-2.1.3.jar" /> + <typedef resource="org/apache/maven/artifact/ant/antlib.xml" + uri="antlib:org.apache.maven.artifact.ant" + classpathref="maven-ant-tasks.classpath" /> + <property file="build.properties"/> + + <!-- Load pom.xml for dependencies --> + <artifact:pom id="pomfile" file="pom.xml" /> + <artifact:dependencies filesetId="mvn-dependencies" pomRefId="pomfile" /> + + <!-- Grab the HSQLDB jar and add it to the classpath + <artifact:dependencies filesetId="warDeps"> + <dependency groupId="org.glassfish.jersey" artifactId="jersey-bom" version="2.22.1" /> + </artifact:dependencies>--> + + <path id="build.classpath"> + <fileset refid="mvn-dependencies" /> + </path> + + <target name="init"> + <mkdir dir="${build.dir}" /> + </target> + + <!-- The target for compiling the gRPC application --> + <target name="build" depends="init" description="Build the sources"> + <echo>Building gRPC (if needed)...</echo> + <javac + debug="${debug}" + debuglevel="${debuglevel}" + source="${source}" + target="${target}" + destdir="${build.dir}" + classpathref="build.classpath" + includeantruntime="false"> + <src path="${generated.dir}" /> + <src path="${src.dir}" /> + <compilerarg value="-Xlint:unchecked"/> + <classpath> + <pathelement path="${other_lib.dir}/qjutils.jar"/> + </classpath> + </javac> + <echo>Done.</echo> + </target> + + <!-- The target for running the gRPC application --> + <target name="run" depends="build" description="Run gRPC"> + <parallel> + <sequential> + <java classname="it.polito.grpc.Service" failonerror="true" classpathref="build.classpath" fork="yes"> + <classpath> + <pathelement path="${build.dir}"/> + </classpath> + </java> + </sequential> + <sequential> + <sleep milliseconds="500"/> + <java classname="it.polito.grpc.Client" failonerror="true" classpathref="build.classpath" fork="yes"> + <classpath> + <pathelement path="${build.dir}"/> + </classpath> + </java> + </sequential> + </parallel> + </target> + + <target name="run-client" depends="build" description="Run gRPC client"> + <java classname="it.polito.grpc.Client" failonerror="true" classpathref="build.classpath" fork="yes"> + <classpath> + <pathelement path="${build.dir}"/> + </classpath> + </java> + </target> + + <target name="run-server" depends="build" description="Run gRPC server"> + <java classname="it.polito.grpc.Service" failonerror="true" classpathref="build.classpath" fork="yes"> + <classpath> + <pathelement path="${build.dir}"/> + </classpath> + </java> + </target> + + <target name="run-tests" description="Run tests for gRPC"> + <echo>Running functional tests</echo> + + <antcall target="runFuncTest.real"> + <param name="exit.code1" value="126" /> + <param name="exit.code2" value="125" /> + <param name="exit.code3" value="124" /> + <param name="exit.code4" value="123" /> + </antcall> + </target> + + <!-- Target runFuncTest.real --> + <target name="runFuncTest.real" depends="build"> + + <echo>Running First set of Junit tests...</echo> + <junit printsummary="yes" dir="." fork="yes" haltonfailure="no" showoutput="no" filtertrace="true" timeout="120000"> + <jvmarg value="-Djava.awt.headless=true" /> + <formatter type="brief" usefile="false"/> + <test haltonfailure="no" failureproperty="test_failed" name="${test1.class}"/> + <classpath> + <path refid="test.classpath" /> + </classpath> + </junit> + <fail if="test_failed" status="${exit.code1}" message="*** First set of Junit tests: Some Tests FAILED ***"/> + <echo>*** First set of Junit tests: All Tests PASSED ***</echo> + + <echo>Running Second set of Junit tests...</echo> + <junit printsummary="yes" dir="." fork="yes" haltonfailure="no" showoutput="no" filtertrace="true" timeout="120000"> + <jvmarg value="-Djava.awt.headless=true" /> + <formatter type="brief" usefile="false"/> + <test haltonfailure="no" failureproperty="test_failed" name="${test2.class}"/> + <classpath> + <path refid="test.classpath" /> + </classpath> + </junit> + <fail if="test_failed" status="${exit.code2}" message="*** Second set of Junit tests: Some Tests FAILED ***"/> + <echo>*** Second set of Junit tests: All Tests PASSED ***</echo> + + <echo>Running Third set of Junit tests...</echo> + <junit printsummary="yes" dir="." fork="yes" haltonfailure="no" showoutput="no" filtertrace="true" timeout="120000"> + <jvmarg value="-Djava.awt.headless=true" /> + <formatter type="brief" usefile="false"/> + <test haltonfailure="no" failureproperty="test_failed" name="${test3.class}"/> + <classpath> + <path refid="test.classpath" /> + </classpath> + </junit> + <fail if="test_failed" status="${exit.code3}" message="*** Third set of Junit tests: Some Tests FAILED ***"/> + <echo>*** Third set of Junit tests: All Tests PASSED ***</echo> + + <echo>Running Fourth set of Junit tests...</echo> + <junit printsummary="yes" dir="." fork="yes" haltonfailure="no" showoutput="no" filtertrace="true" timeout="120000"> + <jvmarg value="-Djava.awt.headless=true" /> + <jvmarg value="-Djava.library.path=${other_lib.dir}" /> + <formatter type="brief" usefile="false"/> + <test haltonfailure="no" failureproperty="test_failed" name="${test4.class}"/> + <classpath> + <path refid="test.classpath" /> + <fileset dir="${other_lib.dir}"> + <include name="*.jar" /> + </fileset> + </classpath> + </junit> + <fail if="test_failed" status="${exit.code4}" message="*** Fourth set of Junit tests: Some Tests FAILED ***"/> + <echo>*** Fourth set of Junit tests: All Tests PASSED ***</echo> + <echo>***************************************************</echo> + <echo>*************** All Tests PASSED *****************</echo> + </target> + + <!-- target for cleaning --> + <target name="clean"> + <delete dir="${build.dir}" /> + </target> +</project> diff --git a/verigraph/pom.xml b/verigraph/pom.xml new file mode 100644 index 0000000..63603a7 --- /dev/null +++ b/verigraph/pom.xml @@ -0,0 +1,213 @@ +<!-- Copyright (c) 2017 Politecnico di Torino and others. All rights reserved. + This program and the accompanying materials are made available under the + terms of the Apache License, Version 2.0 which accompanies this distribution, + and is available at http://www.apache.org/licenses/LICENSE-2.0 --> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <groupId>it.polito.escape</groupId> + <artifactId>verify</artifactId> + <packaging>war</packaging> + <version>0.0.1-SNAPSHOT</version> + <name>verify</name> + <url>http://maven.apache.org</url> + <properties> + <grpc.version>1.0.3</grpc.version><!-- CURRENT_GRPC_VERSION --> + <jersey.version>2.22.1</jersey.version> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + <build> + <finalName>verify</finalName> + <extensions> + <extension> + <groupId>kr.motd.maven</groupId> + <artifactId>os-maven-plugin</artifactId> + <version>1.4.1.Final</version> + </extension> + </extensions> + <plugins> + <plugin> + <groupId>org.xolstice.maven.plugins</groupId> + <artifactId>protobuf-maven-plugin</artifactId> + <version>0.5.0</version> + <configuration> + <protocArtifact>com.google.protobuf:protoc:3.1.0:exe:${os.detected.classifier}</protocArtifact> + <pluginId>grpc-java</pluginId> + <pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}</pluginArtifact> + </configuration> + <executions> + <execution> + <goals> + <goal>compile</goal> + <goal>compile-custom</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>2.5.1</version> + <inherited>true</inherited> + <configuration> + <source>1.8</source> + <target>1.8</target> + </configuration> + </plugin> + </plugins> + <pluginManagement> + <plugins> + <plugin> + <groupId>org.eclipse.m2e</groupId> + <artifactId>lifecycle-mapping</artifactId> + <version>1.0.0</version> + <configuration> + <lifecycleMappingMetadata> + <pluginExecutions> + <pluginExecution> + <pluginExecutionFilter> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-enforcer-plugin</artifactId> + <versionRange>[1.0.0,)</versionRange> + <goals> + <goal>enforce</goal> + </goals> + </pluginExecutionFilter> + <action> + <ignore /> + </action> + </pluginExecution> + </pluginExecutions> + </lifecycleMappingMetadata> + </configuration> + </plugin> + </plugins> + </pluginManagement> + </build> + + <dependencyManagement> + <dependencies> + <dependency> + <groupId>org.glassfish.jersey</groupId> + <artifactId>jersey-bom</artifactId> + <version>${jersey.version}</version> + <type>pom</type> + <scope>import</scope> + </dependency> + </dependencies> + </dependencyManagement> + + <dependencies> + <dependency> + <groupId>org.glassfish.jersey.containers</groupId> + <artifactId>jersey-container-servlet-core</artifactId> + <!-- use the following artifactId if you don't need servlet 2.x compatibility --> + <!-- artifactId>jersey-container-servlet</artifactId --> + </dependency> + + <dependency> + <groupId>org.glassfish.jersey.bundles</groupId> + <artifactId>jaxrs-ri</artifactId> + </dependency> + + <!-- <dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-moxy</artifactId> + </dependency> --> + + <dependency> + <groupId>org.glassfish.jersey.media</groupId> + <artifactId>jersey-media-json-jackson</artifactId> + </dependency> + + <dependency> + <groupId>io.swagger</groupId> + <artifactId>swagger-jersey2-jaxrs</artifactId> + <version>1.5.0</version> + </dependency> + + <dependency> + <groupId>com.googlecode.json-simple</groupId> + <artifactId>json-simple</artifactId> + <version>1.1</version> + </dependency> + + <!-- added to retrieve server path --> + <!-- <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> + <version>3.1.0</version> <scope>provided</scope> </dependency> --> + + <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 --> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + <version>1.5.6</version> + </dependency> + + + <dependency> + <groupId>com.github.fge</groupId> + <artifactId>json-schema-validator</artifactId> + <version>2.2.6</version> + </dependency> + + <!-- http://mvnrepository.com/artifact/org.json/json --> + <dependency> + <groupId>org.json</groupId> + <artifactId>json</artifactId> + <version>20160212</version> + </dependency> + + <!-- https://mvnrepository.com/artifact/junit/junit --> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.12</version> + </dependency> + + + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>javax.servlet-api</artifactId> + <version>3.1.0</version> + <scope>provided</scope> + </dependency> + + <!-- here start dependencies for grpc --> + <dependency> + <groupId>org.apache.thrift</groupId> + <artifactId>libthrift</artifactId> + <version>0.9.1</version> + </dependency> + <dependency> + <groupId>io.grpc</groupId> + <artifactId>grpc-netty</artifactId> + <version>${grpc.version}</version> + </dependency> + <dependency> + <groupId>io.grpc</groupId> + <artifactId>grpc-protobuf</artifactId> + <version>${grpc.version}</version> + </dependency> + <dependency> + <groupId>io.grpc</groupId> + <artifactId>grpc-stub</artifactId> + <version>${grpc.version}</version> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <version>1.9.5</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>com.google.protobuf</groupId> + <artifactId>protobuf-java</artifactId> + <version>3.0.2</version> + </dependency> + + + + </dependencies> + +</project> diff --git a/verigraph/service/src/mcnet/components/Checker.java b/verigraph/service/src/mcnet/components/Checker.java new file mode 100644 index 0000000..3c13d28 --- /dev/null +++ b/verigraph/service/src/mcnet/components/Checker.java @@ -0,0 +1,363 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package mcnet.components; + + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import com.microsoft.z3.BoolExpr; +import com.microsoft.z3.Context; +import com.microsoft.z3.Expr; +import com.microsoft.z3.IntExpr; +import com.microsoft.z3.Model; +import com.microsoft.z3.Solver; +import com.microsoft.z3.Status; + +/**Various checks for specific properties in the network. + * + */ +public class Checker { + + Context ctx; + Network net; + NetContext nctx; + Solver solver; + ArrayList<BoolExpr> constraints; + public BoolExpr [] assertions; + public Status result; + public Model model; + + + public Checker(Context context,NetContext nctx,Network network){ + this.ctx = context; + this.net = network; + this.nctx = nctx; + this.solver = ctx.mkSolver(); + this.constraints = new ArrayList<BoolExpr>(); + } + + /**Resets the constraints + * + */ + public void clearState (){ + this.solver.reset(); + this.constraints = new ArrayList<BoolExpr>(); + } + + /**Checks whether the source provided can reach the destination + * + * @param src + * @param dest + * @return + */ + public IsolationResult checkIsolationProperty (NetworkObject src, NetworkObject dest){ + assert(net.elements.contains(src)); + assert(net.elements.contains(dest)); + solver.push (); + addConstraints(); + + Expr p0 = ctx.mkConst("check_isolation_p0_"+src.getZ3Node()+"_"+dest.getZ3Node(), nctx.packet); + Expr p1 = ctx.mkConst("check_isolation_p1_"+src.getZ3Node()+"_"+dest.getZ3Node(), nctx.packet); + Expr n_0 =ctx.mkConst("check_isolation_n_0_"+src.getZ3Node()+"_"+dest.getZ3Node(), nctx.node); + Expr n_1 =ctx.mkConst("check_isolation_n_1_"+src.getZ3Node()+"_"+dest.getZ3Node(), nctx.node); + IntExpr t_0 = ctx.mkIntConst("check_isolation_t0_"+src.getZ3Node()+"_"+dest.getZ3Node()); + IntExpr t_1 = ctx.mkIntConst("check_isolation_t1_"+src.getZ3Node()+"_"+dest.getZ3Node()); + + // Constraint1 recv(n_0,destNode,p0,t_0) + this.solver.add((BoolExpr)nctx.recv.apply(n_0, dest.getZ3Node(), p0, t_0)); + + // Constraint2 send(srcNode,n_1,p1,t_1) + this.solver.add((BoolExpr)nctx.send.apply(src.getZ3Node(), n_1, p1, t_1)); + + // Constraint3 nodeHasAddr(srcNode,p1.srcAddr) + this.solver.add((BoolExpr)nctx.nodeHasAddr.apply(src.getZ3Node(), nctx.pf.get("src").apply(p1))); + + // Constraint4 p1.origin == srcNode + this.solver.add(ctx.mkEq(nctx.pf.get("origin").apply(p1), src.getZ3Node())); + + // Constraint5 nodeHasAddr(destNode,p1.destAddr) + this.solver.add((BoolExpr)nctx.nodeHasAddr.apply(dest.getZ3Node(), nctx.pf.get("dest").apply(p1))); + + //NON sembrano necessari + // this.solver.add(z3.Or(this.ctx.nodeHasAddr(src.getZ3Node(), this.ctx.packet.src(p0)),\ + // this.ctx.nodeHasAddr(n_0, this.ctx.packet.src(p0)),\ + // this.ctx.nodeHasAddr(n_1, this.ctx.packet.src(p0)))) + //this.solver.add(this.ctx.packet.dest(p1) == this.ctx.packet.dest(p0)) + + // Constraint6 p1.origin == p0.origin + this.solver.add(ctx.mkEq(nctx.pf.get("origin").apply(p1),nctx.pf.get("origin").apply(p0))); + + // Constraint7 nodeHasAddr(destNode, p0.destAddr) + this.solver.add((BoolExpr)nctx.nodeHasAddr.apply(dest.getZ3Node(), nctx.pf.get("dest").apply(p0))); + + result = this.solver.check(); + model = null; + assertions = this.solver.getAssertions(); + if (result == Status.SATISFIABLE){ + model = this.solver.getModel(); + } + this.solver.pop(); + return new IsolationResult(ctx,result, p0, n_0, t_1, t_0, nctx, assertions, model); + } + + + + public IsolationResult CheckIsolationFlowProperty (NetworkObject src, NetworkObject dest){ + assert(net.elements.contains(src)); + assert(net.elements.contains(dest)); + solver.push (); + addConstraints(); + + Expr p = ctx.mkConst("check_isolation_p_"+src.getZ3Node()+"_"+dest.getZ3Node(), nctx.packet); + Expr n_0 =ctx.mkConst("check_isolation_n_0_"+src.getZ3Node()+"_"+dest.getZ3Node(), nctx.node); + Expr n_1 =ctx.mkConst("check_isolation_n_1_"+src.getZ3Node()+"_"+dest.getZ3Node(), nctx.node); + Expr n_2 =ctx.mkConst("check_isolation_n_1_"+src.getZ3Node()+"_"+dest.getZ3Node(), nctx.node); + + IntExpr t_0 = ctx.mkIntConst("check_isolation_t0_"+src.getZ3Node()+"_"+dest.getZ3Node()); + IntExpr t_1 = ctx.mkIntConst("check_isolation_t1_"+src.getZ3Node()+"_"+dest.getZ3Node()); + IntExpr t_2 = ctx.mkIntConst("check_isolation_t2_"+src.getZ3Node()+"_"+dest.getZ3Node()); + + // Constraint1 recv(n_0,destNode,p,t_0) + this.solver.add((BoolExpr)nctx.recv.apply(n_0, dest.getZ3Node(), p, t_0)); + + // Constraint2 send(srcNode,n_1,p1,t_1) + this.solver.add((BoolExpr)nctx.send.apply(src.getZ3Node(), n_1, p, t_1)); + + // Constraint3 nodeHasAddr(srcNode,p.srcAddr) + this.solver.add((BoolExpr)nctx.nodeHasAddr.apply(src.getZ3Node(), nctx.pf.get("src").apply(p))); + + // Constraint4 p.origin == srcNode + this.solver.add(ctx.mkEq(nctx.pf.get("origin").apply(p), src.getZ3Node())); + + + Expr p_2 = ctx.mkConst("check_isolation_p_flow_"+src.getZ3Node()+"_"+dest.getZ3Node(), nctx.packet); + + // Constraint5 there does not exist p_2, n_2, t_2 : + // send(destNode,n_2,p_2,t_2) && + // p_2.srcAddr == p. destAddr && + // p_2.srcPort == p.destPort && + // p_2.destPort == p.srcPort && + // p_2.destt == p.src && + // t_2 < t_0 + this.solver.add(ctx.mkNot(ctx.mkExists(new Expr[]{p_2,n_2,t_2}, + ctx.mkAnd( + (BoolExpr)nctx.send.apply(dest.getZ3Node(), n_2, p_2, t_2), + ctx.mkEq(nctx.pf.get("src").apply(p_2), nctx.pf.get("dest").apply(p)), + ctx.mkEq(nctx.pf.get("src_port").apply(p_2), nctx.pf.get("dest_port").apply(p)), + ctx.mkEq(nctx.pf.get("dest_port").apply(p_2), nctx.pf.get("src_port").apply(p)), + ctx.mkEq(nctx.pf.get("dest").apply(p_2), nctx.pf.get("src").apply(p)), + ctx.mkLt(t_2,t_0)),1,null,null,null,null))); + + + result = this.solver.check(); + model = null; + assertions = this.solver.getAssertions(); + if (result == Status.SATISFIABLE){ + model = this.solver.getModel(); + } + this.solver.pop(); + return new IsolationResult(ctx,result, p, n_0, t_1, t_0, nctx, assertions, model); + } + + + + public IsolationResult CheckNodeTraversalProperty (NetworkObject src, NetworkObject dest, NetworkObject node){ + assert(net.elements.contains(src)); + assert(net.elements.contains(dest)); + solver.push (); + addConstraints(); + + Expr p = ctx.mkConst("check_isolation_p_"+src.getZ3Node()+"_"+dest.getZ3Node(), nctx.packet); + + Expr n_0 =ctx.mkConst("check_isolation_n_0_"+src.getZ3Node()+"_"+dest.getZ3Node(), nctx.node); + Expr n_1 =ctx.mkConst("check_isolation_n_1_"+src.getZ3Node()+"_"+dest.getZ3Node(), nctx.node); + Expr n_2 =ctx.mkConst("check_isolation_n_1_"+src.getZ3Node()+"_"+dest.getZ3Node(), nctx.node); + + IntExpr t_0 = ctx.mkIntConst("check_isolation_t0_"+src.getZ3Node()+"_"+dest.getZ3Node()); + IntExpr t_1 = ctx.mkIntConst("check_isolation_t1_"+src.getZ3Node()+"_"+dest.getZ3Node()); + IntExpr t_2 = ctx.mkIntConst("check_isolation_t2_"+src.getZ3Node()+"_"+dest.getZ3Node()); + + // Constraint1 recv(n_0,destNode,p,t_0) + this.solver.add((BoolExpr)nctx.recv.apply(n_0, dest.getZ3Node(), p, t_0)); + + // Constraint2 send(srcNode,n_1,p1,t_1) + this.solver.add((BoolExpr)nctx.send.apply(src.getZ3Node(), n_1, p, t_1)); + + // Constraint3 nodeHasAddr(srcNode,p.srcAddr) + this.solver.add((BoolExpr)nctx.nodeHasAddr.apply(src.getZ3Node(), nctx.pf.get("src").apply(p))); + + // Constraint4 p.origin == srcNode + this.solver.add(ctx.mkEq(nctx.pf.get("origin").apply(p), src.getZ3Node())); + + + // Constraint5 there does not exist n_2, t_2 : recv(n_2,node,p,t_2) && t_2 < t_0 + this.solver.add(ctx.mkNot(ctx.mkExists(new Expr[]{n_2,t_2}, + ctx.mkAnd( + (BoolExpr)nctx.recv.apply(n_2, node.getZ3Node(), p, t_2), + ctx.mkLt(t_2,t_0)),1,null,null,null,null))); + + // Constraint 6 there does not exist n_2, t_2 : send(node,n_2,p,t_2) && t_2 < t_0 + this.solver.add(ctx.mkNot(ctx.mkExists(new Expr[]{n_2,t_2}, + ctx.mkAnd( + (BoolExpr)nctx.send.apply(node.getZ3Node(), n_2, p, t_2), + ctx.mkLt(t_2,t_0)),1,null,null,null,null))); + + + result = this.solver.check(); + model = null; + assertions = this.solver.getAssertions(); + if (result == Status.SATISFIABLE){ + model = this.solver.getModel(); + } + this.solver.pop(); + return new IsolationResult(ctx,result, p, n_0, t_1, t_0, nctx, assertions, model); + + } + + public IsolationResult CheckLinkTraversalProperty (NetworkObject src, NetworkObject dest, NetworkObject le0, NetworkObject le1){ + assert(net.elements.contains(src)); + assert(net.elements.contains(dest)); + solver.push (); + addConstraints(); + + Expr p = ctx.mkConst("check_isolation_p_"+src.getZ3Node()+"_"+dest.getZ3Node(), nctx.packet); + + Expr n_0 =ctx.mkConst("check_isolation_n_0_"+src.getZ3Node()+"_"+dest.getZ3Node(), nctx.node); + Expr n_1 =ctx.mkConst("check_isolation_n_1_"+src.getZ3Node()+"_"+dest.getZ3Node(), nctx.node); + + IntExpr t_0 = ctx.mkIntConst("check_isolation_t0_"+src.getZ3Node()+"_"+dest.getZ3Node()); + IntExpr t_1 = ctx.mkIntConst("check_isolation_t1_"+src.getZ3Node()+"_"+dest.getZ3Node()); + IntExpr t_2 = ctx.mkIntConst("check_isolation_t2_"+src.getZ3Node()+"_"+dest.getZ3Node()); + + // Constraint1 recv(n_0,destNode,p,t_0) + this.solver.add((BoolExpr)nctx.recv.apply(n_0, dest.getZ3Node(), p, t_0)); + + // Constraint2 send(srcNode,n_1,p1,t_1) + this.solver.add((BoolExpr)nctx.send.apply(src.getZ3Node(), n_1, p, t_1)); + + // Constraint3 nodeHasAddr(srcNode,p.srcAddr) + this.solver.add((BoolExpr)nctx.nodeHasAddr.apply(src.getZ3Node(), nctx.pf.get("src").apply(p))); + + // Constraint4 p.origin == srcNode + this.solver.add(ctx.mkEq(nctx.pf.get("origin").apply(p), src.getZ3Node())); + + // Constraint5 ∃ t_1, t_2 : + // send(linkNode0,linkNode1,p,t_1) && + // recv(linkNode0,linkNode1,p,t_2) && + // t_1 < t_0 && + // t_2 < t_0 + this.solver.add(ctx.mkExists(new Expr[]{t_1,t_2}, + ctx.mkAnd( + (BoolExpr)nctx.send.apply(le0.getZ3Node(), le1.getZ3Node(), p, t_1), + (BoolExpr)nctx.recv.apply(le0.getZ3Node(), le1.getZ3Node(), p, t_2), + ctx.mkLt(t_1,t_0), + ctx.mkLt(t_2,t_0)),1,null,null,null,null)); + + + result = this.solver.check(); + model = null; + assertions = this.solver.getAssertions(); + if (result == Status.SATISFIABLE){ + model = this.solver.getModel(); + } + this.solver.pop(); + return new IsolationResult(ctx,result, p, n_0, t_1, t_0, nctx, assertions, model); + + } + + public Result CheckDataIsolationPropertyCore (NetworkObject src, NetworkObject dest){ + assert(net.elements.contains(src)); + assert(net.elements.contains(dest)); + List<BoolExpr> constr = this.getConstraints(); + Expr p = ctx.mkConst("check_isolation_p_"+src.getZ3Node()+"_"+dest.getZ3Node(), nctx.packet); + + Expr n_0 =ctx.mkConst("check_isolation_n_0_"+src.getZ3Node()+"_"+dest.getZ3Node(), nctx.node); + IntExpr t = ctx.mkIntConst("check_isolation_t_"+src.getZ3Node()+"_"+dest.getZ3Node()); + + // Constraint1 recv(n_0,destNode,p,t) + constr.add((BoolExpr)nctx.recv.apply(n_0, dest.getZ3Node(), p, t)); + + // Constraint2 p.origin == srcNode + this.solver.add(ctx.mkEq(nctx.pf.get("origin").apply(p), src.getZ3Node())); + + this.solver.push(); + + // Constraint3 for each constraint( n -> constraint) + ArrayList<BoolExpr> names =new ArrayList<BoolExpr>(); + for(BoolExpr con : constr){ + BoolExpr n = ctx.mkBoolConst(""+con); + names.add(n); + this.solver.add(ctx.mkImplies(n, con)); + } + + BoolExpr[] nam = new BoolExpr[names.size()]; + result = this.solver.check(names.toArray(nam)); + Result ret =null; + + if (result == Status.SATISFIABLE){ + System.out.println("SAT"); + ret = new Result(ctx,this.solver.getModel()); + }else if(result == Status.UNSATISFIABLE){ + System.out.println("unsat"); + ret = new Result(ctx,this.solver.getUnsatCore()); + } + this.solver.pop(); + return ret; + } + + public DataIsolationResult CheckDataIsolationProperty(NetworkObject src, NetworkObject dest){ + assert(net.elements.contains(src)); + assert(net.elements.contains(dest)); + solver.push (); + addConstraints(); + + Expr p = ctx.mkConst("check_isolation_p_"+src.getZ3Node()+"_"+dest.getZ3Node(), nctx.packet); + + Expr n_0 =ctx.mkConst("check_isolation_n_0_"+src.getZ3Node()+"_"+dest.getZ3Node(), nctx.node); + IntExpr t = ctx.mkIntConst("check_isolation_t_"+src.getZ3Node()+"_"+dest.getZ3Node()); + + // Constraint1 recv(n_0,destNode,p,t) + this.solver.add((BoolExpr)nctx.recv.apply(n_0, dest.getZ3Node(), p, t)); + + // Constraint2 p.origin == srcNode + this.solver.add(ctx.mkEq(nctx.pf.get("origin").apply(p), src.getZ3Node())); + + result = this.solver.check(); + model = null; + assertions = this.solver.getAssertions(); + if (result == Status.SATISFIABLE){ + model = this.solver.getModel(); + } + this.solver.pop(); + return new DataIsolationResult(ctx,result, p, n_0, t, nctx, assertions, model); + } + + + + + public void addConstraints(){ + nctx.addConstraints(solver); + net.addConstraints(solver); + for (NetworkObject el : net.elements) + el.addConstraints(solver); + } + + + public List<BoolExpr> getConstraints(){ + Solver l = ctx.mkSolver(); + nctx.addConstraints(l); + net.addConstraints(l); + for (NetworkObject el : net.elements) + el.addConstraints(l); + return Arrays.asList(l.getAssertions()); + } +} diff --git a/verigraph/service/src/mcnet/components/Core.java b/verigraph/service/src/mcnet/components/Core.java new file mode 100644 index 0000000..c72b9e3 --- /dev/null +++ b/verigraph/service/src/mcnet/components/Core.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package mcnet.components; +import com.microsoft.z3.Context; +import com.microsoft.z3.Solver; + +/**Core component for everything that matters + * + */ +public abstract class Core{ + + final int MAX_PORT = 512; + + /** + * Base class for all objects in the modeling framework + * @param ctx + * @param args + */ + public Core(Context ctx, Object[]... args){ // Object[]... -> The nearest way to implement variable length argument lists + //in Java, in the most generic way. + init(ctx,args); + } + /** + * Override _init for any constructor initialization. Avoids having to explicitly call super.__init__ every Time.class + * @param ctx + * @param args + */ + abstract protected void init(Context ctx,Object[]... args); + + /** + * Add constraints to solver + * @param solver + */ + abstract protected void addConstraints(Solver solver); +} + + diff --git a/verigraph/service/src/mcnet/components/DataIsolationResult.java b/verigraph/service/src/mcnet/components/DataIsolationResult.java new file mode 100644 index 0000000..b90a47f --- /dev/null +++ b/verigraph/service/src/mcnet/components/DataIsolationResult.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package mcnet.components; + +import com.microsoft.z3.BoolExpr; +import com.microsoft.z3.Context; +import com.microsoft.z3.Expr; +import com.microsoft.z3.Model; +import com.microsoft.z3.Status; + + +/**Data structure for the response to a check request for data isolation property + * + */ +public class DataIsolationResult { + + Context ctx; + public NetContext nctx; + public Status result; + public Model model; + public Expr violating_packet,last_hop,last_time,t_1; + public BoolExpr [] assertions; + + public DataIsolationResult(Context ctx,Status result, Expr violating_packet, Expr last_hop, Expr last_time, NetContext nctx, BoolExpr[] assertions, Model model){ + this.ctx = ctx; + this.result = result; + this.violating_packet = violating_packet; + this.last_hop = last_hop; + this.model = model; + this.last_time = last_time; + this.assertions = assertions; + } +} + diff --git a/verigraph/service/src/mcnet/components/IsolationResult.java b/verigraph/service/src/mcnet/components/IsolationResult.java new file mode 100644 index 0000000..1ecaccc --- /dev/null +++ b/verigraph/service/src/mcnet/components/IsolationResult.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package mcnet.components; + +import com.microsoft.z3.BoolExpr; +import com.microsoft.z3.Context; +import com.microsoft.z3.Expr; +import com.microsoft.z3.Model; +import com.microsoft.z3.Status; + +/** + * Data structure for the response to check requests for isolation properties + * + */ +public class IsolationResult { + + Context ctx; + public NetContext nctx; + public Status result; + public Model model; + public Expr violating_packet,last_hop,last_send_time,last_recv_time,t_1; + public BoolExpr [] assertions; + + public IsolationResult(Context ctx,Status result, Expr violating_packet, Expr last_hop, Expr last_send_time, Expr last_recv_time,NetContext nctx, BoolExpr[] assertions, Model model){ + this.ctx = ctx; + this.result = result; + this.violating_packet = violating_packet; + this.last_hop = last_hop; + this.model = model; + this.last_send_time = last_send_time; + this.last_recv_time = last_recv_time; + this.assertions = assertions; + } +} + diff --git a/verigraph/service/src/mcnet/components/NetContext.java b/verigraph/service/src/mcnet/components/NetContext.java new file mode 100644 index 0000000..ece31c5 --- /dev/null +++ b/verigraph/service/src/mcnet/components/NetContext.java @@ -0,0 +1,340 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package mcnet.components; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import com.microsoft.z3.BoolExpr; +import com.microsoft.z3.Constructor; +import com.microsoft.z3.Context; +import com.microsoft.z3.DatatypeExpr; +import com.microsoft.z3.DatatypeSort; +import com.microsoft.z3.EnumSort; +import com.microsoft.z3.Expr; +import com.microsoft.z3.FuncDecl; +import com.microsoft.z3.IntExpr; +import com.microsoft.z3.Solver; +import com.microsoft.z3.Sort; + +import mcnet.netobjs.DumbNode; + +/** + * Basic fields and other things required for model checking. + * + */ +public class NetContext extends Core{ + + + List<BoolExpr> constraints; + List<Core> policies; + + public HashMap<String,NetworkObject> nm; //list of nodes, callable by node name + public HashMap<String,DatatypeExpr> am; // list of addresses, callable by address name + public HashMap<String,FuncDecl> pf; + Context ctx; + public EnumSort node,address; + public FuncDecl src_port,dest_port,nodeHasAddr,addrToNode,send,recv; + public DatatypeSort packet; + + /* Constants definition + - used in the packet proto field */ + public final int HTTP_REQUEST = 1; + public final int HTTP_RESPONSE = 2; + public final int POP3_REQUEST = 3; + public final int POP3_RESPONSE = 4; + + /** + * Context for all of the rest that follows. Every network needs one of these + * @param ctx + * @param args + */ + public NetContext(Context ctx,Object[]... args ){ + super(ctx,args); + + } + + @Override + protected void init(Context ctx, Object[]... args) { + this.ctx = ctx; + nm = new HashMap<String,NetworkObject>(); //list of nodes, callable by node name + am = new HashMap<String,DatatypeExpr>(); // list of addresses, callable by address name + pf= new HashMap<String,FuncDecl>() ; + + mkTypes((String[])args[0],(String[])args[1]); + + constraints = new ArrayList<BoolExpr>(); + policies = new ArrayList<Core>(); + + baseCondition(); + } + + /** + * A policy is a collection of shared algorithms or functions used by multiple components + * (for instance compression or DPI policies etc). + * @param policy + */ + public void AddPolicy (NetworkObject policy){ + policies.add(policy); + } + + @Override + protected void addConstraints(Solver solver) { + BoolExpr[] constr = new BoolExpr[constraints.size()]; + solver.add(constraints.toArray(constr)); + for (Core policy : policies){ + policy.addConstraints(solver); + } + } + + private void mkTypes (String[] nodes, String[] addresses){ + //Nodes in a network + node = ctx.mkEnumSort("Node", nodes); + for(int i=0;i<node.getConsts().length;i++){ + DatatypeExpr fd = (DatatypeExpr)node.getConst(i); + DumbNode dn =new DumbNode(ctx,new Object[]{fd}); + nm.put(fd.toString(),dn); + } + + //Addresses for this network + String[] new_addr = new String[addresses.length+1]; + for(int k=0;k<addresses.length;k++) + new_addr[k] = addresses[k]; + + new_addr[new_addr.length-1] = "null"; + address = ctx.mkEnumSort("Address", new_addr); + for(int i=0;i<address.getConsts().length;i++){ + DatatypeExpr fd = (DatatypeExpr)address.getConst(i); + am.put(fd.toString(),fd); + } + + // Type for packets, contains (some of these are currently represented as relations): + // - src: Source address + // - dest: Destination address + // - origin: Node where the data originated. (Node) + // - body: Packet contents. (Integer) + // - seq: Sequence number for packets. (Integer) + // - options: A representation for IP options. (Integer) + + String[] fieldNames = new String[]{ + "src","dest","inner_src","inner_dest","origin","orig_body","body","seq","proto","emailFrom","url","options","encrypted"}; + Sort[] srt = new Sort[]{ + address,address,address,address,node,ctx.mkIntSort(),ctx.mkIntSort(),ctx.mkIntSort(), + ctx.mkIntSort(),ctx.mkIntSort(),ctx.mkIntSort(),ctx.mkIntSort(),ctx.mkBoolSort()}; + Constructor packetcon = ctx.mkConstructor("packet", "is_packet", fieldNames, srt, null); + packet = ctx.mkDatatypeSort("packet", new Constructor[] {packetcon}); + + for(int i=0;i<fieldNames.length;i++){ + pf.put(fieldNames[i], packet.getAccessors()[0][i]); // pf to get packet's function declarations by name + } + + src_port = ctx.mkFuncDecl("sport", packet, ctx.mkIntSort()); + dest_port = ctx.mkFuncDecl("dport", packet, ctx.mkIntSort()); + + // Some commonly used relations + + // nodeHasAddr: node -> address -> boolean + nodeHasAddr = ctx.mkFuncDecl("nodeHasAddr", new Sort[]{node, address},ctx.mkBoolSort()); + + // addrToNode: address -> node + addrToNode = ctx.mkFuncDecl("addrToNode", address, node); + + // Send and receive both have the form: + // source-> destination -> packet-> int-> bool + + // send: node -> node -> packet-> int-> bool + send = ctx.mkFuncDecl("send", new Sort[]{ node, node, packet, ctx.mkIntSort()},ctx.mkBoolSort()); + + // recv: node -> node -> packet-> int-> bool + recv = ctx.mkFuncDecl("recv", new Sort[]{ node, node, packet, ctx.mkIntSort()},ctx.mkBoolSort()); + + } + + /** + * Set up base conditions for the network + */ + private void baseCondition(){ + // Basic constraints for the overall model + Expr n_0 = ctx.mkConst("ctx_base_n_0", node); + Expr n_1 = ctx.mkConst("ctx_base_n_1", node); + Expr n_2 = ctx.mkConst("ctx_base_n_2", node); + Expr p_0 = ctx.mkConst("ctx_base_p_0", packet); + Expr p_1 = ctx.mkConst("ctx_base_p_1", packet); + IntExpr t_0 = ctx.mkIntConst("ctx_base_t_0"); + IntExpr t_1 = ctx.mkIntConst("ctx_base_t_1"); + + // Constraint1 send(n_0, n_1, p_0, t_0) -> n_0 != n_1 + constraints.add( + ctx.mkForall(new Expr[]{n_0, n_1, p_0, t_0}, + ctx.mkImplies((BoolExpr)send.apply(n_0, n_1, p_0, t_0),ctx.mkNot(ctx.mkEq( n_0, n_1))),1,null,null,null,null)); + + // Constraint2 recv(n_0, n_1, p_0, t_0) -> n_0 != n_1 + constraints.add( + ctx.mkForall(new Expr[]{n_0, n_1, p_0, t_0}, + ctx.mkImplies((BoolExpr)recv.apply(n_0, n_1, p_0, t_0),ctx.mkNot(ctx.mkEq( n_0, n_1))),1,null,null,null,null)); + + // Constraint3 send(n_0, n_1, p_0, t_0) -> p_0.src != p_0.dest + constraints.add( + ctx.mkForall(new Expr[]{n_0, n_1, p_0, t_0}, + ctx.mkImplies((BoolExpr)send.apply(n_0, n_1, p_0, t_0), + ctx.mkNot(ctx.mkEq( pf.get("src").apply(p_0), pf.get("dest").apply(p_0)))),1,null,null,null,null)); + + // Constraint4 recv(n_0, n_1, p_0, t_0) -> p_0.src != p_0.dest + constraints.add( + ctx.mkForall(new Expr[]{n_0, n_1, p_0, t_0}, + ctx.mkImplies((BoolExpr)recv.apply(n_0, n_1, p_0, t_0), + ctx.mkNot(ctx.mkEq(pf.get("src").apply(p_0),pf.get("dest").apply(p_0)))),1,null,null,null,null)); + + // Constraint5 recv(n_0, n_1, p, t_0) -> send(n_0, n_1, p, t_1) && t_1 < t_0 + constraints.add( + ctx.mkForall(new Expr[]{n_0, n_1, p_0, t_0}, + ctx.mkImplies((BoolExpr)recv.apply(n_0, n_1, p_0, t_0), + ctx.mkExists(new Expr[]{t_1}, + ctx.mkAnd((BoolExpr)send.apply(n_0, n_1, p_0, t_1), + ctx.mkLt(t_1, t_0)),1,null,null,null,null)),1,null,null,null,null)); + + // Constraint6 send(n_0, n_1, p, t_0) -> p.src_port > 0 && p.dest_port < MAX_PORT + constraints.add( + ctx.mkForall(new Expr[]{n_0, n_1, p_0, t_0}, + ctx.mkImplies((BoolExpr)send.apply(n_0, n_1, p_0, t_0), + ctx.mkAnd( ctx.mkGe((IntExpr)src_port.apply(p_0),(IntExpr)ctx.mkInt(0)), + ctx.mkLt((IntExpr)src_port.apply(p_0),(IntExpr) ctx.mkInt(MAX_PORT)))),1,null,null,null,null)); + + // Constraint7 recv(n_0, n_1, p, t_0) -> p.src_port > 0 && p.dest_port < MAX_PORT + constraints.add( + ctx.mkForall(new Expr[]{n_0, n_1, p_0, t_0}, + ctx.mkImplies((BoolExpr)recv.apply(n_0, n_1, p_0, t_0), + ctx.mkAnd( ctx.mkGe((IntExpr)dest_port.apply(p_0),(IntExpr)ctx.mkInt(0)), + ctx.mkLt((IntExpr)dest_port.apply(p_0),(IntExpr) ctx.mkInt(MAX_PORT)))),1,null,null,null,null)); + + // Constraint8 recv(n_0, n_1, p_0, t_0) -> t_0 > 0 + constraints.add( + ctx.mkForall(new Expr[]{n_0, n_1, p_0, t_0}, + ctx.mkImplies((BoolExpr)recv.apply(n_0, n_1, p_0, t_0), + ctx.mkGt(t_0,ctx.mkInt(0))),1,null,null,null,null)); + + // Constraint9 send(n_0, n_1, p_0, t_0) -> t_0 > 0 + constraints.add( + ctx.mkForall(new Expr[]{n_0, n_1, p_0, t_0}, + ctx.mkImplies((BoolExpr)send.apply(n_0, n_1, p_0, t_0), + ctx.mkGt(t_0,ctx.mkInt(0))),1,null,null,null,null)); + + // Extra constriants for supporting the VPN gateway + constraints.add( + ctx.mkForall(new Expr[]{n_0, n_1, p_0, t_0}, + ctx.mkImplies( + ctx.mkAnd((BoolExpr)send.apply(n_0, n_1, p_0, t_0), + ctx.mkNot(ctx.mkEq(this.pf.get("inner_src").apply(p_0), this.am.get("null")))), + ctx.mkNot(ctx.mkEq(this.pf.get("inner_src").apply(p_0), this.pf.get("inner_dest").apply(p_0)))),1,null,null,null,null)); + + constraints.add( + ctx.mkForall(new Expr[]{n_0, n_1, p_0, t_0}, + ctx.mkImplies( + ctx.mkAnd((BoolExpr)send.apply(n_0, n_1, p_0, t_0), + ctx.mkEq(this.pf.get("inner_src").apply(p_0), this.am.get("null"))), + ctx.mkEq(this.pf.get("inner_src").apply(p_0), this.pf.get("inner_dest").apply(p_0))),1,null,null,null,null)); + + constraints.add( + ctx.mkForall(new Expr[]{n_0, n_1, p_0, t_0}, + ctx.mkImplies( + ctx.mkAnd((BoolExpr)send.apply(n_0, n_1, p_0, t_0), + ctx.mkEq(this.pf.get("inner_dest").apply(p_0), this.am.get("null"))), + ctx.mkEq(this.pf.get("inner_src").apply(p_0), this.pf.get("inner_dest").apply(p_0))),1,null,null,null,null)); + + constraints.add( + ctx.mkForall(new Expr[]{n_0, n_1, p_0, t_0}, + ctx.mkImplies( + ctx.mkAnd((BoolExpr)recv.apply(n_0, n_1, p_0, t_0), + ctx.mkNot(ctx.mkEq(this.pf.get("inner_src").apply(p_0), this.am.get("null")))), + ctx.mkNot(ctx.mkEq(this.pf.get("inner_src").apply(p_0), this.pf.get("inner_dest").apply(p_0)))),1,null,null,null,null)); + + constraints.add( + ctx.mkForall(new Expr[]{n_0, n_1, p_0, t_0}, + ctx.mkImplies( + ctx.mkAnd((BoolExpr)recv.apply(n_0, n_1, p_0, t_0), + ctx.mkEq(this.pf.get("inner_src").apply(p_0), this.am.get("null"))), + ctx.mkEq(this.pf.get("inner_src").apply(p_0), this.pf.get("inner_dest").apply(p_0))),1,null,null,null,null)); + + constraints.add( + ctx.mkForall(new Expr[]{n_0, n_1, p_0, t_0}, + ctx.mkImplies( + ctx.mkAnd((BoolExpr)recv.apply(n_0, n_1, p_0, t_0), + ctx.mkEq(this.pf.get("inner_dest").apply(p_0), this.am.get("null"))), + ctx.mkEq(this.pf.get("inner_src").apply(p_0), this.pf.get("inner_dest").apply(p_0))),1,null,null,null,null)); + + constraints.add( + ctx.mkForall(new Expr[]{n_0, n_1, p_0, t_0, n_2, p_1, t_1}, + ctx.mkImplies( + ctx.mkAnd( + ctx.mkLt(t_1, t_0), + (BoolExpr)send.apply(n_0, n_1, p_0, t_0), + (BoolExpr)this.pf.get("encrypted").apply(p_1), + (BoolExpr)recv.apply(n_2, n_0, p_1, t_1), + (BoolExpr)this.pf.get("encrypted").apply(p_0)), + ctx.mkAnd( + ctx.mkEq(this.pf.get("inner_src").apply(p_1), this.pf.get("inner_src").apply(p_0)), + ctx.mkEq(this.pf.get("inner_dest").apply(p_1), this.pf.get("inner_dest").apply(p_0)), + ctx.mkEq(this.pf.get("origin").apply(p_1), this.pf.get("origin").apply(p_0)), + ctx.mkEq(this.pf.get("orig_body").apply(p_1), this.pf.get("orig_body").apply(p_0)), + ctx.mkEq(this.pf.get("body").apply(p_1), this.pf.get("body").apply(p_0)), + ctx.mkEq(this.pf.get("seq").apply(p_1), this.pf.get("seq").apply(p_0)), + ctx.mkEq(this.pf.get("proto").apply(p_1), this.pf.get("proto").apply(p_0)), + ctx.mkEq(this.pf.get("emailFrom").apply(p_1), this.pf.get("emailFrom").apply(p_0)), + ctx.mkEq(this.pf.get("url").apply(p_1), this.pf.get("url").apply(p_0)), + ctx.mkEq(this.pf.get("options").apply(p_1), this.pf.get("options").apply(p_0)))),1,null,null,null,null) + ); + } + + /** + * Two packets have equal headers + * @param p1 + * @param p2 + * @return + */ + public BoolExpr PacketsHeadersEqual(Expr p1, Expr p2){ + return ctx.mkAnd(new BoolExpr[]{ + ctx.mkEq(pf.get("src").apply(p1), pf.get("src").apply(p2)), + ctx.mkEq(pf.get("dest").apply(p1), pf.get("dest").apply(p2)), + ctx.mkEq(pf.get("origin").apply(p1), pf.get("origin").apply(p2)), + ctx.mkEq(pf.get("seq").apply(p1), pf.get("seq").apply(p2)), + ctx.mkEq(src_port.apply(p1), src_port.apply(p2)), + ctx.mkEq(dest_port.apply(p1), dest_port.apply(p2)), + ctx.mkEq(pf.get("options").apply(p1), pf.get("options").apply(p2))}); + } + + /** + * Two packets have equal bodies + * @param p1 + * @param p2 + * @return + */ + public BoolExpr PacketContentEqual(Expr p1, Expr p2){ + return ctx.mkEq(pf.get("body").apply(p1), pf.get("body").apply(p2)); + } + + + /* seems to be useless + * + public Function failurePredicate (NetContext context) + { + return (NetworkObject node) -> ctx.mkNot(context.failed (node.z3Node)); + + }*/ + + public BoolExpr destAddrPredicate (Expr p, DatatypeExpr address){ + return ctx.mkEq(pf.get("dest").apply(p),address); + } + + public BoolExpr srcAddrPredicate (Expr p, DatatypeExpr address){ + return ctx.mkEq(pf.get("src").apply(p),address); + } + +}
\ No newline at end of file diff --git a/verigraph/service/src/mcnet/components/Network.java b/verigraph/service/src/mcnet/components/Network.java new file mode 100644 index 0000000..c04f771 --- /dev/null +++ b/verigraph/service/src/mcnet/components/Network.java @@ -0,0 +1,296 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package mcnet.components; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.microsoft.z3.BoolExpr; +import com.microsoft.z3.Context; +import com.microsoft.z3.DatatypeExpr; +import com.microsoft.z3.Expr; +import com.microsoft.z3.IntExpr; +import com.microsoft.z3.Solver; +import com.microsoft.z3.Z3Exception; + +/**Model for a network, encompasses routing and wiring + * + */ +public class Network extends Core{ + + Context ctx; + NetContext nctx; + List<BoolExpr> constraints; + List<NetworkObject> elements; + + + + public Network(Context ctx,Object[]... args) { + super(ctx, args); + } + + @Override + protected void init(Context ctx, Object[]... args) { + this.ctx = ctx; + this.nctx = (NetContext) args[0][0]; + constraints = new ArrayList<BoolExpr>(); + elements = new ArrayList<NetworkObject>(); + + } + + /**Composes the network linking the configured network objects + * + * @param elements + */ + public void attach (NetworkObject ... elements){ + for(NetworkObject el : elements) + this.elements.add(el); + } + + @Override + protected void addConstraints(Solver solver) { + try { + BoolExpr[] constr = new BoolExpr[constraints.size()]; + solver.add(constraints.toArray(constr)); + } catch (Z3Exception e) { + e.printStackTrace(); + } + } + + /** + * Specify host to address mapping. + * Handles the case in which we have more than one address for a node + * @param addrmap + */ + public void setAddressMappings(ArrayList<Tuple<NetworkObject,ArrayList<DatatypeExpr>>> addrmap){ + // Set address mapping for nodes. + for (Tuple<NetworkObject,ArrayList<DatatypeExpr>> entry : addrmap) { + NetworkObject node=entry._1; + List<DatatypeExpr> addr=entry._2; + Expr a_0 = ctx.mkConst(node+"_address_mapping_a_0",nctx.address); + ArrayList<BoolExpr> or_clause = new ArrayList<BoolExpr>(); + + // Constraint 1 addrToNode(foreach ad in addr) = node + for (DatatypeExpr ad : addr){ + constraints.add(ctx.mkEq(nctx.addrToNode.apply(ad), node.getZ3Node())); + or_clause.add(ctx.mkEq(a_0,ad)); + } + BoolExpr[] orClause = new BoolExpr[or_clause.size()]; + + // Constraint 2 nodeHasAddr(node, a_0) == Or(foreach ad in addr (a_0 == ad)) + // Note we need the iff here to make sure that we set nodeHasAddr to false + // for other addresses. + constraints.add(ctx.mkForall(new Expr[]{a_0}, + ctx.mkEq(ctx.mkOr(or_clause.toArray(orClause)), nctx.nodeHasAddr.apply(node.getZ3Node(), a_0)),1,null,null,null,null)); + } + } + + + + /** + * Don't forward packets addressed to node + * @param node + */ + public void saneSend(NetworkObject node){ + Expr n_0 = ctx.mkConst(node+"_saneSend_n_0", nctx.node); + Expr p_0 = ctx.mkConst(node+"_saneSend_p_0", nctx.packet); + IntExpr t_0 = ctx.mkIntConst(node+"_saneSend_t_0"); + // Constant: node + //Constraint send(node, n_0, p, t_0) -> !nodeHasAddr(node, p.dest) + constraints.add( + ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies((BoolExpr)nctx.send.apply(node.getZ3Node(),n_0, p_0, t_0), + ctx.mkNot((BoolExpr)nctx.nodeHasAddr.apply( node.getZ3Node(), + nctx.pf.get("dest").apply(p_0)))),1,null,null,null,null)); + } + + /** + * Node sends all traffic through gateway + * @param node + * @param gateway + */ + public void setGateway (NetworkObject node, NetworkObject gateway){ + // SetGateway(self, node, gateway): All packets from node are sent through gateway + Expr n_0 = ctx.mkConst(node+"_gateway_n_0", nctx.node); + Expr p_0 = ctx.mkConst(node+"_gateway_p_0", nctx.packet); + IntExpr t_0 = ctx.mkIntConst(node+"_gateway_t_0"); + + //Constraint send(node, n_0, p_0, t_0) -> n_0 = gateway + constraints.add( + ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies( + (BoolExpr)nctx.send.apply(node.getZ3Node(), n_0, p_0, t_0), + ctx.mkEq(n_0,gateway.getZ3Node())),1,null,null,null,null)); + +// constraints.add(ctx.mkForall(new Expr[]{n_0, p_0, t_0}, +// ctx.mkImplies((BoolExpr)nctx.recv.apply(n_0, node.getZ3Node(), p_0, t_0), +// ctx.mkEq(n_0,gateway.getZ3Node())),1,null,null,null,null)); + } + + /** + * Assigns a specific routing table to a network object. Routing entries in the form: address -> node + * @param node + * @param routing_table + */ + public void routingTable (NetworkObject node,ArrayList<Tuple<DatatypeExpr,NetworkObject>> routing_table){ + compositionPolicy(node,routing_table); + } + + /** + * Composition policies steer packets between middleboxes. + * @param node + * @param policy + */ + public void compositionPolicy (NetworkObject node,ArrayList<Tuple<DatatypeExpr,NetworkObject>> policy){ + //Policy is of the form predicate -> node + Expr p_0 = ctx.mkConst(node+"_composition_p_0", nctx.packet); + Expr n_0 = ctx.mkConst(node+"_composition_n_0", nctx.node); + Expr t_0 = ctx.mkIntConst(node+"_composition_t_0"); + + HashMap<String,ArrayList<BoolExpr>> collected = new HashMap<String,ArrayList<BoolExpr>>(); + HashMap<String,NetworkObject> node_dict = new HashMap<String,NetworkObject>(); + BoolExpr predicates; + for(int y=0;y<policy.size();y++){ + Tuple<DatatypeExpr,NetworkObject> tp = policy.get(y); + if(collected.containsKey(""+tp._2)) collected.get(""+tp._2).add(nctx.destAddrPredicate(p_0,tp._1)); + else{ + ArrayList<BoolExpr> alb = new ArrayList<BoolExpr>(); + alb.add(nctx.destAddrPredicate(p_0,tp._1)); + collected.put(""+tp._2,alb); + } + node_dict.put(""+tp._2, tp._2); + } + + //Constraint foreach rtAddr,rtNode in rt( send(node, n_0, p_0, t_0) && + // Or(foreach rtAddr in rt destAddrPredicate(p_0,rtAddr)) -> n_0 == rtNode ) + for (Map.Entry<String,ArrayList<BoolExpr>> entry : collected.entrySet()) { + BoolExpr[] pred = new BoolExpr[entry.getValue().size()]; + predicates = ctx.mkOr(entry.getValue().toArray(pred)); + + constraints.add(ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies(ctx.mkAnd((BoolExpr)nctx.send.apply(node.getZ3Node(), n_0, p_0, t_0), predicates), + ctx.mkEq(n_0, node_dict.get(entry.getKey()).getZ3Node())),1,null,null,null,null)); + } + } + + /** + * Routing entries are in the form: address -> node. Also allows packet to be sent to another box for further processing + * @param node + * @param routing_table + * @param shunt_node + */ + public void routingTableShunt (NetworkObject node,ArrayList<Tuple<DatatypeExpr,NetworkObject>> routing_table,NetworkObject shunt_node){ + compositionPolicyShunt(node,routing_table,shunt_node); + } + + /** + * Composition policies steer packets between middleboxes.Policy is in the form: predicate -> node + * @param node + * @param routing_table + * @param shunt_node + */ + public void compositionPolicyShunt (NetworkObject node,ArrayList<Tuple<DatatypeExpr,NetworkObject>> routing_table,NetworkObject shunt_node){ + Expr p_0 = ctx.mkConst(node+"_composition_p_0", nctx.packet); + Expr n_0 = ctx.mkConst(node+"_composition_n_0", nctx.node); + Expr t_0 = ctx.mkIntConst(node+"_composition_t_0"); + + HashMap<String,ArrayList<BoolExpr>> collected = new HashMap<String,ArrayList<BoolExpr>>(); + HashMap<String,NetworkObject> node_dict = new HashMap<String,NetworkObject>(); + BoolExpr predicates; + for(int y=0;y<routing_table.size();y++){ + Tuple<DatatypeExpr,NetworkObject> tp = routing_table.get(y); + if(collected.containsKey(""+tp._2)) collected.get(""+tp._2).add(nctx.destAddrPredicate(p_0,tp._1)); + else{ + ArrayList<BoolExpr> alb = new ArrayList<BoolExpr>(); + alb.add(nctx.destAddrPredicate(p_0,tp._1)); + collected.put(""+tp._2,alb); + } + node_dict.put(""+tp._2, tp._2); + } + + //Constraint foreach rtAddr,rtNode in rt( send(node, n_0, p_0, t_0) && + // Or(foreach rtAddr in rt destAddrPredicate(p_0,rtAddr)) -> n_0 == rtNode ) + for (Map.Entry<String,ArrayList<BoolExpr>> entry : collected.entrySet()) { + BoolExpr[] pred = new BoolExpr[entry.getValue().size()]; + predicates = ctx.mkOr(entry.getValue().toArray(pred)); + + constraints.add(ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies(ctx.mkAnd((BoolExpr)nctx.send.apply(node.getZ3Node(), n_0, p_0, t_0), predicates), + ctx.mkOr(ctx.mkEq(n_0, node_dict.get(entry.getKey()).getZ3Node()),ctx.mkEq(n_0, shunt_node.getZ3Node()))),1,null,null,null,null)); + } + + } + +// public void SimpleIsolation (NetworkObject node, ArrayList<DatatypeExpr> addresses){ +// Expr p = ctx.mkConst(node+"_s_p", nctx.packet); +// Expr n = ctx.mkConst(node+"_s_n", nctx.node); +// IntExpr t = ctx.mkInt(node+"_s_t"); +// +// BoolExpr[] a_pred= new BoolExpr[addresses.size()]; +// for(int y=0;y<addresses.size();y++){ +// DatatypeExpr de = addresses.get(y); +// a_pred[y] = ctx.mkOr(ctx.mkEq(nctx.pf.get("src").apply(p), de),ctx.mkEq(nctx.pf.get("dest").apply(p), de)); +// } +// +// constraints.add( +// ctx.mkForall(new Expr[]{p, n, t}, +// ctx.mkImplies((BoolExpr)nctx.recv.apply(n, node.getZ3Node(), p, t), +// ctx.mkOr(a_pred)),1,null,null,null,null)); +// constraints.add( +// ctx.mkForall(new Expr[]{p, n, t}, +// ctx.mkImplies((BoolExpr)nctx.send.apply(node.getZ3Node(), n, p, t), +// ctx.mkOr(a_pred)),1,null,null,null,null)); +// } + + + /** + * Set isolation constraints on a node. + * Doesn't need to be set but useful when interfering policies are in play. + * @param node + * @param adjacencies + * + */ + public void SetIsolationConstraint ( NetworkObject node, ArrayList<NetworkObject> adjacencies){ + + Expr n_0 = ctx.mkConst(node+"_isolation_n_0", nctx.node); + Expr p_0 = ctx.mkConst(node+"_isolation_p_0", nctx.packet); + IntExpr t_0 = ctx.mkInt(node+"_isolation_t_0"); + + BoolExpr[] adj = new BoolExpr[adjacencies.size()]; + for(int y=0;y<adjacencies.size();y++){ + NetworkObject no = adjacencies.get(y); + adj[y] = ctx.mkEq(n_0,no.getZ3Node()); + } + BoolExpr clause = ctx.mkOr(adj); + + constraints.add(ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies((BoolExpr)nctx.send.apply(node.getZ3Node(), n_0, p_0, t_0), + clause),1,null,null,null,null)); + constraints.add(ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies((BoolExpr)nctx.recv.apply(n_0, node.getZ3Node(), p_0, t_0), + clause),1,null,null,null,null)); + } + + /** + * Return all currently attached endhosts + * @return NetworkObject + */ + public List<String> EndHosts(){ + List<String> att_nos = new ArrayList<String>(); + for(NetworkObject el :elements){ + if(el.isEndHost){ + System.out.println("el: "+el); + att_nos.add(el.getZ3Node().toString()); + } + } + return att_nos; + } +} diff --git a/verigraph/service/src/mcnet/components/NetworkObject.java b/verigraph/service/src/mcnet/components/NetworkObject.java new file mode 100644 index 0000000..0de3937 --- /dev/null +++ b/verigraph/service/src/mcnet/components/NetworkObject.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package mcnet.components; + +import com.microsoft.z3.Context; +import com.microsoft.z3.DatatypeExpr; + +/** Represents a generic network object. + * + */ +public abstract class NetworkObject extends Core{ + + public NetworkObject(Context ctx,Object[]... args) { + super(ctx,args); + } + + protected DatatypeExpr z3Node; + protected boolean isEndHost; + /** + * Get a reference to the z3 node this class wraps around + * @return + */ + abstract public DatatypeExpr getZ3Node(); + + public String toString(){ + return z3Node.toString(); + } + + //There is probably an error: z3Node.hashCode = 0 because AST.hashCode() has always hash=0 + /*public int hashCode(){ + return z3Node.hashCode(); + }*/ + + /** + * A simple way to determine the set of endhosts + * @return + */ + public boolean isEndHost(){ + return isEndHost; + } + + /** + * Wrap methods to set policy + * @param policy + * @throws UnsupportedOperationException + */ + void setPolicy (Object policy) throws UnsupportedOperationException{ + throw new UnsupportedOperationException(); + } +} diff --git a/verigraph/service/src/mcnet/components/Result.java b/verigraph/service/src/mcnet/components/Result.java new file mode 100644 index 0000000..acb23f1 --- /dev/null +++ b/verigraph/service/src/mcnet/components/Result.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package mcnet.components; + +import com.microsoft.z3.BoolExpr; +import com.microsoft.z3.Context; +import com.microsoft.z3.Model; + +/**Data structure for the core of the response to a check request for data isolation property + * + */ +public class Result { + Context ctx; + public Model model; + public BoolExpr[] unsat_core; + +/** + * + * @param ctx + * @param model + */ + public Result(Context ctx, Model model){ + this.ctx = ctx; + this.model = model; + } + +/** + * + * @param ctx + * @param unsat_core + */ + public Result(Context ctx, BoolExpr[] unsat_core){ + this.ctx = ctx; + this.unsat_core = unsat_core; +} +} diff --git a/verigraph/service/src/mcnet/components/Tuple.java b/verigraph/service/src/mcnet/components/Tuple.java new file mode 100644 index 0000000..849d607 --- /dev/null +++ b/verigraph/service/src/mcnet/components/Tuple.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package mcnet.components; + +/** A data structure which is an utility to make a generic couple of objects with different types in Java + * + */ +public class Tuple<T, U> { + public final T _1; + public final U _2; + + + public Tuple(T arg1,U arg2) { + super(); + this._1 = arg1; + this._2 = arg2; + } + + public Tuple(){ + this._1 = null; + this._2 = null; + } + + @Override + public String toString() { + return String.format("(%s, %s)", _1, _2); + } + }
\ No newline at end of file diff --git a/verigraph/service/src/mcnet/netobjs/AclFirewall.java b/verigraph/service/src/mcnet/netobjs/AclFirewall.java new file mode 100644 index 0000000..4ae3421 --- /dev/null +++ b/verigraph/service/src/mcnet/netobjs/AclFirewall.java @@ -0,0 +1,123 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package mcnet.netobjs; + +import java.util.ArrayList; +import java.util.List; + +import com.microsoft.z3.BoolExpr; +import com.microsoft.z3.Context; +import com.microsoft.z3.DatatypeExpr; +import com.microsoft.z3.Expr; +import com.microsoft.z3.FuncDecl; +import com.microsoft.z3.IntExpr; +import com.microsoft.z3.Solver; +import com.microsoft.z3.Sort; + +import mcnet.components.NetContext; +import mcnet.components.Network; +import mcnet.components.NetworkObject; +import mcnet.components.Tuple; + +/** Represents a Firewall with the associated Access Control List + * + */ +public class AclFirewall extends NetworkObject{ + + List<BoolExpr> constraints; + Context ctx; + DatatypeExpr fw; + ArrayList<Tuple<DatatypeExpr,DatatypeExpr>> acls; + Network net; + NetContext nctx; + FuncDecl acl_func; + + public AclFirewall(Context ctx, Object[]... args) { + super(ctx, args); + } + + @Override + protected void init(Context ctx, Object[]... args) { + this.ctx = ctx; + isEndHost=false; + constraints = new ArrayList<BoolExpr>(); + acls = new ArrayList<Tuple<DatatypeExpr,DatatypeExpr>>(); + z3Node = ((NetworkObject)args[0][0]).getZ3Node(); + fw = z3Node; + net = (Network)args[0][1]; + nctx = (NetContext)args[0][2]; + net.saneSend(this); + firewallSendRules(); + } + + /** + * Wrap add acls + * @param policy + */ + public void setPolicy(ArrayList<Tuple<DatatypeExpr, DatatypeExpr>> policy){ + addAcls(policy); + } + + public void addAcls(ArrayList<Tuple<DatatypeExpr,DatatypeExpr>> acls){ + this.acls.addAll(acls); + } + + @Override + public DatatypeExpr getZ3Node() { + return fw; + } + + + @Override + protected void addConstraints(Solver solver) { + BoolExpr[] constr = new BoolExpr[constraints.size()]; + solver.add(constraints.toArray(constr)); + aclConstraints(solver); + } + + private void firewallSendRules (){ + Expr p_0 = ctx.mkConst(fw+"_firewall_send_p_0", nctx.packet); + Expr n_0 = ctx.mkConst(fw+"_firewall_send_n_0", nctx.node); + Expr n_1 = ctx.mkConst(fw+"_firewall_send_n_1", nctx.node); + IntExpr t_0 = ctx.mkIntConst(fw+"_firewall_send_t_0"); + IntExpr t_1 = ctx.mkIntConst(fw+"_firewall_send_t_1"); + acl_func = ctx.mkFuncDecl(fw+"_acl_func", new Sort[]{nctx.address, nctx.address},ctx.mkBoolSort()); + + //Constraint1 send(fw, n_0, p, t_0) -> (exist n_1,t_1 : (recv(n_1, fw, p, t_1) && + // t_1 < t_0 && !acl_func(p.src,p.dest)) + constraints.add( + ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies( + (BoolExpr)nctx.send.apply(new Expr[]{ fw, n_0, p_0, t_0}), + ctx.mkExists(new Expr[]{t_1}, + ctx.mkAnd(ctx.mkLt(t_1,t_0), + ctx.mkExists(new Expr[]{n_1}, + nctx.recv.apply(n_1, fw, p_0, t_1),1,null,null,null,null), + ctx.mkNot((BoolExpr)acl_func.apply(nctx.pf.get("src").apply(p_0), nctx.pf.get("dest").apply(p_0)))),1,null,null,null,null)),1,null,null,null,null)); + + } + + private void aclConstraints(Solver solver){ + if (acls.size() == 0) + return; + Expr a_0 = ctx.mkConst(fw+"_firewall_acl_a_0", nctx.address); + Expr a_1 = ctx.mkConst(fw+"_firewall_acl_a_1", nctx.address); + BoolExpr[] acl_map = new BoolExpr[acls.size()]; + for(int y=0;y<acls.size();y++){ + Tuple<DatatypeExpr,DatatypeExpr> tp = acls.get(y); + acl_map[y] = ctx.mkOr(ctx.mkAnd(ctx.mkEq(a_0,tp._1),ctx.mkEq(a_1,tp._2)), ctx.mkAnd(ctx.mkEq(a_0,tp._2),ctx.mkEq(a_1,tp._1))); + } + //Constraint2 acl_func(a_0,a_1) == or(foreach ip1,ip2 in acl_map ((a_0 == ip1 && a_1 == ip2)||(a_0 == ip2 && a_1 == ip1))) + solver.add(ctx.mkForall(new Expr[]{a_0, a_1}, + ctx.mkEq( + acl_func.apply(a_0, a_1), + ctx.mkOr(acl_map)),1,null,null,null,null)); + } +}
\ No newline at end of file diff --git a/verigraph/service/src/mcnet/netobjs/DumbNode.java b/verigraph/service/src/mcnet/netobjs/DumbNode.java new file mode 100644 index 0000000..012ff40 --- /dev/null +++ b/verigraph/service/src/mcnet/netobjs/DumbNode.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package mcnet.netobjs; + +import com.microsoft.z3.Context; +import com.microsoft.z3.DatatypeExpr; +import com.microsoft.z3.Solver; + +import mcnet.components.NetworkObject; + +/** + * This is just a wrapper around z3 instances. The idea is that by using this we perhaps need to have + * fewer (or no) ifs to deal with the case where we don't instantiate an object for a node + * + */ +public class DumbNode extends NetworkObject { + public DumbNode(Context ctx, Object[]... args){ + super(ctx,args); + } + + @Override + protected void addConstraints(Solver solver) { + return; + } + + @Override + protected void init(Context ctx, Object[]... args) { + isEndHost=true; + this.z3Node = (DatatypeExpr)args[0][0]; + } + @Override + public DatatypeExpr getZ3Node() { + return z3Node; + } +} diff --git a/verigraph/service/src/mcnet/netobjs/EndHost.java b/verigraph/service/src/mcnet/netobjs/EndHost.java new file mode 100644 index 0000000..99cf732 --- /dev/null +++ b/verigraph/service/src/mcnet/netobjs/EndHost.java @@ -0,0 +1,100 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package mcnet.netobjs; + +import java.util.ArrayList; +import java.util.List; + +import com.microsoft.z3.BoolExpr; +import com.microsoft.z3.Context; +import com.microsoft.z3.DatatypeExpr; +import com.microsoft.z3.Expr; +import com.microsoft.z3.IntExpr; +import com.microsoft.z3.Solver; + +import mcnet.components.NetContext; +import mcnet.components.Network; +import mcnet.components.NetworkObject; +/** + * End host network objects + * + */ +public class EndHost extends NetworkObject{ + + List<BoolExpr> constraints; + Context ctx; + DatatypeExpr node; + Network net; + NetContext nctx; + + public EndHost(Context ctx, Object[]... args) { + super(ctx, args); + } + + @Override + protected void init(Context ctx, Object[]... args) { + this.ctx = ctx; + isEndHost=true; + constraints = new ArrayList<BoolExpr>(); + z3Node = ((NetworkObject)args[0][0]).getZ3Node(); + node = z3Node; + net = (Network)args[0][1]; + nctx = (NetContext)args[0][2]; + endHostRules(); + } + + @Override + public DatatypeExpr getZ3Node() { + return node; + } + + @Override + protected void addConstraints(Solver solver) { + BoolExpr[] constr = new BoolExpr[constraints.size()]; + solver.add(constraints.toArray(constr)); + } + + public void endHostRules (){ + Expr n_0 = ctx.mkConst("eh_"+node+"_n_0", nctx.node); + IntExpr t_0 = ctx.mkIntConst("eh_"+node+"_t_0"); + Expr p_0 = ctx.mkConst("eh_"+node+"_p_0", nctx.packet); + + //Constraint1 send(node, n_0, p, t_0) -> nodeHasAddr(node,p.src) + constraints.add( + ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies( + (BoolExpr)nctx.send.apply( new Expr[]{ node, n_0, p_0, t_0}), + (BoolExpr)nctx.nodeHasAddr.apply(new Expr[]{node, nctx.pf.get("src").apply(p_0)})),1,null,null,null,null)); + //Constraint2 send(node, n_0, p, t_0) -> p.origin == node + constraints.add( + ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies( + (BoolExpr)nctx.send.apply( new Expr[]{ node, n_0, p_0, t_0}), + ctx.mkEq(nctx.pf.get("origin").apply(p_0),node)),1,null,null,null,null)); + //Constraint3 send(node, n_0, p, t_0) -> p.orig_body == p.body + constraints.add( + ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies( + (BoolExpr)nctx.send.apply(new Expr[]{ node, n_0, p_0, t_0}), + ctx.mkEq(nctx.pf.get("orig_body").apply(p_0),nctx.pf.get("body").apply(p_0))),1,null,null,null,null)); + //Constraint4 recv(n_0, node, p, t_0) -> nodeHasAddr(node,p.dest) + constraints.add( + ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies( + (BoolExpr)nctx.recv.apply( new Expr[]{ n_0, node, p_0, t_0}), + (BoolExpr)nctx.nodeHasAddr.apply(new Expr[]{node, nctx.pf.get("dest").apply(p_0)})),1,null,null,null,null)); + +// Just a try: here we state that an endhost is not able to issue a HTTP response traffic +// See PolitoCache.py model for constants definition (2 means HTTP_RESPONSE, 1 means HTTP_REQUEST) +// constraints.add(ctx.mkForall(new Expr[]{n_0, p_0, t_0}, +// ctx.mkImplies((BoolExpr)nctx.send.apply(node, n_0, p_0, t_0), +// ctx.mkEq(nctx.pf.get("proto").apply(p_0), ctx.mkInt(1))),1,null,null,null,null)); + } +}
\ No newline at end of file diff --git a/verigraph/service/src/mcnet/netobjs/PacketModel.java b/verigraph/service/src/mcnet/netobjs/PacketModel.java new file mode 100644 index 0000000..5761861 --- /dev/null +++ b/verigraph/service/src/mcnet/netobjs/PacketModel.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package mcnet.netobjs; + +import com.microsoft.z3.DatatypeExpr; + +/* + * Fields that can be configured -> "dest","body","seq","proto","emailFrom","url","options" + */ +public class PacketModel { + + private DatatypeExpr ip_dest; + private Integer body; + private Integer seq; + private Integer proto; + private Integer emailFrom; + private Integer url; + private Integer options; + + public DatatypeExpr getIp_dest() { + return ip_dest; + } + public void setIp_dest(DatatypeExpr ip_dest) { + this.ip_dest = ip_dest; + } + public Integer getBody() { + return body; + } + public void setBody(Integer body) { + this.body = body; + } + public Integer getSeq() { + return seq; + } + public void setSeq(Integer seq) { + this.seq = seq; + } + public Integer getProto() { + return proto; + } + public void setProto(Integer proto) { + this.proto = proto; + } + public Integer getEmailFrom() { + return emailFrom; + } + public void setEmailFrom(Integer emailFrom) { + this.emailFrom = emailFrom; + } + public Integer getUrl() { + return url; + } + public void setUrl(Integer url) { + this.url = url; + } + public Integer getOptions() { + return options; + } + public void setOptions(Integer options) { + this.options = options; + } + +} diff --git a/verigraph/service/src/mcnet/netobjs/PolitoAntispam.java b/verigraph/service/src/mcnet/netobjs/PolitoAntispam.java new file mode 100644 index 0000000..abb4615 --- /dev/null +++ b/verigraph/service/src/mcnet/netobjs/PolitoAntispam.java @@ -0,0 +1,124 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package mcnet.netobjs; + + +import java.util.ArrayList; +import java.util.List; + +import com.microsoft.z3.BoolExpr; +import com.microsoft.z3.Context; +import com.microsoft.z3.DatatypeExpr; +import com.microsoft.z3.Expr; +import com.microsoft.z3.FuncDecl; +import com.microsoft.z3.IntExpr; +import com.microsoft.z3.Solver; + +import mcnet.components.NetContext; +import mcnet.components.Network; +import mcnet.components.NetworkObject; + +/** + * Model of an anti-spam node + * + */ +public class PolitoAntispam extends NetworkObject{ + + List<BoolExpr> constraints; + Context ctx; + DatatypeExpr politoAntispam; + Network net; + NetContext nctx; + FuncDecl isInBlacklist; + + public PolitoAntispam(Context ctx, Object[]... args) { + super(ctx, args); + } + + @Override + protected void init(Context ctx, Object[]... args) { + this.ctx = ctx; + isEndHost=false; + constraints = new ArrayList<BoolExpr>(); + z3Node = ((NetworkObject)args[0][0]).getZ3Node(); + politoAntispam = z3Node; + net = (Network)args[0][1]; + nctx = (NetContext)args[0][2]; + //net.saneSend(this); + } + + @Override + public DatatypeExpr getZ3Node() { + return politoAntispam; + } + + @Override + protected void addConstraints(Solver solver) { + BoolExpr[] constr = new BoolExpr[constraints.size()]; + solver.add(constraints.toArray(constr)); + } + + public void installAntispam (int[] blackList){ + Expr n_0 = ctx.mkConst(politoAntispam+"_n_0", nctx.node); + Expr n_1 = ctx.mkConst(politoAntispam+"_n_1", nctx.node); + Expr p_0 = ctx.mkConst(politoAntispam+"_p_0", nctx.packet); + IntExpr t_0 = ctx.mkIntConst(politoAntispam+"_t_0"); + IntExpr t_1 = ctx.mkIntConst(politoAntispam+"_t_1"); + IntExpr ef_0 = ctx.mkIntConst(politoAntispam+"_ef_0"); + + isInBlacklist = ctx.mkFuncDecl(politoAntispam+"_isInBlacklist", ctx.mkIntSort(), ctx.mkBoolSort()); + BoolExpr[] blConstraint = new BoolExpr[blackList.length]; + if(blackList.length != 0){ + for (int i=0;i<blackList.length;i++) + blConstraint[i]=(ctx.mkEq(ef_0,ctx.mkInt(blackList[i]))); + //Constraint1a if(isInBlackList(ef_0) == or(for bl in blacklist (ef_0==bl)) ? true : false + constraints.add(ctx.mkForall(new Expr[]{ef_0}, ctx.mkIff((BoolExpr)isInBlacklist.apply(ef_0),ctx.mkOr(blConstraint)),1,null,null,null,null)); + }else{ + //Constraint1b isInblackList(ef_0) == false + constraints.add(ctx.mkForall(new Expr[]{ef_0}, ctx.mkEq((BoolExpr)isInBlacklist.apply(ef_0), ctx.mkBool(false)),1,null,null,null,null)); + } + + //Constraint2 send(politoAntispam, n_0, p, t_0) && p.proto(POP3_RESP) -> + // (exist n_1,t_1 : (recv(n_1, politoAntispam, p, t_1) && t_1 < t_0)) && !isInBlackList(p.emailFrom) + constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies(ctx.mkAnd((BoolExpr)nctx.send.apply(politoAntispam, n_0, p_0, t_0), ctx.mkEq(nctx.pf.get("proto").apply(p_0), ctx.mkInt(nctx.POP3_RESPONSE))), + ctx.mkAnd( ctx.mkExists(new Expr[]{n_1, t_1}, + ctx.mkAnd((BoolExpr)nctx.recv.apply(n_1, politoAntispam, p_0, t_1), ctx.mkLt(t_1 , t_0)),1,null,null,null,null), + ctx.mkNot((BoolExpr)isInBlacklist.apply(nctx.pf.get("emailFrom").apply(p_0))))),1,null,null,null,null)); + + //Constraint3 send(politoAntispam, n_0, p, t_0) && p.proto(POP3_REQ) -> + // (exist n_1,t_1 : (recv(n_1, politoAntispam, p, t_1) && t_1 < t_0)) + constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies(ctx.mkAnd((BoolExpr)nctx.send.apply(politoAntispam, n_0, p_0, t_0), ctx.mkEq(nctx.pf.get("proto").apply(p_0), ctx.mkInt(nctx.POP3_REQUEST))), + ctx.mkAnd(ctx.mkExists(new Expr[]{n_1, t_1}, + ctx.mkAnd((BoolExpr)nctx.recv.apply(n_1, politoAntispam, p_0, t_1), + ctx.mkLt(t_1 , t_0)),1,null,null,null,null))),1,null,null,null,null)); + + //Constraint4 send(politoAntispam, politoErrFunction, p, t_0) -> + // (exist n_1,t_1 : (recv(n_1, politoAntispam, p, t_1) && t_1 < t_0 && p.emailFrom ==1)) + constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies((BoolExpr)nctx.send.apply(politoAntispam, nctx.nm.get("politoErrFunction").getZ3Node(), p_0, t_0), + ctx.mkAnd(ctx.mkExists(new Expr[]{n_1, t_1}, + ctx.mkAnd((BoolExpr)nctx.recv.apply(n_1, politoAntispam, p_0, t_1), + ctx.mkLt(t_1 , t_0), + ctx.mkEq(nctx.pf.get("emailFrom").apply(p_0),ctx.mkInt(1))),1,null,null,null,null))),1,null,null,null,null)); + + //Constraint5 send(politoAntispam, n_0, p, t_0) -> p.proto == POP_REQ || p.protpo == POP_RESP + constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies((BoolExpr)nctx.send.apply(politoAntispam, n_0, p_0, t_0), + ctx.mkOr( ctx.mkEq(nctx.pf.get("proto").apply(p_0), ctx.mkInt(nctx.POP3_REQUEST)), + ctx.mkEq(nctx.pf.get("proto").apply(p_0), ctx.mkInt(nctx.POP3_RESPONSE)))),1,null,null,null,null)); + + //Constraint6 send(politoAntispam, n_0, p, t_0) -> nodeHasAddr(politoAntispam,p.src) + constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies((BoolExpr)nctx.send.apply(politoAntispam, n_0, p_0, t_0), + ctx.mkNot((BoolExpr)nctx.nodeHasAddr.apply(politoAntispam,nctx.pf.get("src").apply(p_0)))),1,null,null,null,null)); + } + }
\ No newline at end of file diff --git a/verigraph/service/src/mcnet/netobjs/PolitoCache.java b/verigraph/service/src/mcnet/netobjs/PolitoCache.java new file mode 100644 index 0000000..948915c --- /dev/null +++ b/verigraph/service/src/mcnet/netobjs/PolitoCache.java @@ -0,0 +1,177 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package mcnet.netobjs; + + +import java.util.ArrayList; +import java.util.List; + +import com.microsoft.z3.BoolExpr; +import com.microsoft.z3.Context; +import com.microsoft.z3.DatatypeExpr; +import com.microsoft.z3.Expr; +import com.microsoft.z3.FuncDecl; +import com.microsoft.z3.IntExpr; +import com.microsoft.z3.Solver; +import com.microsoft.z3.Sort; + +import mcnet.components.NetContext; +import mcnet.components.Network; +import mcnet.components.NetworkObject; +/**Cache Model + * + */ +public class PolitoCache extends NetworkObject{ + + List<BoolExpr> constraints; + Context ctx; + DatatypeExpr politoCache; + Network net; + NetContext nctx; + FuncDecl isInBlacklist; + + public PolitoCache(Context ctx, Object[]... args) { + super(ctx, args); + } + + @Override + protected void init(Context ctx, Object[]... args) { + this.ctx = ctx; + isEndHost=false; + constraints = new ArrayList<BoolExpr>(); + z3Node = ((NetworkObject)args[0][0]).getZ3Node(); + politoCache = z3Node; + net = (Network)args[0][1]; + nctx = (NetContext)args[0][2]; + //net.saneSend(this); + } + + @Override + public DatatypeExpr getZ3Node() { + return politoCache; + } + + @Override + protected void addConstraints(Solver solver) { + BoolExpr[] constr = new BoolExpr[constraints.size()]; + solver.add(constraints.toArray(constr)); + } + + public void installCache (NetworkObject[] internalNodes){ + Expr n_0 = ctx.mkConst("politoCache_"+politoCache+"_n_0", nctx.node); + Expr n_1 = ctx.mkConst("politoCache_"+politoCache+"_n_1", nctx.node); + Expr n_2 = ctx.mkConst("politoCache_"+politoCache+"_n_2", nctx.node); + Expr p_0 = ctx.mkConst("politoCache_"+politoCache+"_p_0", nctx.packet); + Expr p_1 = ctx.mkConst("politoCache_"+politoCache+"_p_1", nctx.packet); + Expr p_2 = ctx.mkConst("politoCache_"+politoCache+"_p_2", nctx.packet); + + IntExpr t_0 = ctx.mkIntConst("politoCache_"+politoCache+"_t_0"); + IntExpr t_1 = ctx.mkIntConst("politoCache_"+politoCache+"_t_1"); + IntExpr t_2 = ctx.mkIntConst("politoCache_"+politoCache+"_t_2"); + + Expr a_0 = ctx.mkConst(politoCache+"politoCache_a_0", nctx.node); + IntExpr u_0 = ctx.mkIntConst("politoCache_"+politoCache+"_u_0"); + + FuncDecl isInternalNode = ctx.mkFuncDecl(politoCache+"_isInternalNode", nctx.node, ctx.mkBoolSort()); + FuncDecl isInCache = ctx.mkFuncDecl(politoCache+"_isInCache", new Sort[]{ctx.mkIntSort(),ctx.mkIntSort()}, ctx.mkBoolSort()); + + assert(internalNodes.length!=0); //No internal nodes => Should never happen + + //Modeling the behavior of the isInternalNode() and isInCache() functions + BoolExpr[] internalNodesConstraint = new BoolExpr[internalNodes.length]; + for(int w=0;w<internalNodesConstraint.length;w++) + internalNodesConstraint[w]= (ctx.mkEq(a_0,internalNodes[w].getZ3Node())); + + //Constraint1 if(isInternalNode(a_0) == or(listadeinodiinterni) ? True : false + constraints.add( + ctx.mkForall(new Expr[]{a_0}, + ctx.mkIff((BoolExpr)isInternalNode.apply(a_0), ctx.mkOr(internalNodesConstraint)),1,null,null,null,null)); + +// constraints.add(ctx.mkForall(new Expr[]{a_0}, ctx.mkEq(isInternalNode.apply(a_0),ctx.mkOr(internalNodesConstraint)),1,null,null,null,null)); + +// constraints.add(ctx.mkForall(new Expr[]{u_0, t_0}, +// ctx.mkITE(ctx.mkExists(new Expr[]{t_1, t_2, p_1, p_2, n_1, n_2}, +// ctx.mkAnd(ctx.mkLt(t_1, t_2), +// ctx.mkLt(t_1, t_0), +// ctx.mkLt(t_2, t_0), +// (BoolExpr)nctx.recv.apply(n_1, politoCache, p_1, t_1), +// (BoolExpr)nctx.recv.apply(n_2, politoCache, p_2, t_2), +// ctx.mkEq(nctx.pf.get("proto").apply(p_1),ctx.mkInt(nctx.HTTP_REQUEST)), +// ctx.mkEq(nctx.pf.get("proto").apply(p_2),ctx.mkInt(nctx.HTTP_RESPONSE)), +// (BoolExpr)isInternalNode.apply(n_1), +// ctx.mkNot((BoolExpr)isInternalNode.apply(n_2)), +// ctx.mkEq(nctx.pf.get("url").apply(p_1),u_0), +// ctx.mkEq(nctx.pf.get("url").apply(p_2),u_0)),1,null,null,null,null), +// ctx.mkEq(isInCache.apply(u_0,t_0),ctx.mkBool(true)),ctx.mkEq(isInCache.apply(u_0,t_0),ctx.mkBool(false))),1,null,null,null,null)); +// + + //Constraint2 isInCache(u_0,t_0), exist t_1, t_2, p_1, p_2, n_1, n_2 : + // ( t_1< t_2 < t_0 && recv(n_1, politoCache, p_1, t_1) && recv(n_2, politoCache, p_2, t_2))) && + // p_1.proto == HTTP_REQ && p_2.proto == HTTP_RESP && + // isInternalNode(n_1) && !isInternalNode(n_2) && + // p_1.url == u_0 && p_2.url == u_0 ) + constraints.add( + ctx.mkForall(new Expr[]{u_0, t_0}, + ctx.mkImplies((BoolExpr)isInCache.apply(u_0, t_0), + ctx.mkExists(new Expr[]{t_1,t_2,p_1,p_2,n_1, n_2}, + ctx.mkAnd( + ctx.mkLt(t_1, t_2), + ctx.mkLt(t_1, t_0), + ctx.mkLt(t_2, t_0), + (BoolExpr)nctx.recv.apply(n_1, politoCache, p_1, t_1), + (BoolExpr)nctx.recv.apply(n_2, politoCache, p_2, t_2), + ctx.mkEq(nctx.pf.get("proto").apply(p_1), ctx.mkInt(nctx.HTTP_REQUEST)), + ctx.mkEq(nctx.pf.get("proto").apply(p_2), ctx.mkInt(nctx.HTTP_RESPONSE)), + (BoolExpr)isInternalNode.apply(n_1), + ctx.mkNot((BoolExpr)isInternalNode.apply(n_2)), + ctx.mkEq(nctx.pf.get("url").apply(p_1), u_0), + ctx.mkEq(nctx.pf.get("url").apply(p_2), u_0)),1,null,null,null,null)),1,null,null,null,null)); +// //Always in cache +// constraints.add(ctx.mkForall(new Expr[]{u_0, t_0},ctx.mkEq(isInCache.apply(u_0,t_0),ctx.mkBool(true)),1,null,null,null,null)); + + //Constraint3 Modeling the behavior of the cache + // send(politoCache, n_0, p, t_0) && !isInternalNode(n_0) -> + // (exist t_1,n_1 : + // (t_1 < t_0 && recv(n_1, politoCache, p, t_1) && + // p.proto == HTTP_REQ && !isInCache(p.url,t_0)) + constraints.add( + ctx.mkForall(new Expr[]{n_0,p_0, t_0}, + ctx.mkImplies( + ctx.mkAnd((BoolExpr)nctx.send.apply(politoCache,n_0,p_0,t_0),ctx.mkNot((BoolExpr)isInternalNode.apply(n_0))), + ctx.mkAnd(ctx.mkExists(new Expr[]{t_1, n_1}, + ctx.mkAnd( + ctx.mkLt(t_1, t_0), + (BoolExpr)isInternalNode.apply(n_1), + (BoolExpr)nctx.recv.apply(n_1, politoCache, p_0, t_1)),1,null,null,null,null), + ctx.mkEq(nctx.pf.get("proto").apply(p_0), ctx.mkInt(nctx.HTTP_REQUEST)), + ctx.mkNot((BoolExpr)isInCache.apply(nctx.pf.get("url").apply(p_0), t_0)))),1,null,null,null,null)); + + //Constraint4 send(politoCache, n_0, p, t_0) && isInternalNode(n_0) -> + // (exist p_1,t_1 : + // (t_1 < t_0 && recv(n_0, politoCache, p_1, t_1) && + // p_1.proto == HTTP_REQ && p.proto == HTTP_RESP && + // p_1.url == p.url && p.src == p_1.dest && p.dest==p_1.src + // && isInCache(p.url,t_0)) + constraints.add( + ctx.mkForall(new Expr[]{n_0,p_0, t_0}, + ctx.mkImplies( + ctx.mkAnd((BoolExpr)nctx.send.apply(politoCache,n_0,p_0,t_0),(BoolExpr)isInternalNode.apply(n_0)), + ctx.mkAnd(ctx.mkExists(new Expr[]{p_1, t_1}, + ctx.mkAnd( + ctx.mkLt(t_1, t_0), + (BoolExpr)nctx.recv.apply(n_0, politoCache, p_1, t_1), + ctx.mkEq(nctx.pf.get("proto").apply(p_1), ctx.mkInt(nctx.HTTP_REQUEST)), + ctx.mkEq(nctx.pf.get("url").apply(p_1), nctx.pf.get("url").apply(p_0))),1,null,null,null,null), + ctx.mkEq(nctx.pf.get("proto").apply(p_0), ctx.mkInt(nctx.HTTP_RESPONSE)), + ctx.mkEq(nctx.pf.get("src").apply(p_0), nctx.pf.get("dest").apply(p_1)), + ctx.mkEq(nctx.pf.get("dest").apply(p_0), nctx.pf.get("src").apply(p_1)), + (BoolExpr)isInCache.apply(nctx.pf.get("url").apply(p_0), t_0))),1,null,null,null,null)); + } +}
\ No newline at end of file diff --git a/verigraph/service/src/mcnet/netobjs/PolitoEndHost.java b/verigraph/service/src/mcnet/netobjs/PolitoEndHost.java new file mode 100644 index 0000000..e12579f --- /dev/null +++ b/verigraph/service/src/mcnet/netobjs/PolitoEndHost.java @@ -0,0 +1,100 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package mcnet.netobjs; + +import java.util.ArrayList; +import java.util.List; + +import com.microsoft.z3.BoolExpr; +import com.microsoft.z3.Context; +import com.microsoft.z3.DatatypeExpr; +import com.microsoft.z3.Expr; +import com.microsoft.z3.IntExpr; +import com.microsoft.z3.Solver; + +import mcnet.components.NetContext; +import mcnet.components.Network; +import mcnet.components.NetworkObject; + +public class PolitoEndHost extends NetworkObject { + + List<BoolExpr> constraints = new ArrayList<BoolExpr>(); + Context ctx; + DatatypeExpr politoEndHost; + Network net; + NetContext nctx; + + public PolitoEndHost(Context ctx, Object[]... args) { + super(ctx, args); + } + + @Override + public DatatypeExpr getZ3Node() { + return politoEndHost; + } + + @Override + protected void init(Context ctx, Object[]... args) { + this.ctx = ctx; + this.isEndHost = true; + this.politoEndHost = this.z3Node = ((NetworkObject)args[0][0]).getZ3Node(); + this.net = (Network)args[0][1]; + this.nctx = (NetContext)args[0][2]; + } + + @Override + protected void addConstraints(Solver solver) { + BoolExpr[] constr = new BoolExpr[constraints.size()]; + solver.add(constraints.toArray(constr)); + } + + /* + * Fields that can be configured -> "dest","body","seq","proto","emailFrom","url","options" + */ + public void installEndHost (PacketModel packet){ + System.out.println("Installing PolitoEndHost..."); + Expr n_0 = ctx.mkConst("PolitoEndHost_"+politoEndHost+"_n_0", nctx.node); + Expr p_0 = ctx.mkConst("PolitoEndHost_"+politoEndHost+"_p_0", nctx.packet); + IntExpr t_0 = ctx.mkIntConst("PolitoEndHost_"+politoEndHost+"_t_0"); + BoolExpr predicatesOnPktFields = ctx.mkTrue(); + + if(packet.getIp_dest() != null) + predicatesOnPktFields = ctx.mkAnd(predicatesOnPktFields, ctx.mkEq(nctx.pf.get("dest").apply(p_0), packet.getIp_dest())); + if(packet.getBody() != null) + predicatesOnPktFields = ctx.mkAnd(predicatesOnPktFields, ctx.mkEq(nctx.pf.get("body").apply(p_0), ctx.mkInt(packet.getBody()))); + if(packet.getEmailFrom() != null) + predicatesOnPktFields = ctx.mkAnd(predicatesOnPktFields, ctx.mkEq(nctx.pf.get("emailFrom").apply(p_0), ctx.mkInt(packet.getEmailFrom()))); + if(packet.getOptions() != null) + predicatesOnPktFields = ctx.mkAnd(predicatesOnPktFields, ctx.mkEq(nctx.pf.get("options").apply(p_0), ctx.mkInt(packet.getOptions()))); + if(packet.getProto() != null) + predicatesOnPktFields = ctx.mkAnd(predicatesOnPktFields, ctx.mkEq(nctx.pf.get("proto").apply(p_0), ctx.mkInt(packet.getProto()))); + if(packet.getSeq() != null) + predicatesOnPktFields = ctx.mkAnd(predicatesOnPktFields, ctx.mkEq(nctx.pf.get("seq").apply(p_0), ctx.mkInt(packet.getSeq()))); + if(packet.getUrl() != null) + predicatesOnPktFields = ctx.mkAnd(predicatesOnPktFields, ctx.mkEq(nctx.pf.get("url").apply(p_0), ctx.mkInt(packet.getUrl()))); + + //Constraint1 send(politoWebClient, n_0, p, t_0) -> p.origin == politoWebClient && p.orig_body == p.body && nodeHasAddr(politoWebClient,p.src) + constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies((BoolExpr)nctx.send.apply(politoEndHost, n_0, p_0, t_0), + ctx.mkAnd(predicatesOnPktFields, + ctx.mkEq(nctx.pf.get("orig_body").apply(p_0),nctx.pf.get("body").apply(p_0)), + ctx.mkEq(nctx.pf.get("origin").apply(p_0),politoEndHost), + (BoolExpr)nctx.nodeHasAddr.apply(politoEndHost,nctx.pf.get("src").apply(p_0)))),1,null,null,null,null)); + + //Constraint2 recv(n_0, politoWebClient, p, t_0) -> nodeHasAddr(politoWebClient,p.dest) + constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies((BoolExpr)nctx.recv.apply(n_0,politoEndHost, p_0, t_0), + (BoolExpr)nctx.nodeHasAddr.apply(politoEndHost,nctx.pf.get("dest").apply(p_0))),1,null,null,null,null)); + + System.out.println("Done."); + return; + } + +} diff --git a/verigraph/service/src/mcnet/netobjs/PolitoErrFunction.java b/verigraph/service/src/mcnet/netobjs/PolitoErrFunction.java new file mode 100644 index 0000000..5f84b9f --- /dev/null +++ b/verigraph/service/src/mcnet/netobjs/PolitoErrFunction.java @@ -0,0 +1,96 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package mcnet.netobjs; + + +import java.util.ArrayList; +import java.util.List; + +import com.microsoft.z3.BoolExpr; +import com.microsoft.z3.Context; +import com.microsoft.z3.DatatypeExpr; +import com.microsoft.z3.Expr; +import com.microsoft.z3.FuncDecl; +import com.microsoft.z3.IntExpr; +import com.microsoft.z3.Solver; + +import mcnet.components.NetContext; +import mcnet.components.Network; +import mcnet.components.NetworkObject; +/**Error Function objects + * + */ +public class PolitoErrFunction extends NetworkObject{ + + List<BoolExpr> constraints; + Context ctx; + DatatypeExpr politoErrFunction; + Network net; + NetContext nctx; + FuncDecl isInBlacklist; + + public PolitoErrFunction(Context ctx, Object[]... args) { + super(ctx, args); + } + + @Override + protected void init(Context ctx, Object[]... args) { + this.ctx = ctx; + isEndHost=true; + constraints = new ArrayList<BoolExpr>(); + z3Node = ((NetworkObject)args[0][0]).getZ3Node(); + politoErrFunction = z3Node; + net = (Network)args[0][1]; + nctx = (NetContext)args[0][2]; + errFunctionRules(); + //net.saneSend(this); + } + + @Override + public DatatypeExpr getZ3Node() { + return politoErrFunction; + } + + @Override + protected void addConstraints(Solver solver) { +// System.out.println("[ERR FUNC] Installing rules."); + BoolExpr[] constr = new BoolExpr[constraints.size()]; + solver.add(constraints.toArray(constr)); + } + + private void errFunctionRules (){ + Expr n_0 = ctx.mkConst("PolitoErrFunction_"+politoErrFunction+"_n_0", nctx.node); + Expr p_0 = ctx.mkConst("PolitoErrFunction_"+politoErrFunction+"_p_0", nctx.packet); + IntExpr t_0 = ctx.mkIntConst("PolitoErrFunction_"+politoErrFunction+"_t_0"); + +// constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, +// ctx.mkImplies((BoolExpr)nctx.send.apply(politoErrFunction, n_0, p_0, t_0), +// (BoolExpr)nctx.nodeHasAddr.apply(politoErrFunction, nctx.pf.get("src").apply(p_0))),1,null,null,null,null)); +// constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, +// ctx.mkImplies((BoolExpr)nctx.send.apply(politoErrFunction, n_0, p_0, t_0), +// ctx.mkEq(nctx.pf.get("origin").apply(p_0), politoErrFunction)),1,null,null,null,null)); +// +// constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, +// ctx.mkImplies((BoolExpr)nctx.send.apply(politoErrFunction, n_0, p_0, t_0), +// ctx.mkEq(nctx.pf.get("orig_body").apply(p_0),nctx.pf.get("body").apply(p_0))),1,null,null,null,null)); + + +// Constraint1 We want the ErrFunction not to send out any packet +// send(politoErrFunction, n_0, p, t_0) -> 1 == 2 + constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies((BoolExpr)nctx.send.apply(politoErrFunction, n_0, p_0, t_0), + ctx.mkEq(ctx.mkInt(1),ctx.mkInt(2))),1,null,null,null,null)); + +// constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, +// ctx.mkImplies( (BoolExpr)nctx.send.apply(n_0, politoErrFunction, p_0, t_0), +// (BoolExpr)nctx.nodeHasAddr.apply(politoErrFunction, nctx.pf.get("dest").apply(p_0))),1,null,null,null,null)); + + } + }
\ No newline at end of file diff --git a/verigraph/service/src/mcnet/netobjs/PolitoFieldModifier.java b/verigraph/service/src/mcnet/netobjs/PolitoFieldModifier.java new file mode 100644 index 0000000..6d8d8fe --- /dev/null +++ b/verigraph/service/src/mcnet/netobjs/PolitoFieldModifier.java @@ -0,0 +1,91 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package mcnet.netobjs; + +import java.util.ArrayList; +import java.util.List; + +import com.microsoft.z3.BoolExpr; +import com.microsoft.z3.Context; +import com.microsoft.z3.DatatypeExpr; +import com.microsoft.z3.Expr; +import com.microsoft.z3.IntExpr; +import com.microsoft.z3.Solver; + +import mcnet.components.NetContext; +import mcnet.components.Network; +import mcnet.components.NetworkObject; + +public class PolitoFieldModifier extends NetworkObject { + + List<BoolExpr> constraints; + Context ctx; + DatatypeExpr politoFieldModifier; + Network net; + NetContext nctx; + + public PolitoFieldModifier(Context ctx, Object[]... args) { + super(ctx, args); + } + + @Override + public DatatypeExpr getZ3Node() { + return politoFieldModifier; + } + + @Override + protected void init(Context ctx, Object[]... args) { + this.ctx = ctx; + isEndHost=false; + constraints = new ArrayList<BoolExpr>(); + z3Node = ((NetworkObject)args[0][0]).getZ3Node(); + politoFieldModifier = z3Node; + net = (Network)args[0][1]; + nctx = (NetContext)args[0][2]; + } + + @Override + protected void addConstraints(Solver solver) { + BoolExpr[] constr = new BoolExpr[constraints.size()]; + solver.add(constraints.toArray(constr)); + } + + public void installFieldModifier (){ + Expr x = ctx.mkConst("politoFieldModifier_"+politoFieldModifier+"_x", nctx.node); + Expr y = ctx.mkConst("politoFieldModifier_"+politoFieldModifier+"_y", nctx.node); + Expr p_0 = ctx.mkConst("politoFieldModifier_"+politoFieldModifier+"_p_0", nctx.packet); + Expr p_1 = ctx.mkConst("politoFieldModifier_"+politoFieldModifier+"_p_1", nctx.packet); + + IntExpr t_0 = ctx.mkIntConst("politoFieldModifier_"+politoFieldModifier+"_t_0"); + IntExpr t_1 = ctx.mkIntConst("politoFieldModifier_"+politoFieldModifier+"_t_1"); + + constraints.add( + ctx.mkForall(new Expr[]{t_0, p_0, x}, + ctx.mkImplies((BoolExpr)nctx.send.apply(politoFieldModifier,x,p_0,t_0), + ctx.mkExists(new Expr[]{y, p_1, t_1}, + ctx.mkAnd(ctx.mkLt(t_1, t_0), + (BoolExpr)nctx.recv.apply(y, politoFieldModifier, p_1, t_1), + ctx.mkEq(nctx.pf.get("encrypted").apply(p_0), nctx.pf.get("encrypted").apply(p_1)), + ctx.mkEq(nctx.pf.get("src").apply(p_0), nctx.pf.get("src").apply(p_1)), + ctx.mkEq(nctx.pf.get("dest").apply(p_0), nctx.pf.get("dest").apply(p_1)), + ctx.mkEq(nctx.pf.get("inner_src").apply(p_0), nctx.pf.get("inner_src").apply(p_1)), + ctx.mkEq(nctx.pf.get("inner_dest").apply(p_0), nctx.pf.get("inner_dest").apply(p_1)), + ctx.mkEq(nctx.pf.get("origin").apply(p_0), nctx.pf.get("origin").apply(p_1)), + ctx.mkEq(nctx.pf.get("orig_body").apply(p_0), nctx.pf.get("orig_body").apply(p_1)), + ctx.mkEq(nctx.pf.get("body").apply(p_0), nctx.pf.get("body").apply(p_1)), + ctx.mkEq(nctx.pf.get("seq").apply(p_0), nctx.pf.get("seq").apply(p_1)), + ctx.mkEq(nctx.pf.get("proto").apply(p_0), nctx.pf.get("proto").apply(p_1)), + ctx.mkEq(nctx.pf.get("emailFrom").apply(p_0), nctx.pf.get("emailFrom").apply(p_1)), + ctx.mkNot(ctx.mkEq(nctx.pf.get("url").apply(p_0), nctx.pf.get("url").apply(p_1))), + ctx.mkEq(nctx.pf.get("options").apply(p_0), nctx.pf.get("options").apply(p_1))),1,null,null,null,null)), + 1,null,null,null,null)); + } + +}
\ No newline at end of file diff --git a/verigraph/service/src/mcnet/netobjs/PolitoIDS.java b/verigraph/service/src/mcnet/netobjs/PolitoIDS.java new file mode 100644 index 0000000..6f2cddf --- /dev/null +++ b/verigraph/service/src/mcnet/netobjs/PolitoIDS.java @@ -0,0 +1,140 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package mcnet.netobjs; + +import java.util.ArrayList; +import java.util.List; + +import com.microsoft.z3.BoolExpr; +import com.microsoft.z3.Context; +import com.microsoft.z3.DatatypeExpr; +import com.microsoft.z3.Expr; +import com.microsoft.z3.FuncDecl; +import com.microsoft.z3.IntExpr; +import com.microsoft.z3.Solver; + +import mcnet.components.NetContext; +import mcnet.components.Network; +import mcnet.components.NetworkObject; + +public class PolitoIDS extends NetworkObject { + + public static final int DROGA = 1; //no go + public static final int GATTINI = 2; //go + + Context ctx; + List<BoolExpr> constraints = new ArrayList<BoolExpr>(); + DatatypeExpr politoIDS; + Network net; + NetContext nctx; + FuncDecl isInBlacklist; + + + public PolitoIDS(Context ctx, Object[]...args){ + super(ctx, args); + } + + @Override + public DatatypeExpr getZ3Node() { + return politoIDS; + } + + @Override + protected void init(Context ctx, Object[]... args) { + + this.ctx = ctx; + this.isEndHost = false; + this.politoIDS = this.z3Node = ((NetworkObject)args[0][0]).getZ3Node(); + this.net = (Network)args[0][1]; + this.nctx = (NetContext)args[0][2]; + + } + + @Override + protected void addConstraints(Solver solver) { + BoolExpr[] constr = new BoolExpr[constraints.size()]; + solver.add(constraints.toArray(constr)); + + } + + public void installIDS(int[] blackList){ + Expr n_0 = ctx.mkConst(politoIDS + "_n_0", nctx.node); + Expr n_1 = ctx.mkConst(politoIDS + "_n_1", nctx.node); + Expr p_0 = ctx.mkConst(politoIDS + "_p_0", nctx.packet); + IntExpr t_0 = ctx.mkIntConst(politoIDS + "_t_0"); + IntExpr t_1 = ctx.mkIntConst(politoIDS + "_t_1"); + Expr b_0 = ctx.mkIntConst(politoIDS + "_b_0"); + + isInBlacklist = ctx.mkFuncDecl(politoIDS + "_isInBlacklist", ctx.mkIntSort(), ctx.mkBoolSort()); + + + BoolExpr[] blConstraints = new BoolExpr[blackList.length]; + if(blackList.length != 0){ + + for(int i = 0; i<blackList.length; i++) + blConstraints[i] = ctx.mkEq(b_0, ctx.mkInt(blackList[i])); + + this.constraints.add(ctx.mkForall(new Expr[]{b_0}, + ctx.mkIff((BoolExpr)isInBlacklist.apply(b_0), ctx.mkOr(blConstraints)), + 1, + null, null, null, null)); + }else{ + this.constraints.add(ctx.mkForall(new Expr[]{b_0}, + ctx.mkEq(isInBlacklist.apply(b_0), ctx.mkBool(false)), + 1, + null, null, null, null)); + } + + //Constraint2 send(politoIDS, n_0, p, t_0) && (p.proto(HTTP_RESPONSE) || p.proto(HTTP_REQUEST)) -> + // (exist n_1,t_1 : (recv(n_1, politoIDS, p, t_1) && t_1 < t_0)) && !isInBlackList(p.body) + + this.constraints.add(ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies(ctx.mkAnd((BoolExpr)nctx.send.apply(politoIDS, n_0, p_0, t_0), ctx.mkOr(ctx.mkEq(nctx.pf.get("proto").apply(p_0), ctx.mkInt(nctx.HTTP_RESPONSE)), ctx.mkEq(nctx.pf.get("proto").apply(p_0), ctx.mkInt(nctx.HTTP_REQUEST)))), + ctx.mkAnd(ctx.mkExists(new Expr[]{n_1,t_1}, + ctx.mkAnd((BoolExpr)nctx.recv.apply(n_1,politoIDS,p_0,t_1),ctx.mkLt(t_1, t_0)), + 1, + null, null, null, null), + ctx.mkNot((BoolExpr)isInBlacklist.apply(nctx.pf.get("body").apply(p_0))))), + 1, + null, null, null, null)); + + //Constraint3 send(politoIDS, n_0, p, t_0) && p.proto(HTTP_REQUEST) -> + // (exist n_1,t_1 : (recv(n_1, politoIDS, p, t_1) && t_1 < t_0)) Constraint not needed anymore (included in contr. 2) + /* + this.constraints.add(ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies(ctx.mkAnd((BoolExpr)nctx.send.apply(politoIDS, n_0, p_0, t_0), ctx.mkEq(nctx.pf.get("proto").apply(p_0), ctx.mkInt(nctx.HTTP_REQUEST))), + ctx.mkAnd(ctx.mkExists(new Expr[]{n_1,t_1}, + ctx.mkAnd((BoolExpr)nctx.recv.apply(n_1,politoIDS,p_0,t_1),ctx.mkLt(t_1, t_0)), + 1, + null, null, null, null))), + 1, + null, null, null, null)); + */ + + //Constraint5 send(politoIDS, n_0, p, t_0) -> p.proto == HTTP_REQ || p.protpo == HTTP_RESP + + this.constraints.add(ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies((BoolExpr)nctx.send.apply(politoIDS, n_0, p_0, t_0), + ctx.mkOr(ctx.mkEq(nctx.pf.get("proto").apply(p_0), ctx.mkInt(nctx.HTTP_REQUEST)), + ctx.mkEq(nctx.pf.get("proto").apply(p_0), ctx.mkInt(nctx.HTTP_RESPONSE)))), + 1, + null,null,null,null)); + + //Constraint6 send(politoIDS, n_0, p, t_0) -> nodeHasAddr(politoIDS,p.src) + + this.constraints.add(ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies((BoolExpr)nctx.send.apply(politoIDS, n_0, p_0, t_0), + ctx.mkNot((BoolExpr)nctx.nodeHasAddr.apply(politoIDS,nctx.pf.get("src").apply(p_0)))), + 1, + null,null,null,null)); + + } + +} diff --git a/verigraph/service/src/mcnet/netobjs/PolitoMailClient.java b/verigraph/service/src/mcnet/netobjs/PolitoMailClient.java new file mode 100644 index 0000000..6925258 --- /dev/null +++ b/verigraph/service/src/mcnet/netobjs/PolitoMailClient.java @@ -0,0 +1,106 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package mcnet.netobjs; + + +import java.util.ArrayList; +import java.util.List; + +import com.microsoft.z3.BoolExpr; +import com.microsoft.z3.Context; +import com.microsoft.z3.DatatypeExpr; +import com.microsoft.z3.Expr; +import com.microsoft.z3.FuncDecl; +import com.microsoft.z3.IntExpr; +import com.microsoft.z3.Solver; + +import mcnet.components.NetContext; +import mcnet.components.Network; +import mcnet.components.NetworkObject; +/** + * MailClient objects + * + */ +public class PolitoMailClient extends NetworkObject{ + + List<BoolExpr> constraints; + Context ctx; + DatatypeExpr politoMailClient; + Network net; + NetContext nctx; + FuncDecl isInBlacklist; + + public PolitoMailClient(Context ctx, Object[]... args) { + super(ctx, args); + } + + @Override + protected void init(Context ctx, Object[]... args) { + this.ctx = ctx; + isEndHost=true; + constraints = new ArrayList<BoolExpr>(); + z3Node = ((NetworkObject)args[0][0]).getZ3Node(); + politoMailClient = z3Node; + net = (Network)args[0][1]; + nctx = (NetContext)args[0][2]; + DatatypeExpr ipServer = (DatatypeExpr) args[0][3]; + mailClientRules(ipServer); + //net.saneSend(this); + } + + @Override + public DatatypeExpr getZ3Node() { + return politoMailClient; + } + + @Override + protected void addConstraints(Solver solver) { +// System.out.println("[MailClient] Installing rules."); + BoolExpr[] constr = new BoolExpr[constraints.size()]; + solver.add(constraints.toArray(constr)); + } + + private void mailClientRules (DatatypeExpr ipServer){ + Expr n_0 = ctx.mkConst("PolitoMailClient_"+politoMailClient+"_n_0", nctx.node); + Expr p_0 = ctx.mkConst("PolitoMailClient_"+politoMailClient+"_p_0", nctx.packet); + IntExpr t_0 = ctx.mkIntConst("PolitoMailClient_"+politoMailClient+"_t_0"); + +// Constraint1 send(politoMailClient, n_0, p, t_0) -> nodeHasAddr(politoMailClient,p.src) + constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies((BoolExpr)nctx.send.apply(politoMailClient, n_0, p_0, t_0), + (BoolExpr)nctx.nodeHasAddr.apply(politoMailClient,nctx.pf.get("src").apply(p_0))),1,null,null,null,null)); + +// Constraint2 send(politoMailClient, n_0, p, t_0) -> p.origin == politoMailClient + constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies((BoolExpr)nctx.send.apply(politoMailClient, n_0, p_0, t_0), + ctx.mkEq(nctx.pf.get("origin").apply(p_0),politoMailClient)),1,null,null,null,null)); + +// Constraint3 send(politoMailClient, n_0, p, t_0) -> p.orig_body == p.body + constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies((BoolExpr)nctx.send.apply(politoMailClient, n_0, p_0, t_0), + ctx.mkEq(nctx.pf.get("orig_body").apply(p_0),nctx.pf.get("body").apply(p_0))),1,null,null,null,null)); + +// Constraint4 recv(n_0, politoMailClient, p, t_0) -> nodeHasAddr(politoMailClient,p.dest) + constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies((BoolExpr)nctx.recv.apply(n_0,politoMailClient, p_0, t_0), + (BoolExpr)nctx.nodeHasAddr.apply(politoMailClient,nctx.pf.get("dest").apply(p_0))),1,null,null,null,null)); + +// Constraint5 This client is only able to produce POP3 requests +// send(politoMailClient, n_0, p, t_0) -> p.proto == POP3_REQ + constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies((BoolExpr)nctx.send.apply(politoMailClient, n_0, p_0, t_0), + ctx.mkEq(nctx.pf.get("proto").apply(p_0), ctx.mkInt(nctx.POP3_REQUEST))),1,null,null,null,null)); + +// Constraint6 send(politoMailClient, n_0, p, t_0) -> p.dest == ip_mailServer + constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies((BoolExpr)nctx.send.apply(politoMailClient, n_0, p_0, t_0), + ctx.mkEq(nctx.pf.get("dest").apply(p_0), ipServer)),1,null,null,null,null)); + } +} diff --git a/verigraph/service/src/mcnet/netobjs/PolitoMailServer.java b/verigraph/service/src/mcnet/netobjs/PolitoMailServer.java new file mode 100644 index 0000000..c464195 --- /dev/null +++ b/verigraph/service/src/mcnet/netobjs/PolitoMailServer.java @@ -0,0 +1,117 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package mcnet.netobjs; + + +import java.util.ArrayList; +import java.util.List; + +import com.microsoft.z3.BoolExpr; +import com.microsoft.z3.Context; +import com.microsoft.z3.DatatypeExpr; +import com.microsoft.z3.Expr; +import com.microsoft.z3.FuncDecl; +import com.microsoft.z3.IntExpr; +import com.microsoft.z3.Solver; + +import mcnet.components.NetContext; +import mcnet.components.Network; +import mcnet.components.NetworkObject; +/** Mail server objects + * + */ +public class PolitoMailServer extends NetworkObject{ + + List<BoolExpr> constraints; + Context ctx; + DatatypeExpr politoMailServer; + Network net; + NetContext nctx; + FuncDecl isInBlacklist; + + public PolitoMailServer(Context ctx, Object[]... args) { + super(ctx, args); + } + + @Override + protected void init(Context ctx, Object[]... args) { + this.ctx = ctx; + isEndHost=false; + constraints = new ArrayList<BoolExpr>(); + z3Node = ((NetworkObject)args[0][0]).getZ3Node(); + politoMailServer = z3Node; + net = (Network)args[0][1]; + nctx = (NetContext)args[0][2]; + mailServerRules(); + net.saneSend(this); + } + + @Override + public DatatypeExpr getZ3Node() { + return politoMailServer; + } + + @Override + protected void addConstraints(Solver solver) { + BoolExpr[] constr = new BoolExpr[constraints.size()]; + solver.add(constraints.toArray(constr)); + } + + private void mailServerRules (){ + Expr n_0 = ctx.mkConst(politoMailServer+"_n_0", nctx.node); + Expr p_0 = ctx.mkConst(politoMailServer+"_p_0", nctx.packet); + Expr p_1 = ctx.mkConst(politoMailServer+"_p_1", nctx.packet); + IntExpr t_0 = ctx.mkIntConst(politoMailServer+"_t_0"); + IntExpr t_1 = ctx.mkIntConst(politoMailServer+"_t_1"); + +// Constraint1 send(politoMailServer, n_0, p, t_0) -> nodeHasAddr(politoMailServer,p.src) + constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies((BoolExpr)nctx.send.apply(politoMailServer, n_0, p_0, t_0), + (BoolExpr)nctx.nodeHasAddr.apply(politoMailServer,nctx.pf.get("src").apply(p_0))),1,null,null,null,null)); + +// Constraint2 send(politoMailServer, n_0, p, t_0) -> p.origin == politoMailServer + constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies((BoolExpr)nctx.send.apply(politoMailServer, n_0, p_0, t_0), + ctx.mkEq(nctx.pf.get("origin").apply(p_0),politoMailServer)),1,null,null,null,null)); + +// Constraint3 send(politoMailServer, n_0, p, t_0) -> p.orig_body == p.body + constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies((BoolExpr)nctx.send.apply(politoMailServer, n_0, p_0, t_0), + ctx.mkEq(nctx.pf.get("orig_body").apply(p_0),nctx.pf.get("body").apply(p_0))),1,null,null,null,null)); + +// Constraint4 recv(n_0, politoMailServer, p, t_0) -> nodeHasAddr(politoMailServer,p.dest) + constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies((BoolExpr)nctx.recv.apply(n_0,politoMailServer, p_0, t_0), + (BoolExpr)nctx.nodeHasAddr.apply(politoMailServer,nctx.pf.get("dest").apply(p_0))),1,null,null,null,null)); + +// Constraint5 send(politoMailServer, n_0, p, t_0) -> p.proto == POP3_RESP && p.emailFrom == 1 + constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies((BoolExpr)nctx.send.apply(politoMailServer, n_0, p_0, t_0), + ctx.mkAnd( ctx.mkEq(nctx.pf.get("proto").apply(p_0), ctx.mkInt(nctx.POP3_RESPONSE)), + ctx.mkEq(nctx.pf.get("emailFrom").apply(p_0), ctx.mkInt(1)))),1,null,null,null,null)); + +// Constraint6 send(politoMailServer, n_0, p, t_0) -> +// (exist p_1, t_1 : (t_1 < t_0 && recv(n_0, politoMailServer, p_1, t_1) && +// p_0.proto == POP3_RESP && p_1.proto == POP3_REQ && p_0.dest == p_1.src ) + + constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies((BoolExpr)nctx.send.apply(politoMailServer, n_0, p_0, t_0), + ctx.mkExists(new Expr[]{p_1, t_1}, + ctx.mkAnd(ctx.mkLt(t_1, t_0), + (BoolExpr)nctx.recv.apply(n_0, politoMailServer, p_1, t_1), + ctx.mkEq(nctx.pf.get("proto").apply(p_0), ctx.mkInt(nctx.POP3_RESPONSE)), + ctx.mkEq(nctx.pf.get("proto").apply(p_1), ctx.mkInt(nctx.POP3_REQUEST)), + ctx.mkEq(nctx.pf.get("dest").apply(p_0), nctx.pf.get("src").apply(p_1))),1,null,null,null,null)),1,null,null,null,null)); + +// constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, +// ctx.mkImplies((BoolExpr)nctx.send.apply(politoMailServer, n_0, p_0, t_0), +// ctx.mkEq(nctx.pf.get("emailFrom").apply(p_0),ctx.mkInt(2))),1,null,null,null,null)); + } +}
\ No newline at end of file diff --git a/verigraph/service/src/mcnet/netobjs/PolitoNF.java b/verigraph/service/src/mcnet/netobjs/PolitoNF.java new file mode 100644 index 0000000..53cae28 --- /dev/null +++ b/verigraph/service/src/mcnet/netobjs/PolitoNF.java @@ -0,0 +1,101 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package mcnet.netobjs; + + +import java.util.ArrayList; +import java.util.List; + +import com.microsoft.z3.BoolExpr; +import com.microsoft.z3.Context; +import com.microsoft.z3.DatatypeExpr; +import com.microsoft.z3.Expr; +import com.microsoft.z3.FuncDecl; +import com.microsoft.z3.IntExpr; +import com.microsoft.z3.Solver; +import com.microsoft.z3.Sort; + +import mcnet.components.NetContext; +import mcnet.components.Network; +import mcnet.components.NetworkObject; + +/** First example of custom network function: a simple filter + * + */ +public class PolitoNF extends NetworkObject{ + + List<BoolExpr> constraints; + Context ctx; + DatatypeExpr politoNF; + Network net; + NetContext nctx; + FuncDecl isInBlacklist; + + + public PolitoNF(Context ctx, Object[]... args) { + super(ctx, args); + } + + @Override + protected void init(Context ctx, Object[]... args) { + this.ctx = ctx; + isEndHost=false; + constraints = new ArrayList<BoolExpr>(); + z3Node = ((NetworkObject)args[0][0]).getZ3Node(); + politoNF = z3Node; + net = (Network)args[0][1]; + nctx = (NetContext)args[0][2]; + //net.saneSend(this); + } + + public void politoNFRules (DatatypeExpr ipA,DatatypeExpr ipB){ +// System.out.println("[PolitoNf] Installing rules"); + Expr n_0 = ctx.mkConst("politoNF_"+politoNF+"_n_0", nctx.node); + Expr n_1 = ctx.mkConst("politoNF_"+politoNF+"_n_1", nctx.node); + Expr p_0 = ctx.mkConst("politoNF_"+politoNF+"_p_0", nctx.packet); + IntExpr t_0 = ctx.mkIntConst("politoNF_"+politoNF+"_t_0"); + IntExpr t_1 = ctx.mkIntConst("politoNF_"+politoNF+"_t_1"); + Expr a_0 = ctx.mkConst(politoNF+"_politoNF_a_0", nctx.address); + Expr a_1 = ctx.mkConst(politoNF+"_politoNF_a_1", nctx.address); + + FuncDecl myFunction = ctx.mkFuncDecl(politoNF+"_myFunction", new Sort[]{nctx.address,nctx.address}, ctx.mkBoolSort()); + + BoolExpr myConstraint = ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies((BoolExpr)nctx.send.apply(politoNF, n_0, p_0, t_0), + ctx.mkExists(new Expr[]{n_1, t_1}, + ctx.mkAnd((BoolExpr)nctx.recv.apply(n_1, politoNF, p_0, t_1), + ctx.mkLt(t_1 , t_0), + (BoolExpr)myFunction.apply(nctx.pf.get("src").apply(p_0), nctx.pf.get("dest").apply(p_0))),1,null,null,null,null)),1,null,null,null,null); + + BoolExpr funcConstraint = ctx.mkOr(ctx.mkAnd(ctx.mkEq(a_0, ipA), ctx.mkEq(a_1, ipB)), ctx.mkAnd(ctx.mkEq(a_0,ipB), ctx.mkEq(a_1,ipA))); + + // Constraint1 myFunction(a_0,a_1) == ((a_0 == ipA && a_1 == ipB) || (a_0 == ipB && a_1 == ipA)) + constraints.add( + ctx.mkForall(new Expr[]{a_0,a_1}, + ctx.mkEq(myFunction.apply(a_0, a_1), funcConstraint),1,null,null,null,null)); + + //Constraint2 send(politoNF, n_0, p, t_0) -> + // (exist n_1,t_1 : (t_1 < t_0 && recv(n_1, politoNF, p, t_1) && myFunction(p.src,p.dest)) + constraints.add(myConstraint); + + } + + @Override + protected void addConstraints(Solver solver) { + BoolExpr[] constr = new BoolExpr[constraints.size()]; + solver.add(constraints.toArray(constr)); + } + + @Override + public DatatypeExpr getZ3Node() { + return politoNF; + } + + }
\ No newline at end of file diff --git a/verigraph/service/src/mcnet/netobjs/PolitoNat.java b/verigraph/service/src/mcnet/netobjs/PolitoNat.java new file mode 100644 index 0000000..6d8a36d --- /dev/null +++ b/verigraph/service/src/mcnet/netobjs/PolitoNat.java @@ -0,0 +1,176 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package mcnet.netobjs; + + +import java.util.ArrayList; +import java.util.List; + +import com.microsoft.z3.BoolExpr; +import com.microsoft.z3.Context; +import com.microsoft.z3.DatatypeExpr; +import com.microsoft.z3.Expr; +import com.microsoft.z3.FuncDecl; +import com.microsoft.z3.IntExpr; +import com.microsoft.z3.Solver; + +import mcnet.components.NetContext; +import mcnet.components.Network; +import mcnet.components.NetworkObject; +/** + * NAT Model object + * + */ +public class PolitoNat extends NetworkObject{ + List<BoolExpr> constraints; + Context ctx; + DatatypeExpr nat; + List<DatatypeExpr> private_addresses; + List<NetworkObject> private_node; + Network net; + NetContext nctx; + FuncDecl private_addr_func ; + + public PolitoNat(Context ctx, Object[]... args) { + super(ctx, args); + } + + @Override + protected void init(Context ctx, Object[]... args) { + this.ctx = ctx; + isEndHost=false; + constraints = new ArrayList<BoolExpr>(); + z3Node = ((NetworkObject)args[0][0]).getZ3Node(); + nat = z3Node; + net = (Network)args[0][1]; + nctx = (NetContext)args[0][2]; + private_addresses = new ArrayList<DatatypeExpr>(); + private_node = new ArrayList<NetworkObject>(); + net.saneSend(this); + } + + @Override + public DatatypeExpr getZ3Node() { + return nat; + } + + @Override + protected void addConstraints(Solver solver) { + BoolExpr[] constr = new BoolExpr[constraints.size()]; + solver.add(constraints.toArray(constr)); + } + + /* + private void addPrivateAdd(List<DatatypeExpr> address){ + private_addresses.addAll(address); + } + */ + + public List<DatatypeExpr> getPrivateAddress(){ + return private_addresses; + } + + public void natModel(DatatypeExpr natIp){ + Expr x = ctx.mkConst("x", nctx.node); + Expr y = ctx.mkConst("y", nctx.node); + Expr z = ctx.mkConst("z", nctx.node); + + Expr p_0 = ctx.mkConst("p_0", nctx.packet); + Expr p_1 = ctx.mkConst("p_1", nctx.packet); + Expr p_2 = ctx.mkConst("p_2", nctx.packet); + + IntExpr t_0 = ctx.mkIntConst("t_0"); + IntExpr t_1 = ctx.mkIntConst("t_1"); + IntExpr t_2 = ctx.mkIntConst("t_2"); + +// private_addr_func = ctx.mkFuncDecl("private_addr_func", nctx.address, ctx.mkBoolSort()); + private_addr_func = ctx.mkFuncDecl(nat + "_nat_func", nctx.address, ctx.mkBoolSort()); + + //Constraint1 +// "send(nat, x, p_0, t_0) && !private_addr_func(p_0.dest) -> +// p_0.src == ip_politoNat && +// (exist y, p_1,t_1 : +// (recv(y, nat, p_1, t_1) && t_1 < t_0 && +// private_addr_func(p1.src) && +// p_1.origin == p_0.origin && +// same for p_1.<dest,orig_body,body,seq,proto,emailFrom,url,options> == p_0.<...>) " + constraints.add( ctx.mkForall(new Expr[]{t_0, p_0, x}, + ctx.mkImplies( + ctx.mkAnd((BoolExpr)nctx.send.apply(nat, x, p_0, t_0), + ctx.mkNot((BoolExpr)private_addr_func.apply(nctx.pf.get("dest").apply(p_0)))), + ctx.mkAnd( + ctx.mkEq(nctx.pf.get("src").apply(p_0),natIp), + ctx.mkExists(new Expr[]{y, p_1, t_1}, + ctx.mkAnd( + (BoolExpr)nctx.recv.apply(y, nat, p_1, t_1), + ctx.mkLt(t_1 , t_0), + (BoolExpr)private_addr_func.apply(nctx.pf.get("src").apply(p_1)), + ctx.mkEq(nctx.pf.get("origin").apply(p_1),nctx.pf.get("origin").apply(p_0)), + ctx.mkEq(nctx.pf.get("dest").apply(p_1),nctx.pf.get("dest").apply(p_0)), + ctx.mkEq(nctx.pf.get("orig_body").apply(p_1),nctx.pf.get("orig_body").apply(p_0)), + ctx.mkEq(nctx.pf.get("body").apply(p_1),nctx.pf.get("body").apply(p_0)), + ctx.mkEq(nctx.pf.get("seq").apply(p_1),nctx.pf.get("seq").apply(p_0)), + ctx.mkEq(nctx.pf.get("proto").apply(p_1),nctx.pf.get("proto").apply(p_0)), + ctx.mkEq(nctx.pf.get("emailFrom").apply(p_1),nctx.pf.get("emailFrom").apply(p_0)), + ctx.mkEq(nctx.pf.get("url").apply(p_1),nctx.pf.get("url").apply(p_0)), + ctx.mkEq(nctx.pf.get("options").apply(p_1),nctx.pf.get("options").apply(p_0))),1,null,null,null,null))),1,null,null,null,null)); + + //Constraint2 +// send(nat, x, p_0, t_0) && private_addr_func(p_0.dest) -> +// !private_addr_func(p_0.src) && +// (exist y, p_1,t_1 : +// (recv(y, nat, p_1, t_1) && t_1 < t_0 && +// !private_addr_func(p1.src) && +// p_1.dest == ip_politoNat && +// p_1.origin == p_0.origin && +// same for p_1.<src,orig_body,body,seq,proto,emailFrom,url,options> == p_0.<...>) + constraints.add( ctx.mkForall(new Expr[]{x, p_0, t_0}, + ctx.mkImplies( + ctx.mkAnd((BoolExpr)nctx.send.apply(nat, x, p_0, t_0), + (BoolExpr)private_addr_func.apply(nctx.pf.get("dest").apply(p_0))), + ctx.mkAnd( + ctx.mkNot((BoolExpr)private_addr_func.apply(nctx.pf.get("src").apply(p_0))), + ctx.mkExists(new Expr[]{y, p_1, t_1}, + ctx.mkAnd( + ctx.mkLt(t_1 , t_0), + (BoolExpr)nctx.recv.apply(y, nat, p_1, t_1), + ctx.mkNot((BoolExpr)private_addr_func.apply(nctx.pf.get("src").apply(p_1))), + ctx.mkEq(nctx.pf.get("dest").apply(p_1),natIp), + ctx.mkEq(nctx.pf.get("src").apply(p_1),nctx.pf.get("src").apply(p_0)), + ctx.mkEq(nctx.pf.get("origin").apply(p_0),nctx.pf.get("origin").apply(p_1)), + ctx.mkEq(nctx.pf.get("orig_body").apply(p_1),nctx.pf.get("orig_body").apply(p_0)), + ctx.mkEq(nctx.pf.get("body").apply(p_1),nctx.pf.get("body").apply(p_0)), + ctx.mkEq(nctx.pf.get("seq").apply(p_1),nctx.pf.get("seq").apply(p_0)), + ctx.mkEq(nctx.pf.get("proto").apply(p_1),nctx.pf.get("proto").apply(p_0)), + ctx.mkEq(nctx.pf.get("emailFrom").apply(p_1),nctx.pf.get("emailFrom").apply(p_0)), + ctx.mkEq(nctx.pf.get("url").apply(p_1),nctx.pf.get("url").apply(p_0)), + ctx.mkEq(nctx.pf.get("options").apply(p_1),nctx.pf.get("options").apply(p_0)), + ctx.mkExists(new Expr[]{z, p_2, t_2}, + ctx.mkAnd( + ctx.mkLt(t_2 , t_1), + (BoolExpr)nctx.recv.apply(z, nat, p_2, t_2), + (BoolExpr)private_addr_func.apply(nctx.pf.get("src").apply(p_2)), + ctx.mkEq(nctx.pf.get("src").apply(p_1),nctx.pf.get("dest").apply(p_2)), + ctx.mkEq(nctx.pf.get("src").apply(p_0),nctx.pf.get("dest").apply(p_2)), + ctx.mkEq(nctx.pf.get("src").apply(p_2),nctx.pf.get("dest").apply(p_0))),1,null,null,null,null)),1,null,null,null,null))),1,null,null,null,null)); + } + + public void setInternalAddress(ArrayList<DatatypeExpr> internalAddress){ + List<BoolExpr> constr = new ArrayList<BoolExpr>(); + Expr n_0 = ctx.mkConst("nat_node", nctx.address); + + for(DatatypeExpr n : internalAddress){ + constr.add(ctx.mkEq(n_0,n)); + } + BoolExpr[] constrs = new BoolExpr[constr.size()]; + //Constraint private_addr_func(n_0) == or(n_0==n foreach internal address) + constraints.add(ctx.mkForall(new Expr[]{n_0}, ctx.mkEq(private_addr_func.apply(n_0),ctx.mkOr(constr.toArray(constrs))),1,null,null,null,null)); + } +}
\ No newline at end of file diff --git a/verigraph/service/src/mcnet/netobjs/PolitoVpnAccess.java b/verigraph/service/src/mcnet/netobjs/PolitoVpnAccess.java new file mode 100644 index 0000000..e6fc5fe --- /dev/null +++ b/verigraph/service/src/mcnet/netobjs/PolitoVpnAccess.java @@ -0,0 +1,142 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package mcnet.netobjs; + +import java.util.ArrayList; +import java.util.List; + +import com.microsoft.z3.BoolExpr; +import com.microsoft.z3.Context; +import com.microsoft.z3.DatatypeExpr; +import com.microsoft.z3.Expr; +import com.microsoft.z3.FuncDecl; +import com.microsoft.z3.IntExpr; +import com.microsoft.z3.Solver; + +import mcnet.components.NetContext; +import mcnet.components.Network; +import mcnet.components.NetworkObject; + +public class PolitoVpnAccess extends NetworkObject { + + List<BoolExpr> constraints = new ArrayList<BoolExpr>(); + DatatypeExpr politoVpnAccess; + FuncDecl private_addr_func; + NetContext nctx; + Context ctx; + Network net; + + public PolitoVpnAccess(Context ctx, Object[]... args) { + super(ctx, args); + } + + @Override + public DatatypeExpr getZ3Node() { + return politoVpnAccess; + } + + @Override + protected void init(Context ctx, Object[]... args) { + this.ctx = ctx; + this.isEndHost = false; + this.politoVpnAccess = this.z3Node = ((NetworkObject)args[0][0]).getZ3Node(); + this.net = (Network)args[0][1]; + this.nctx = (NetContext)args[0][2]; + } + + @Override + protected void addConstraints(Solver solver) { + BoolExpr[] constr = new BoolExpr[constraints.size()]; + solver.add(constraints.toArray(constr)); + } + + public void vpnAccessModel(DatatypeExpr vpnAccessIp, DatatypeExpr vpnExitIp) { + Expr x = ctx.mkConst("vpn_x", nctx.node); + Expr y = ctx.mkConst("vpn_y", nctx.node); + + Expr p_0 = ctx.mkConst("vpn_p_0", nctx.packet); + Expr p_1 = ctx.mkConst("vpn_p_1", nctx.packet); + + IntExpr t_0 = ctx.mkIntConst("vpn_t_0"); + IntExpr t_1 = ctx.mkIntConst("vpn_t_1"); + + private_addr_func = ctx.mkFuncDecl("vpn_private_addr_func", nctx.address, ctx.mkBoolSort()); + + BoolExpr constraint1 = ctx.mkForall(new Expr[]{t_0, p_0, x}, + ctx.mkImplies(ctx.mkAnd( + (BoolExpr)nctx.send.apply(politoVpnAccess, x, p_0, t_0), + ctx.mkEq(nctx.pf.get("inner_src").apply(p_0), nctx.am.get("null"))), + ctx.mkAnd( + (BoolExpr)private_addr_func.apply(nctx.pf.get("dest").apply(p_0)), + ctx.mkNot((BoolExpr)nctx.pf.get("encrypted").apply(p_0)), + ctx.mkExists(new Expr[]{y, p_1, t_1}, + ctx.mkAnd((BoolExpr)nctx.recv.apply(y, politoVpnAccess, p_1, t_1), + ctx.mkLt(t_1, t_0), + (BoolExpr)nctx.pf.get("encrypted").apply(p_1), + ctx.mkEq(nctx.pf.get("src").apply(p_1), vpnExitIp), + ctx.mkEq(nctx.pf.get("dest").apply(p_1), vpnAccessIp), + ctx.mkEq(nctx.pf.get("inner_src").apply(p_1), nctx.pf.get("src").apply(p_0)), + ctx.mkEq(nctx.pf.get("inner_dest").apply(p_1), nctx.pf.get("dest").apply(p_0)), + ctx.mkEq(nctx.pf.get("origin").apply(p_1), nctx.pf.get("origin").apply(p_0)), + ctx.mkEq(nctx.pf.get("orig_body").apply(p_1), nctx.pf.get("orig_body").apply(p_0)), + ctx.mkEq(nctx.pf.get("body").apply(p_1), nctx.pf.get("body").apply(p_0)), + ctx.mkEq(nctx.pf.get("seq").apply(p_1), nctx.pf.get("seq").apply(p_0)), + ctx.mkEq(nctx.pf.get("proto").apply(p_1), nctx.pf.get("proto").apply(p_0)), + ctx.mkEq(nctx.pf.get("emailFrom").apply(p_1), nctx.pf.get("emailFrom").apply(p_0)), + ctx.mkEq(nctx.pf.get("url").apply(p_1), nctx.pf.get("url").apply(p_0)), + ctx.mkEq(nctx.pf.get("options").apply(p_1), nctx.pf.get("options").apply(p_0))), 1, null, null, null, null))), + 1,null,null,null,null); + + constraints.add(constraint1); + + BoolExpr constraint2 = ctx.mkForall(new Expr[]{t_0, p_0, x}, + ctx.mkImplies(ctx.mkAnd( + (BoolExpr)nctx.send.apply(politoVpnAccess, x, p_0, t_0), + ctx.mkNot(ctx.mkEq(nctx.pf.get("inner_src").apply(p_0), nctx.am.get("null")))), + ctx.mkAnd( + ctx.mkEq(nctx.pf.get("src").apply(p_0), vpnAccessIp), + ctx.mkEq(nctx.pf.get("dest").apply(p_0), vpnExitIp), + (BoolExpr)private_addr_func.apply(nctx.pf.get("inner_src").apply(p_0)), + ctx.mkNot(ctx.mkEq(nctx.pf.get("inner_dest").apply(p_0), vpnAccessIp)), + (BoolExpr)nctx.pf.get("encrypted").apply(p_0), + ctx.mkExists(new Expr[]{y, p_1, t_1}, + ctx.mkAnd((BoolExpr)nctx.recv.apply(y, politoVpnAccess, p_1, t_1), + ctx.mkLt(t_1, t_0), + ctx.mkNot((BoolExpr)nctx.pf.get("encrypted").apply(p_1)), + ctx.mkEq(nctx.pf.get("src").apply(p_1), nctx.pf.get("inner_src").apply(p_0)), + ctx.mkEq(nctx.pf.get("dest").apply(p_1), nctx.pf.get("inner_dest").apply(p_0)), + ctx.mkEq(nctx.pf.get("inner_src").apply(p_1), nctx.am.get("null")), + ctx.mkEq(nctx.pf.get("inner_dest").apply(p_1), nctx.am.get("null")), + ctx.mkEq(nctx.pf.get("origin").apply(p_1), nctx.pf.get("origin").apply(p_0)), + ctx.mkEq(nctx.pf.get("orig_body").apply(p_1), nctx.pf.get("orig_body").apply(p_0)), + ctx.mkEq(nctx.pf.get("body").apply(p_1), nctx.pf.get("body").apply(p_0)), + ctx.mkEq(nctx.pf.get("seq").apply(p_1), nctx.pf.get("seq").apply(p_0)), + ctx.mkEq(nctx.pf.get("proto").apply(p_1), nctx.pf.get("proto").apply(p_0)), + ctx.mkEq(nctx.pf.get("emailFrom").apply(p_1), nctx.pf.get("emailFrom").apply(p_0)), + ctx.mkEq(nctx.pf.get("url").apply(p_1), nctx.pf.get("url").apply(p_0)), + ctx.mkEq(nctx.pf.get("options").apply(p_1), nctx.pf.get("options").apply(p_0))), 1, null, null, null, null))), + 1,null,null,null,null); + + constraints.add(constraint2); + } + + public void setInternalAddress(ArrayList<DatatypeExpr> internalAddress){ + List<BoolExpr> constr = new ArrayList<BoolExpr>(); + Expr n_0 = ctx.mkConst("vpn_node", nctx.address); + + for(DatatypeExpr n : internalAddress){ + constr.add(ctx.mkEq(n_0,n)); + } + BoolExpr[] constrs = new BoolExpr[constr.size()]; + //Constraint private_addr_func(n_0) == or(n_0==n foreach internal address) + constraints.add(ctx.mkForall(new Expr[]{n_0}, ctx.mkEq(private_addr_func.apply(n_0),ctx.mkOr(constr.toArray(constrs))),1,null,null,null,null)); + } + +}
\ No newline at end of file diff --git a/verigraph/service/src/mcnet/netobjs/PolitoVpnExit.java b/verigraph/service/src/mcnet/netobjs/PolitoVpnExit.java new file mode 100644 index 0000000..fb2341f --- /dev/null +++ b/verigraph/service/src/mcnet/netobjs/PolitoVpnExit.java @@ -0,0 +1,142 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package mcnet.netobjs; + +import java.util.ArrayList; +import java.util.List; + +import com.microsoft.z3.BoolExpr; +import com.microsoft.z3.Context; +import com.microsoft.z3.DatatypeExpr; +import com.microsoft.z3.Expr; +import com.microsoft.z3.FuncDecl; +import com.microsoft.z3.IntExpr; +import com.microsoft.z3.Solver; + +import mcnet.components.NetContext; +import mcnet.components.Network; +import mcnet.components.NetworkObject; + +public class PolitoVpnExit extends NetworkObject { + + List<BoolExpr> constraints = new ArrayList<BoolExpr>(); + DatatypeExpr politoVpnExit; + FuncDecl private_addr_func; + NetContext nctx; + Context ctx; + Network net; + + public PolitoVpnExit(Context ctx, Object[]... args) { + super(ctx, args); + } + + @Override + public DatatypeExpr getZ3Node() { + return politoVpnExit; + } + + @Override + protected void init(Context ctx, Object[]... args) { + this.ctx = ctx; + this.isEndHost = false; + this.politoVpnExit = this.z3Node = ((NetworkObject)args[0][0]).getZ3Node(); + this.net = (Network)args[0][1]; + this.nctx = (NetContext)args[0][2]; + } + + @Override + protected void addConstraints(Solver solver) { + BoolExpr[] constr = new BoolExpr[constraints.size()]; + solver.add(constraints.toArray(constr)); + } + + public void vpnAccessModel(DatatypeExpr vpnAccessIp, DatatypeExpr vpnExitIp) { + Expr x = ctx.mkConst("vpn_x", nctx.node); + Expr y = ctx.mkConst("vpn_y", nctx.node); + + Expr p_0 = ctx.mkConst("vpn_p_0", nctx.packet); + Expr p_1 = ctx.mkConst("vpn_p_1", nctx.packet); + + IntExpr t_0 = ctx.mkIntConst("vpn_t_0"); + IntExpr t_1 = ctx.mkIntConst("vpn_t_1"); + + private_addr_func = ctx.mkFuncDecl("vpn_private_addr_func", nctx.address, ctx.mkBoolSort()); + + BoolExpr constraint1 = ctx.mkForall(new Expr[]{t_0, p_0, x}, + ctx.mkImplies(ctx.mkAnd( + (BoolExpr)nctx.send.apply(politoVpnExit, x, p_0, t_0), + ctx.mkEq(nctx.pf.get("inner_src").apply(p_0), nctx.am.get("null"))), + ctx.mkAnd( + (BoolExpr)private_addr_func.apply(nctx.pf.get("src").apply(p_0)), + ctx.mkNot((BoolExpr)nctx.pf.get("encrypted").apply(p_0)), + ctx.mkExists(new Expr[]{y, p_1, t_1}, + ctx.mkAnd((BoolExpr)nctx.recv.apply(y, politoVpnExit, p_1, t_1), + ctx.mkLt(t_1, t_0), + (BoolExpr)nctx.pf.get("encrypted").apply(p_1), + ctx.mkEq(nctx.pf.get("src").apply(p_1), vpnAccessIp), + ctx.mkEq(nctx.pf.get("dest").apply(p_1), vpnExitIp), + ctx.mkEq(nctx.pf.get("inner_src").apply(p_1), nctx.pf.get("src").apply(p_0)), + ctx.mkEq(nctx.pf.get("inner_dest").apply(p_1), nctx.pf.get("dest").apply(p_0)), + ctx.mkEq(nctx.pf.get("origin").apply(p_1), nctx.pf.get("origin").apply(p_0)), + ctx.mkEq(nctx.pf.get("orig_body").apply(p_1), nctx.pf.get("orig_body").apply(p_0)), + ctx.mkEq(nctx.pf.get("body").apply(p_1), nctx.pf.get("body").apply(p_0)), + ctx.mkEq(nctx.pf.get("seq").apply(p_1), nctx.pf.get("seq").apply(p_0)), + ctx.mkEq(nctx.pf.get("proto").apply(p_1), nctx.pf.get("proto").apply(p_0)), + ctx.mkEq(nctx.pf.get("emailFrom").apply(p_1), nctx.pf.get("emailFrom").apply(p_0)), + ctx.mkEq(nctx.pf.get("url").apply(p_1), nctx.pf.get("url").apply(p_0)), + ctx.mkEq(nctx.pf.get("options").apply(p_1), nctx.pf.get("options").apply(p_0))), 1, null, null, null, null))), + 1,null,null,null,null); + + constraints.add(constraint1); + + BoolExpr constraint2 = ctx.mkForall(new Expr[]{t_0, p_0, x}, + ctx.mkImplies(ctx.mkAnd( + (BoolExpr)nctx.send.apply(politoVpnExit, x, p_0, t_0), + ctx.mkNot(ctx.mkEq(nctx.pf.get("inner_src").apply(p_0), nctx.am.get("null")))), + ctx.mkAnd( + ctx.mkEq(nctx.pf.get("src").apply(p_0), vpnExitIp), + ctx.mkEq(nctx.pf.get("dest").apply(p_0), vpnAccessIp), + (BoolExpr)private_addr_func.apply(nctx.pf.get("dest").apply(p_0)), + ctx.mkNot(ctx.mkEq(nctx.pf.get("inner_dest").apply(p_1), vpnExitIp)), + (BoolExpr)nctx.pf.get("encrypted").apply(p_0), + ctx.mkExists(new Expr[]{y, p_1, t_1}, + ctx.mkAnd((BoolExpr)nctx.recv.apply(y, politoVpnExit, p_1, t_1), + ctx.mkLt(t_1, t_0), + ctx.mkNot((BoolExpr)nctx.pf.get("encrypted").apply(p_1)), + ctx.mkEq(nctx.pf.get("src").apply(p_1), nctx.pf.get("inner_src").apply(p_0)), + ctx.mkEq(nctx.pf.get("dest").apply(p_1), nctx.pf.get("inner_dest").apply(p_0)), + ctx.mkEq(nctx.pf.get("inner_src").apply(p_1), nctx.am.get("null")), + ctx.mkEq(nctx.pf.get("inner_dest").apply(p_1), nctx.am.get("null")), + ctx.mkEq(nctx.pf.get("origin").apply(p_1), nctx.pf.get("origin").apply(p_0)), + ctx.mkEq(nctx.pf.get("orig_body").apply(p_1), nctx.pf.get("orig_body").apply(p_0)), + ctx.mkEq(nctx.pf.get("body").apply(p_1), nctx.pf.get("body").apply(p_0)), + ctx.mkEq(nctx.pf.get("seq").apply(p_1), nctx.pf.get("seq").apply(p_0)), + ctx.mkEq(nctx.pf.get("proto").apply(p_1), nctx.pf.get("proto").apply(p_0)), + ctx.mkEq(nctx.pf.get("emailFrom").apply(p_1), nctx.pf.get("emailFrom").apply(p_0)), + ctx.mkEq(nctx.pf.get("url").apply(p_1), nctx.pf.get("url").apply(p_0)), + ctx.mkEq(nctx.pf.get("options").apply(p_1), nctx.pf.get("options").apply(p_0))), 1, null, null, null, null))), + 1,null,null,null,null); + + constraints.add(constraint2); + } + + public void setInternalAddress(ArrayList<DatatypeExpr> internalAddress){ + List<BoolExpr> constr = new ArrayList<BoolExpr>(); + Expr n_0 = ctx.mkConst("vpn_node", nctx.address); + + for(DatatypeExpr n : internalAddress){ + constr.add(ctx.mkEq(n_0,n)); + } + BoolExpr[] constrs = new BoolExpr[constr.size()]; + //Constraint private_addr_func(n_0) == or(n_0==n foreach internal address) + constraints.add(ctx.mkForall(new Expr[]{n_0}, ctx.mkEq(private_addr_func.apply(n_0),ctx.mkOr(constr.toArray(constrs))),1,null,null,null,null)); + } + +}
\ No newline at end of file diff --git a/verigraph/service/src/mcnet/netobjs/PolitoWebClient.java b/verigraph/service/src/mcnet/netobjs/PolitoWebClient.java new file mode 100644 index 0000000..28e2cf2 --- /dev/null +++ b/verigraph/service/src/mcnet/netobjs/PolitoWebClient.java @@ -0,0 +1,107 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package mcnet.netobjs; + + +import java.util.ArrayList; +import java.util.List; + +import com.microsoft.z3.BoolExpr; +import com.microsoft.z3.Context; +import com.microsoft.z3.DatatypeExpr; +import com.microsoft.z3.Expr; +import com.microsoft.z3.FuncDecl; +import com.microsoft.z3.IntExpr; +import com.microsoft.z3.Solver; + +import mcnet.components.NetContext; +import mcnet.components.Network; +import mcnet.components.NetworkObject; + +/** + * WebClient + */ +public class PolitoWebClient extends NetworkObject{ + + List<BoolExpr> constraints; + Context ctx; + DatatypeExpr politoWebClient; + Network net; + NetContext nctx; + FuncDecl isInBlacklist; + + public PolitoWebClient(Context ctx, Object[]... args) { + super(ctx, args); + } + + @Override + protected void init(Context ctx, Object[]... args) { + this.ctx = ctx; + isEndHost=true; + constraints = new ArrayList<BoolExpr>(); + z3Node = ((NetworkObject)args[0][0]).getZ3Node(); + politoWebClient = z3Node; + net = (Network)args[0][1]; + nctx = (NetContext)args[0][2]; + DatatypeExpr ipServer = (DatatypeExpr) args[0][3]; + webClientRules(ipServer); + //net.saneSend(this); + } + + @Override + public DatatypeExpr getZ3Node() { + return politoWebClient; + } + + @Override + protected void addConstraints(Solver solver) { +// System.out.println("[MailClient] Installing rules."); + BoolExpr[] constr = new BoolExpr[constraints.size()]; + solver.add(constraints.toArray(constr)); + } + + private void webClientRules (DatatypeExpr ipServer){ + Expr n_0 = ctx.mkConst("PolitoWebClient_"+politoWebClient+"_n_0", nctx.node); + Expr p_0 = ctx.mkConst("PolitoWebClient_"+politoWebClient+"_p_0", nctx.packet); + IntExpr t_0 = ctx.mkIntConst("PolitoWebClient_"+politoWebClient+"_t_0"); + + //Constraint1 send(politoWebClient, n_0, p, t_0) -> nodeHasAddr(politoWebClient,p.src) + constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies((BoolExpr)nctx.send.apply(politoWebClient, n_0, p_0, t_0), + (BoolExpr)nctx.nodeHasAddr.apply(politoWebClient,nctx.pf.get("src").apply(p_0))),1,null,null,null,null)); + + //Constraint2 send(politoWebClient, n_0, p, t_0) -> p.origin == politoWebClient + constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies((BoolExpr)nctx.send.apply(politoWebClient, n_0, p_0, t_0), + ctx.mkEq(nctx.pf.get("origin").apply(p_0),politoWebClient)),1,null,null,null,null)); + + //Constraint3 send(politoWebClient, n_0, p, t_0) -> p.orig_body == p.body + constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies((BoolExpr)nctx.send.apply(politoWebClient, n_0, p_0, t_0), + ctx.mkEq(nctx.pf.get("orig_body").apply(p_0),nctx.pf.get("body").apply(p_0))),1,null,null,null,null)); + + //Constraint4 recv(n_0, politoWebClient, p, t_0) -> nodeHasAddr(politoWebClient,p.dest) + constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies((BoolExpr)nctx.recv.apply(n_0,politoWebClient, p_0, t_0), + (BoolExpr)nctx.nodeHasAddr.apply(politoWebClient,nctx.pf.get("dest").apply(p_0))),1,null,null,null,null)); + + + //Constraint5 This client is only able to produce HTTP requests + // send(politoWebClient, n_0, p, t_0) -> p.proto == HTTP_REQ + constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies((BoolExpr)nctx.send.apply(politoWebClient, n_0, p_0, t_0), + ctx.mkEq(nctx.pf.get("proto").apply(p_0), ctx.mkInt(nctx.HTTP_REQUEST))),1,null,null,null,null)); + + //Constraint6 send(politoWebClient, n_0, p, t_0) -> p.dest == ipServer + constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies((BoolExpr)nctx.send.apply(politoWebClient, n_0, p_0, t_0), + ctx.mkEq(nctx.pf.get("dest").apply(p_0), ipServer)),1,null,null,null,null)); + } + } diff --git a/verigraph/service/src/mcnet/netobjs/PolitoWebServer.java b/verigraph/service/src/mcnet/netobjs/PolitoWebServer.java new file mode 100644 index 0000000..54710d9 --- /dev/null +++ b/verigraph/service/src/mcnet/netobjs/PolitoWebServer.java @@ -0,0 +1,114 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package mcnet.netobjs; + + +import java.util.ArrayList; +import java.util.List; + +import com.microsoft.z3.BoolExpr; +import com.microsoft.z3.Context; +import com.microsoft.z3.DatatypeExpr; +import com.microsoft.z3.Expr; +import com.microsoft.z3.FuncDecl; +import com.microsoft.z3.IntExpr; +import com.microsoft.z3.Solver; + +import mcnet.components.NetContext; +import mcnet.components.Network; +import mcnet.components.NetworkObject; +/** + * WebServer object + * + */ +public class PolitoWebServer extends NetworkObject{ + + List<BoolExpr> constraints; + Context ctx; + DatatypeExpr node; + Network net; + NetContext nctx; + FuncDecl isInBlacklist; + + public PolitoWebServer(Context ctx, Object[]... args) { + super(ctx, args); + } + + @Override + protected void init(Context ctx, Object[]... args) { + this.ctx = ctx; + isEndHost=true; + constraints = new ArrayList<BoolExpr>(); + z3Node = ((NetworkObject)args[0][0]).getZ3Node(); + node = z3Node; + net = (Network)args[0][1]; + nctx = (NetContext)args[0][2]; + webServerRules(); + } + + @Override + public DatatypeExpr getZ3Node() { + return node; + } + + @Override + protected void addConstraints(Solver solver) { + BoolExpr[] constr = new BoolExpr[constraints.size()]; + solver.add(constraints.toArray(constr)); + } + + private void webServerRules (){ + Expr n_0 = ctx.mkConst("webserver_"+node+"_n_0", nctx.node); + Expr p_0 = ctx.mkConst("webserver_"+node+"_p_0", nctx.packet); + Expr p_1 = ctx.mkConst("webserver_"+node+"_p_1", nctx.packet); + IntExpr t_0 = ctx.mkIntConst("webserver_"+node+"_t_0"); + IntExpr t_1 = ctx.mkIntConst("webserver_"+node+"_t_1"); + + //Constraint1 send(politoWebServer, n_0, p, t_0) -> nodeHasAddr(politoWebServer,p.src) + constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies((BoolExpr)nctx.send.apply(node, n_0, p_0, t_0), + (BoolExpr)nctx.nodeHasAddr.apply(node,nctx.pf.get("src").apply(p_0))),1,null,null,null,null)); + + //Constraint2 send(politoWebServer, n_0, p, t_0) -> p.origin == politoWebServer + constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies((BoolExpr)nctx.send.apply(node, n_0, p_0, t_0), + ctx.mkEq(nctx.pf.get("origin").apply(p_0),node)),1,null,null,null,null)); + + //Constraint3 send(politoWebServer, n_0, p, t_0) -> p.orig_body == p.body + constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies((BoolExpr)nctx.send.apply(node, n_0, p_0, t_0), + ctx.mkEq(nctx.pf.get("orig_body").apply(p_0),nctx.pf.get("body").apply(p_0))), + 1,null,null,null,null)); + + //Constraint4 recv(n_0, politoWebServer, p, t_0) -> nodeHasAddr(politoWebServer,p.dest) + constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies((BoolExpr)nctx.recv.apply(n_0,node, p_0, t_0), + (BoolExpr)nctx.nodeHasAddr.apply(node,nctx.pf.get("dest").apply(p_0))),1,null,null,null,null)); + + //Constraint5 + // send(politoWebServer, n_0, p, t_0) -> + // (exist p_1,t_1 : + // (t_1 < t_0 && recv(n_0, politoWebServer, p_1, t_1) && + // p_0.proto == HTTP_RESP && p_1.proto == HTTP_REQ && + // p_0.dest == p_1.src && p_0.src == p_1.dest && p_0.url == p_1.url) + constraints.add( ctx.mkForall(new Expr[]{n_0, p_0, t_0}, + ctx.mkImplies((BoolExpr)nctx.send.apply(node, n_0, p_0, t_0), + ctx.mkExists(new Expr[]{p_1, t_1}, + ctx.mkAnd( + ctx.mkLt(t_1, t_0), + ctx.mkEq(nctx.pf.get("url").apply(p_0), nctx.pf.get("url").apply(p_1)), + (BoolExpr)nctx.recv.apply(n_0, node, p_1, t_1), + ctx.mkEq(nctx.pf.get("proto").apply(p_0), ctx.mkInt(nctx.HTTP_RESPONSE)), + ctx.mkEq(nctx.pf.get("proto").apply(p_1), ctx.mkInt(nctx.HTTP_REQUEST)), + ctx.mkEq(nctx.pf.get("dest").apply(p_0), nctx.pf.get("src").apply(p_1)), + ctx.mkEq(nctx.pf.get("src").apply(p_0), nctx.pf.get("dest").apply(p_1))), + 1,null,null,null,null)),1,null,null,null,null)); + } +} diff --git a/verigraph/service/src/tests/j-verigraph-generator/README.rst b/verigraph/service/src/tests/j-verigraph-generator/README.rst new file mode 100644 index 0000000..c796af7 --- /dev/null +++ b/verigraph/service/src/tests/j-verigraph-generator/README.rst @@ -0,0 +1,54 @@ +.. This work is licensed under a Creative Commons Attribution 4.0 International License. +.. http://creativecommons.org/licenses/by/4.0 + +CODE\_GENERATOR Java serializer and formatter + +UTILITY Contains utility methods used by other modules + +JSON\_GENERATOR Interactive module to generate the configuration files +(default names are "chains.json" and "config.json") "chains.json" +describes all the chains of nodes belonging to a certain scenario + +TEST\_CLASS\_GENERATOR Generates one or multiple test scenarios given +the two configuration files above (default names are "chains.json" and +"config.json") All the test scenarios have to be placed in the examples +folder (i. e. under "j-verigraph/service/src/tests/examples"). Here is +the script help: + +test\_class\_generator.py -c -f -o + +Supposing the module gets executed from the project root directory (i.e. +"j-verigraph"), a sample command is the following: + +service/src/tests/j-verigraph-generator/test\_class\_generator.py -c +"service/src/tests/j-verigraph-generator/examples/budapest/chains.json" +-f +"service/src/tests/j-verigraph-generator/examples/budapest/config.json" +-o "service/src/tests/examples/Scenario" + +Keep in mind that in the previous command "Scenario" represents a prefix +which will be followed by an underscore and an incremental number +starting from 1, which represents the n-th scenario starting from the +previously mentioned "chains.json" file (this file can indeed contain +multiple chains). + +TEST\_GENERATOR Generates a file which performs the verification test +through Z3 (theorem prover from Microsoft Research) given a certain +scenario generated with the above snippet. All the test modules have to +be placed under the "tests" directory (i.e. under +"j-verigraph/service/src/tests"). Here is the module help: + +test\_generator.py -i -o -s -d + +Supposing the module gets executed from the project root directory (i.e. +"j-verigraph") a sample command given the previously generated scenario +is the following: + +service/src/tests/j-verigraph-generator/test\_generator.py -i +service/src/tests/examples/Scenario\_1.java -o +service/src/tests/Test.java -s user1 -d webserver + +The aforementioned "Test.java" file can be compiled and executed +normally. Its output will be either "SAT" or "UNSAT". For possible +statistics the test is repeated 10 times and the average execution time +in seconds is printed to the console. diff --git a/verigraph/service/src/tests/j-verigraph-generator/__init__.py b/verigraph/service/src/tests/j-verigraph-generator/__init__.py new file mode 100644 index 0000000..d8a620f --- /dev/null +++ b/verigraph/service/src/tests/j-verigraph-generator/__init__.py @@ -0,0 +1,8 @@ +############################################################################## +# Copyright (c) 2017 Politecnico di Torino and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## diff --git a/verigraph/service/src/tests/j-verigraph-generator/batch_generator.py b/verigraph/service/src/tests/j-verigraph-generator/batch_generator.py new file mode 100644 index 0000000..517bdf7 --- /dev/null +++ b/verigraph/service/src/tests/j-verigraph-generator/batch_generator.py @@ -0,0 +1,186 @@ +#!/usr/bin/python + +############################################################################## +# Copyright (c) 2017 Politecnico di Torino and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +import json +from pprint import pprint +import sys, getopt +import commands +import os +from config import * +from utility import * +import subprocess + +#global variables +chains = {} +chains["chains"] = [] +routing = {} +routing["routing_table"] = [] +configuration = {} +configuration["nodes"] = [] +#end of global variables + + +#generates json file describing the chains (default chains.json) +def generate_chains(curr_dir, multiplier, flowspace): + filename = "chains.json" + + multiplier = int(multiplier) + number_of_chains = multiplier*multiplier + for i in range(0, int(number_of_chains)): + chains["chains"].insert(i, {}) + chains["chains"][i]["id"] = i+1 + chains["chains"][i]["flowspace"] = flowspace + chain_nodes = multiplier + chains["chains"][i]["nodes"] = [] + #set attributes for nth client + chains["chains"][i]["nodes"].insert(0, {}) + node_name = "client_" + str((i%multiplier)+1) + chains["chains"][i]["nodes"][0]["name"] = node_name + node_type = "web_client" + chains["chains"][i]["nodes"][0]["functional_type"] = node_type + node_address = "ip_web_client_" + str((i%multiplier)+1) + chains["chains"][i]["nodes"][0]["address"] = node_address + #set attributes for chain of firewalls + for j in range(1, chain_nodes+1): + chains["chains"][i]["nodes"].insert(j, {}) + node_name = "firewall_" + str(j) + chains["chains"][i]["nodes"][j]["name"] = node_name + node_type = "firewall" + chains["chains"][i]["nodes"][j]["functional_type"] = node_type + node_address = "ip_firewall_" + str(j) + chains["chains"][i]["nodes"][j]["address"] = node_address + #set attributes for nth web server + chains["chains"][i]["nodes"].insert(chain_nodes+1, {}) + node_name = "server_" + str((i%multiplier)+1) + chains["chains"][i]["nodes"][chain_nodes+1]["name"] = node_name + node_type = "web_server" + chains["chains"][i]["nodes"][chain_nodes+1]["functional_type"] = node_type + node_address = "ip_web_server_" + str((i%multiplier)+1) + chains["chains"][i]["nodes"][chain_nodes+1]["address"] = node_address + #pprint(chains) + with smart_open(curr_dir + "/" + filename) as f: + print >>f, json.dumps(chains) + return filename + +#generates json file describing the node configurations (default config.json) +def generate_config(curr_dir): + chains_file = "chains.json" + + chains = parse_chains(curr_dir + "/" + chains_file) + + print "Chains read from file:" + pprint(chains) + chains_id = [] + + for chain_id, chain in chains.items(): + chains_id.append(chain_id) + print "Chain #" + str(chain_id) + " has " + str(len(chain)) + " elements" + for node_name in chain.keys(): + print node_name + " ", + print "" + + + filename = "config.json" + + config_names = [] + + i = -1 + + for number_of_chain in chains_id: + number_of_nodes = len(chains[number_of_chain].keys()) + + # for i in range(0, number_of_nodes): + + for node_name, node_map in chains[number_of_chain].items(): + if node_name in config_names: + continue + config_names.append(node_name) + i += 1 + configuration["nodes"].insert(i, {}) + # node_id = raw_input("Node #" + str(i+1) + " id? -->") + # configuration["nodes"][i]["id"] = node_id + configuration["nodes"][i]["id"] = node_name + + name_split = node_name.split("_") + + #init = raw_input("Any parameter for inizialization of node " + node_name + "? (N/Y)-->") + init_list = devices_initialization[node_map["functional_type"]] + if init_list != []: + for init_item in init_list: + init_param = "ip_" + init_item + "_" + name_split[1] + configuration["nodes"][i][init_item] = init_param + + node_description = name_split[0] + " denies any traffic from web_client #" + name_split[1] + " to web_server #" + name_split[1] + configuration["nodes"][i]["description"] = node_description + while(True): + #node_configuration_type = raw_input("Node " + node_id +"'s configuration type (list, maps)? (L/M) -->") + #n = search_node_in_chains(node_id) + + node_configuration_type = devices_configuration_methods[node_map["functional_type"]] + if node_configuration_type == "list": + #list + configuration["nodes"][i]["configuration"] = [] + + break + if node_configuration_type == "maps": + #maps + configuration["nodes"][i]["configuration"] = [] + n_entries = 1 + + for m in range(0, n_entries): + configuration["nodes"][i]["configuration"].insert(m, {}) + + map_elements = 1 + + for n in range(0, map_elements): + key = "ip_web_server_" + name_split[1] + value = "ip_web_client_" + name_split[1] + configuration["nodes"][i]["configuration"][m][key] = value + break + else: + print "Invalid config, please edit the config file" + #pprint(configuration) + with smart_open(curr_dir + "/" + filename) as f: + print >>f, json.dumps(configuration) + return filename + +def main(argv): + #exit if any command line argument is missing + if len(argv) < 4: + print 'batch_generator.py -m <multiplier> -o <output_directory>' + sys.exit(2) + #initialize json file names + chains_file = '' + configuration_file = '' + output_dir = '' + multiplier = '' + #parse command line arguments and exit if there is an error + try: + opts, args = getopt.getopt(argv,"hm:o:",["mutliplier=","help","odir="]) + except getopt.GetoptError as err: + print str(err) + print 'batch_generator.py -m <multiplier> -o <output_directory>' + sys.exit(2) + for opt, arg in opts: + if opt in ("-h", "--help"): + print 'batch_generator.py -m <multiplier> -o <output_directory>' + sys.exit() + elif opt in ("-o", "--output"): + output_dir = arg + elif opt in ("-m", "--multiplier"): + multiplier = arg + + generate_chains(output_dir, multiplier, "tcp=80") + generate_config(output_dir) + + +if __name__ == "__main__": + main(sys.argv[1:]) diff --git a/verigraph/service/src/tests/j-verigraph-generator/code_generator.py b/verigraph/service/src/tests/j-verigraph-generator/code_generator.py new file mode 100644 index 0000000..5b9834f --- /dev/null +++ b/verigraph/service/src/tests/j-verigraph-generator/code_generator.py @@ -0,0 +1,59 @@ +#!/usr/bin/python + +############################################################################## +# Copyright (c) 2017 Politecnico di Torino and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +import sys, string + +class CodeGeneratorBackend: + + def begin(self, tab="\t"): + self.code = [] + self.tab = tab + self.level = 0 + + def end(self): + return string.join(self.code, "") + + def write(self, string): + self.code.append(self.tab * self.level + string) + + def writeln(self, string): + self.code.append(self.tab * self.level + string + "\n") + + def append(self, string): + self.code.append(string) + + def indent(self): + self.level = self.level + 1 + + def dedent(self): + if self.level == 0: + raise SyntaxError, "internal error in code generator" + self.level = self.level - 1 + + def write_list(self, data, delimiter=True, wrapper="'"): + if delimiter == True: + self.code.append("{") + first = True + for element in data: + if (first == False): + self.code.append(", ") + else: + first = False + if wrapper == "'": + self.code.append("'" + str(element) + "'") + elif wrapper == "\"": + self.code.append("\"" + str(element) + "\"") + elif wrapper == "b": + self.code.append("(" + str(element) + ")") + else: + self.code.append(str(element)) + if delimiter == True: + self.code.append("}") diff --git a/verigraph/service/src/tests/j-verigraph-generator/config.py b/verigraph/service/src/tests/j-verigraph-generator/config.py new file mode 100644 index 0000000..3fe5d6c --- /dev/null +++ b/verigraph/service/src/tests/j-verigraph-generator/config.py @@ -0,0 +1,88 @@ +#!/usr/bin/python + +############################################################################## +# Copyright (c) 2017 Politecnico di Torino and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +devices_to_classes = { "webclient" : "PolitoWebClient", + "webserver" : "PolitoWebServer", + "cache" : "PolitoCache", + "nat" : "PolitoNat", + "firewall" : "AclFirewall", + "mailclient" : "PolitoMailClient", + "mailserver" : "PolitoMailServer", + "antispam" : "PolitoAntispam", + "endpoint": "EndHost", + "dpi": "PolitoIDS", + "endhost": "PolitoEndHost", + "vpnaccess":"PolitoVpnAccess", + "vpnexit":"PolitoVpnExit", + "fieldmodifier":"PolitoFieldModifier" + } +devices_to_configuration_methods = {"webclient" : "", + "webserver" : "", + "cache" : "installCache", + "nat" : "setInternalAddress", + "firewall" : "addAcls", + "mailclient" : "", + "mailserver" : "", + "antispam" : "", + "endpoint": "", + "dpi": "installIDS", + "endhost": "installEndHost", + "vpnaccess":"vpnAccessModel", + "vpnexit":"vpnAccessModel", + "fieldmodifier":"installFieldModifier" + } +devices_initialization = { "webclient" : ["webserver"], + "webserver" : [], + "cache" : [], + "nat" : [], + "firewall" : [], + "mailclient" : ["mailserver"], + "mailserver" : [], + "antispam" : [], + "endpoint": [], + "dpi":[] , + "endhost":[], + "vpnaccess":[], + "vpnexit":[], + "fieldmodifier":[] + } + +convert_configuration_property_to_ip = { "webclient" : ["value"], + "webserver" : [], + "cache" : ["value"], + "nat" : ["value"], + "firewall" : ["key", "value"], + "mailclient" : ["value"], + "mailserver" : [], + "antispam" : [], + "endpoint": [], + "dpi": [], + "endhost": [], + "vpnaccess": ["value"], + "vpnexit": ["value"], + "fieldmodifier": [] + } + +devices_configuration_fields = { "webclient" : "", + "webserver" : "", + "cache" : "cached address", + "nat" : "natted address", + "firewall" : "acl entry", + "mailclient" : "", + "mailserver" : "", + "antispam" : "", + "endpoint": "", + "dpi":"words blacklist", + "endhost":"", + "vpnaccess":"vpn access", + "vpnexit":"vpn exit", + "fieldmodifier":"field modifier" + } diff --git a/verigraph/service/src/tests/j-verigraph-generator/json_generator.py b/verigraph/service/src/tests/j-verigraph-generator/json_generator.py new file mode 100644 index 0000000..d65ea43 --- /dev/null +++ b/verigraph/service/src/tests/j-verigraph-generator/json_generator.py @@ -0,0 +1,261 @@ +#!/usr/bin/python + +############################################################################## +# Copyright (c) 2017 Politecnico di Torino and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +import json +from pprint import pprint +import sys +import commands +import os +from config import * +from utility import * +import batch_generator +import subprocess + +#global variables +chains = {} +chains["chains"] = [] +routing = {} +routing["routing_table"] = [] +configuration = {} +configuration["nodes"] = [] +#end of global variables + + + +#generates json file describing the chains (default chains.json) +def generate_chains(curr_dir): + filename = "chains.json" + fn = raw_input("Please enter a file name for the json file describing the nodes chains (default \"chains.json\") -->") + if fn != "": + filename = fn + + number_of_chains = check_input_is_int("Please enter the number of chains you wish to simulate: -->") + for i in range(0, int(number_of_chains)): + chains["chains"].insert(i, {}) + #decomment the following 2 lines to make chain id an arbitrary integer + #chain_id = check_input_is_int("Chain #" + str(i+1) + " id? -->") + #chains["chains"][i]["id"] = chain_id + chains["chains"][i]["id"] = i+1 + flowspace = raw_input("Chain #" + str(i+1) + " flowspace? -->") + chains["chains"][i]["flowspace"] = flowspace + chain_nodes = check_input_is_int("How many nodes does the chain #" + str(i+1) + " have? -->") + chains["chains"][i]["nodes"] = [] + for j in range(0, chain_nodes): + chains["chains"][i]["nodes"].insert(j, {}) + node_name = raw_input("Node #" + str(j+1) + " name? -->") + chains["chains"][i]["nodes"][j]["name"] = node_name + print "Available functional types are:" + for device in devices_to_classes.keys(): + print device + " ", + while True: + node_type = raw_input("Node #" + str(j+1) + " functional_type (see valid options above)? -->") + if node_type in devices_to_classes.keys(): + break + chains["chains"][i]["nodes"][j]["functional_type"] = node_type + node_address = raw_input("Node #" + str(j+1) + " address? -->") + chains["chains"][i]["nodes"][j]["address"] = node_address + #pprint(chains) + with smart_open(curr_dir + "/" + filename) as f: + print >>f, json.dumps(chains) + return filename + +#generates json file describing the node configurations (default config.json) +def generate_config(curr_dir): + chains_file = "chains.json" + while True: + list_files(curr_dir) + fn = raw_input("Please enter the file name of the json file containing the chains (default \"chains.json\") -->") + if fn != "": + chains_file = fn + try: + chains = parse_chains(curr_dir + "/" + chains_file) + except: + print "Chains file is not valid" + continue + break + print "Chains read from file:" + pprint(chains) + chains_id = [] + + for chain_id, chain in chains.items(): + chains_id.append(chain_id) + print "Chain #" + str(chain_id) + " has " + str(len(chain)) + " elements" + for node_name in chain.keys(): + print node_name + " ", + print "" + + while True: + number_of_chain = check_input_is_int("Please enter the number of the chain you wish to configure: -->") + if number_of_chain in chains_id: + break + else: + print "Please enter a valid chain id (see options above)" + + filename = "config.json" + fn = raw_input("Please enter a file name for the json file describing the nodes configuration (default \"config.json\") -->") + if fn != "": + filename = fn + + number_of_nodes = len(chains[number_of_chain].keys()) + +# for i in range(0, number_of_nodes): + i = -1 + for node_name, node_map in chains[number_of_chain].items(): + i += 1 + configuration["nodes"].insert(i, {}) +# node_id = raw_input("Node #" + str(i+1) + " id? -->") +# configuration["nodes"][i]["id"] = node_id + configuration["nodes"][i]["id"] = node_name + #init = raw_input("Any parameter for inizialization of node " + node_name + "? (N/Y)-->") + init_list = devices_initialization[node_map["functional_type"]] + if init_list != []: + for init_item in init_list: + init_param = raw_input("Please enter the IP address of parameter \"" + init_item + "\" for node " + node_name + ": -->") + configuration["nodes"][i][init_item] = init_param + + node_description = raw_input("Node " + node_name +"'s configuration description? -->") + configuration["nodes"][i]["description"] = node_description + while(True): + #node_configuration_type = raw_input("Node " + node_id +"'s configuration type (list, maps)? (L/M) -->") + #n = search_node_in_chains(node_id) + + node_configuration_type = devices_configuration_methods[node_map["functional_type"]] + if node_configuration_type == "list": + #list + configuration["nodes"][i]["configuration"] = [] + config_elements = check_input_is_int("How many configuration elements for node " + node_name + "? (type 0 to skip configuration) -->") + for e in range(0, config_elements): + element = raw_input("\tPlease enter " + devices_configuration_fields[node_map["functional_type"]] + "#" + str(e+1) + " -->") + configuration["nodes"][i]["configuration"].append(element) + break + elif node_configuration_type == "maps": + #maps + configuration["nodes"][i]["configuration"] = [] + n_entries = check_input_is_int("How many maps for the configuration of node " + node_name + "? (type 0 to skip configuration) -->") + + for m in range(0, n_entries): + configuration["nodes"][i]["configuration"].insert(m, {}) + + map_elements = check_input_is_int("How many elements for map #" + str(m+1) + "? -->") + + for n in range(0, map_elements): + key = raw_input("\tKey for " + devices_configuration_fields[node_map["functional_type"]] + "#" + str(n+1) + ": -->") + value = raw_input("\tValue for " + devices_configuration_fields[node_map["functional_type"]] + "#" + str(n+1) + ": -->") + configuration["nodes"][i]["configuration"][m][key] = value + break + else: + print "Invalid config, please edit the config file" + #pprint(configuration) + with smart_open(curr_dir + "/" + filename) as f: + print >>f, json.dumps(configuration) + return filename + + +def main(): + + chains_file = "" + configuration_file = "" + routing_file = "" + curr_dir = os.getcwd() + current_path = curr_dir + + set_dir = raw_input("Change working directory? (" + curr_dir + ") (N/Y) -->") + if set_dir == "Y" or set_dir == "y": + print "List of subdirectories:" + print list_directories(curr_dir) + while True: + curr_dir = os.path.abspath(raw_input("Enter working path (relative or absolute path are supported) -->")) + if os.path.exists(curr_dir): + current_path = curr_dir + break + else: + print "Please enter a valid path!" + + directory = raw_input("Do you want to create a new test directory? (N/Y) -->") + if directory == "Y" or directory =="y": + directory_name = raw_input("Directory name? -->") + print commands.getoutput("mkdir -v " + curr_dir + "/" + directory_name) + current_path = curr_dir + "/" + directory_name + + print "Files will be created at " + current_path + + firewall_chain = False + + while True: + choice = raw_input("""CHAINS?\n + Choose one of the following options:\n + 1) Automatic generation of chains.json and config.json for an N-firewall chain + 2) Generate step-by-step + 3) Verify the integrity of an existing json file + 4) Skip step\n-->""") + try: + if int(choice) == 1: + multiplier = check_input_is_int("Please enter N -->") + arguments = ["-m", str(multiplier), "-o", current_path] + batch_generator.main(arguments) + firewall_chain = True + break + elif int(choice) == 2: + chains_file = generate_chains(current_path) + break + elif int(choice) == 3: + chains_file = raw_input("Input file for CHAINS? -->") + if(check_chains_integrity(current_path + "/" + chains_file)) == True: + break + else: + print "Input json file for CHAINS not well formed, please try again!" + elif int(choice) == 4: + break + else: + print "Invalid choice, please try again!" + except ValueError, e: + print "Invalid choice, please try again!" + continue + + while True: + + if firewall_chain == True: + chains_file = "chains.json" + configuration_file = "config.json" + routing_file = "" + break + + choice = raw_input("""CONFIGURATION?\n + Choose one of the following options:\n + 1) Generate step-by-step + 2) Verify the integrity of an existing json file + 3) Skip step\n-->""") + try: + if int(choice) == 1: + configuration_file = generate_config(current_path) + break + elif int(choice) == 2: + configuration_file = raw_input("Input file for CONFIGURATION? -->") + if(check_config_integrity(current_path + "/" + configuration_file)) == True: + break + else: + print "Input json file for CONFIGURATION not well formed, please try again!" + elif int(choice) == 3: + break + else: + print "Invalid choice, please try again!" + except ValueError, e: + print "Invalid choice, please try again!" + continue + + print "All done, you are ready to launch the test generator like so:" + print "test_class_generator.py -c " + chains_file + " -f " + configuration_file + " -o <output_file>" + + return chains_file, configuration_file, routing_file, current_path + + +if __name__ == "__main__": + main() diff --git a/verigraph/service/src/tests/j-verigraph-generator/routing_generator.py b/verigraph/service/src/tests/j-verigraph-generator/routing_generator.py new file mode 100644 index 0000000..c8956f2 --- /dev/null +++ b/verigraph/service/src/tests/j-verigraph-generator/routing_generator.py @@ -0,0 +1,80 @@ +#!/usr/bin/python + +############################################################################## +# Copyright (c) 2017 Politecnico di Torino and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +from pprint import pprint +import sys, getopt +import os +from utility import * + +# used by test_class_generator +def generate_routing_from_chain(chain): + routing = {} + routing["routing_table"] = {} + + chain = chain["nodes"] + for i in range(0, len(chain)): + routing["routing_table"][chain[i]["name"]] = {} + for j in range(i-1, -1, -1): + routing["routing_table"][chain[i]["name"]][chain[j]["address"]] = chain[i-1]["name"] + for k in range (i+1, len(chain)): + routing["routing_table"][chain[i]["name"]][chain[k]["address"]] = chain[i+1]["name"] + pprint(routing) + return routing + +def generate_routing_from_chains_file(chains_file, chain_number): + routing = {} + routing["routing_table"] = {} + + chains = convert_unicode_to_ascii(parse_json_file(chains_file)) + chain = None + for chn in chains["chains"]: + if chn["id"] == chain_number: + chain = chn["nodes"] + break + if chain == None: + return routing + + for i in range(0, len(chain)): + routing["routing_table"][chain[i]["name"]] = {} + for j in range(i-1, -1, -1): + routing["routing_table"][chain[i]["name"]][chain[j]["address"]] = chain[i-1]["name"] + for k in range (i+1, len(chain)): + routing["routing_table"][chain[i]["name"]][chain[k]["address"]] = chain[i+1]["name"] + pprint(routing) + return routing + +def main(argv): + if len(argv) < 4: + print 'routing_generator.py -c <chains_file> -n <chain_number>' + sys.exit(2) + chains_file = "" + chain_number = "" + try: + opts, args = getopt.getopt(argv,"hc:n:",["chains=","id="]) + except getopt.GetoptError: + print 'routing_generator.py -c <chains_file> -n <chain_number>' + sys.exit(2) + for opt, arg in opts: + if opt == '-h': + print 'routing_generator.py -c <chains_file> -n <chain_number>' + sys.exit() + elif opt in ("-c", "--chains"): + chains_file = arg + elif opt in ("-n", "--id"): + chain_number = arg + + print "Chains file is " + chains_file + print "Chain id is " + chain_number + + return generate_routing_from_chains_file(chains_file, chain_number) + +if __name__ == '__main__': + main(sys.argv[1:])
\ No newline at end of file diff --git a/verigraph/service/src/tests/j-verigraph-generator/test_class_generator.py b/verigraph/service/src/tests/j-verigraph-generator/test_class_generator.py new file mode 100644 index 0000000..7bf446c --- /dev/null +++ b/verigraph/service/src/tests/j-verigraph-generator/test_class_generator.py @@ -0,0 +1,399 @@ +#!/usr/bin/python + +############################################################################## +# Copyright (c) 2017 Politecnico di Torino and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +from pprint import pprint +from pprint import pformat +import sys, getopt +from code_generator import CodeGeneratorBackend +import os, errno +from config import * +from utility import * +from routing_generator import * +import logging +from pip._vendor.pkg_resources import null_ns_handler + +#generates a custom test file +def generate_test_file(chain, number, configuration, output_file="test_class"): + + route = {} + config = {} + chn = {} + + #initiatlize the config dictionary for each node + for node in chain["nodes"]: + config[node["name"]] = {} + + #initiatlize the route dictionary for each node + for node in chain["nodes"]: + route[node["name"]] = {} + + #initiatlize the chn dictionary for each node + for node in chain["nodes"]: + chn[node["name"]] = {} + + #set chn values: chn[name][key] = value + for node in chain["nodes"]: + for key, value in node.items(): + try: + #name key is redundant in map + if key != "name": + chn[node["name"]][key] = value + except KeyError, e: + logging.debug("Field " + str(key) + " not found for node " + str(node["name"])) + logging.debug("Cotinuing...") + continue + + #debug print of chn + logging.debug(pformat((chn))) + + routing = generate_routing_from_chain(chain) + + for node_name, node_rt in routing["routing_table"].items(): + route[node_name] = node_rt + + #debug print of route + logging.debug(pformat((route))) + + #set config: config[node_name][key] = value + for node in configuration["nodes"]: + for key, value in node.items(): + #id field is redundant + if key != "id": + try: + if key == "configuration": + #init config[node_name][key] with an empty array + config[node["id"]][key] = [] + + for value_item in value: + change_key = "key" in convert_configuration_property_to_ip[chn[node["id"]]["functional_type"]] + change_value = "value" in convert_configuration_property_to_ip[chn[node["id"]]["functional_type"]] + if (change_key==False and change_value==False): + config[node["id"]][key].append(value_item) + continue + # config[node_name][configuration] is a dictionary + if isinstance(value_item, dict): + for config_item_key, config_item_value in value_item.items(): + new_key = config_item_key + changed_key = False + changed_value = False + if change_key and config_item_key in chn.keys(): + changed_key = True + new_key = "ip_" + str(config_item_key) + value_item[new_key] = str(config_item_value) + del value_item[config_item_key] + if change_value and config_item_value in chn.keys(): + changed_value = True + new_value = "ip_" + str(config_item_value) + value_item[new_key] = new_value + if(change_key==changed_key) and (change_value==changed_value): + config[node["id"]][key].append(value_item) + else: + if change_value: + if value_item in chn.keys(): + new_value = "ip_" + str(value_item) + config[node["id"]][key].append(new_value) + else: + config[node["id"]][key].append(str(value_item)) + else: + config[node["id"]][key] = value + except KeyError, e: + #node not found in current chain + logging.debug("Field '" + key + "' not found for node '" + str(node["id"]) + "'") + logging.debug(key + " probably doesn't belong to the current chain, thus it will be skipped") + #sys.exit(1) + continue + + # debug print of config + logging.debug(pformat((config))) + + #prepare a few more helpful data structures + nodes_names = [] + nodes_types = [] + nodes_addresses = [] + nodes_ip_mappings = [] + nodes_rt = {} + + #initialize vectors for node names and routing tables + for name in chn.keys(): + nodes_names.append(name) + nodes_rt[name] = [] + + #add functional types, addresses and ip mapping to vectors + for node, field in chn.items(): + nodes_types.append(field["functional_type"]) + nodes_addresses.append(field["address"]) + nodes_ip_mappings.append(field["address"]) + + for node, rt in route.items(): + for dest, next_hop in rt.items(): + row = "nctx.am.get(\"" + dest + "\"), " + next_hop + try: + nodes_rt[node].append(row) + except KeyError, e: + #node not found, notify and exit + logging.debug("Node " + node + " not found!") + sys.exit(1) + + #begin file generation + logging.debug("* instantiating chain #" + str(number)) + dirname = os.path.dirname(output_file) + basename = os.path.basename(output_file) + basename = os.path.splitext(basename)[0] + basename = basename[0].upper() + basename[1:] + with smart_open(dirname + "/" + basename + "_" + str(number) + ".java") as f: + c = CodeGeneratorBackend() + c.begin(tab=" ") + + c.writeln("package tests.scenarios;") + + #imports here + c.writeln("import java.util.ArrayList;") + c.writeln("import com.microsoft.z3.Context;") + c.writeln("import com.microsoft.z3.DatatypeExpr;") + + c.writeln("import mcnet.components.Checker;") + c.writeln("import mcnet.components.NetContext;") + c.writeln("import mcnet.components.Network;") + c.writeln("import mcnet.components.NetworkObject;") + c.writeln("import mcnet.components.Tuple;") + c.writeln("import mcnet.netobjs.PacketModel;") + + #import components + #for i in range(0, len(nodes_names)): + # c.writeln("import mcnet.netobjs." + devices_to_classes[str(nodes_types[i])] + ";") + + for key, value in devices_to_classes.items(): + c.writeln("import mcnet.netobjs." + value + ";") + + c.writeln("public class " + basename + "_" + str(number) + "{") + + c.indent() + c.writeln("public Checker check;") + # declare components + for i in range(0, len(nodes_names)): + c.writeln("public " + devices_to_classes[str(nodes_types[i])] + " " + str(nodes_names[i]) + ";") + + # method setDevices + c.writeln("private void setDevices(Context ctx, NetContext nctx, Network net){") + c.indent() + for i in range(0, len(nodes_names)): + c.write(str(nodes_names[i]) + " = new " + devices_to_classes[str(nodes_types[i])] + "(ctx, new Object[]{nctx.nm.get(\"" + nodes_names[i] + "\"), net, nctx") + if devices_initialization[nodes_types[i]] != [] : + for param in devices_initialization[nodes_types[i]]: + print "configuring node " + nodes_names[i] + for config_param in config[nodes_names[i]]["configuration"]: + if param in config_param: + c.append(", nctx.am.get(\"" + config_param[param] + "\")") + c.append("});\n") + c.dedent() + c.writeln("}") + # end method setDevices + + # method doMappings + c.writeln("private void doMappings(NetContext nctx, ArrayList<Tuple<NetworkObject,ArrayList<DatatypeExpr>>> adm){") + c.indent() + for i in range(0, len(nodes_names)): + c.writeln("ArrayList<DatatypeExpr> al" + str(i) + " = new ArrayList<DatatypeExpr>();") + c.writeln("al" + str(i) + ".add(nctx.am.get(\"" + nodes_ip_mappings[i] + "\"));") + c.writeln("adm.add(new Tuple<>((NetworkObject)" + nodes_names[i] + ", al" + str(i) + "));") + c.dedent() + c.writeln("}") + # end method doMappings + + # for each node methods setRouting and configureDevice + for i in range(0, len(nodes_names)): + # method setRouting + c.writeln("private void setRouting" + nodes_names[i] + "(NetContext nctx, Network net, ArrayList<Tuple<DatatypeExpr,NetworkObject>> rt_" + nodes_names[i] + "){") + c.indent() + for row in nodes_rt[nodes_names[i]]: + c.writeln("rt_" + nodes_names[i] + ".add(new Tuple<DatatypeExpr,NetworkObject>(" + row + "));") + c.writeln("net.routingTable(" + nodes_names[i] + ", rt_" + nodes_names[i] + ");") + c.dedent() + c.writeln("}") + # end method setRouting + # method configureDevice + c.writeln("private void configureDevice" + nodes_names[i] + "(NetContext nctx) {") + c.indent() + #configure middle-box only if its configuration is not empty + if config[nodes_names[i]]["configuration"] != [] : + if nodes_types[i] == "cache": + c.write(nodes_names[i] + "." + devices_to_configuration_methods[nodes_types[i]] + "(new NetworkObject[]") + cache_ips = config[nodes_names[i]]["configuration"] + cache_hosts = [] + for cache_ip in cache_ips: + i = -1 + for host in nodes_addresses: + i += 1 + if host == cache_ip: + cache_hosts.append(nodes_names[i]) + c.write_list(formatted_list_from_list_of_maps(cache_hosts), wrapper="") + c.append(");\n") + elif nodes_types[i] == "nat": + c.writeln("ArrayList<DatatypeExpr> ia" + str(i) +" = new ArrayList<DatatypeExpr>();") + config_elements = [] + config_elements = formatted_list_from_list_of_maps(config[nodes_names[i]]["configuration"]) + for address in config_elements: + c.writeln("ia" + str(i) + ".add(nctx.am.get(\"" + address + "\"));") + c.writeln(nodes_names[i] + ".natModel(nctx.am.get(\"ip_" + nodes_names[i] + "\"));") + c.writeln(nodes_names[i] + "." + devices_to_configuration_methods[nodes_types[i]] + "(ia" + str(i) +");") + elif nodes_types[i] == "firewall": + c.writeln("ArrayList<Tuple<DatatypeExpr,DatatypeExpr>> acl" + str(i) + " = new ArrayList<Tuple<DatatypeExpr,DatatypeExpr>>();") + for config_element in config[nodes_names[i]]["configuration"]: + if isinstance(config_element,dict): + for key, value in config_element.items(): + if key in nodes_addresses and value in nodes_addresses: + c.writeln("acl" + str(i) + ".add(new Tuple<DatatypeExpr,DatatypeExpr>(nctx.am.get(\"" + key + "\"),nctx.am.get(\"" + value + "\")));") + c.writeln(nodes_names[i] + "." + devices_to_configuration_methods[nodes_types[i]] + "(acl" + str(i) + ");") + elif nodes_types[i] == "antispam": + c.write(nodes_names[i] + "." + devices_to_configuration_methods[nodes_types[i]] + "(new int[]") + c.write_list(formatted_list_from_list_of_maps(config[nodes_names[i]]["configuration"])) + c.append(");\n") + elif nodes_types[i] == "dpi": + for index in range(0, len(config[nodes_names[i]]["configuration"])): + config[nodes_names[i]]["configuration"][index] = "String.valueOf(\"" + str(config[nodes_names[i]]["configuration"][index]) + "\").hashCode()" + c.write(nodes_names[i] + "." + devices_to_configuration_methods[nodes_types[i]] + "(new int[]") + c.write_list(formatted_list_from_list_of_maps(config[nodes_names[i]]["configuration"]), wrapper="") + c.append(");\n") + elif nodes_types[i] == "endhost": + c.writeln("PacketModel pModel" + str(i) + " = new PacketModel();") + if "body" in config[nodes_names[i]]["configuration"][0]: + c.writeln("pModel" + str(i) + ".setBody(String.valueOf(\"" + config[nodes_names[i]]["configuration"][0]["body"] + "\").hashCode());") + if "sequence" in config[nodes_names[i]]["configuration"][0]: + c.writeln("pModel" + str(i) + ".setSeq(" + config[nodes_names[i]]["configuration"][0]["sequence"] + ");") + if "protocol" in config[nodes_names[i]]["configuration"][0]: + c.writeln("pModel" + str(i) + ".setProto(nctx." + config[nodes_names[i]]["configuration"][0]["protocol"] + ");") + if "email_from" in config[nodes_names[i]]["configuration"][0]: + c.writeln("pModel" + str(i) + ".setEmailFrom(String.valueOf(\"" + config[nodes_names[i]]["configuration"][0]["email_from"] + "\").hashCode());") + if "url" in config[nodes_names[i]]["configuration"][0]: + c.writeln("pModel" + str(i) + ".setUrl(String.valueOf(\"" + config[nodes_names[i]]["configuration"][0]["url"] + "\").hashCode());") + if "options" in config[nodes_names[i]]["configuration"][0]: + c.writeln("pModel" + str(i) + ".setOptions(String.valueOf(\"" + config[nodes_names[i]]["configuration"][0]["options"] + "\").hashCode());") + if "destination" in config[nodes_names[i]]["configuration"][0]: + c.writeln("pModel" + str(i) + ".setIp_dest(nctx.am.get(\"" + config[nodes_names[i]]["configuration"][0]["destination"] + "\"));") + + c.writeln(nodes_names[i] + "." + devices_to_configuration_methods[nodes_types[i]] + "(pModel" + str(i) + ");") + elif nodes_types[i] == "vpnaccess": + c.writeln(nodes_names[i] + "." + devices_to_configuration_methods[nodes_types[i]] + "(nctx.am.get(\"" + nodes_addresses[i] + "\"), nctx.am.get(\"" + config[nodes_names[i]]["configuration"][0]["vpnexit"] + "\"));") + elif nodes_types[i] == "vpnexit": + c.writeln(nodes_names[i] + "." + devices_to_configuration_methods[nodes_types[i]] + "(nctx.am.get(\"" + config[nodes_names[i]]["configuration"][0]["vpnaccess"] + "\"), nctx.am.get(\"" + nodes_addresses[i] + "\"));") + + # config is empty but configure device anyway + elif nodes_types[i] == "fieldmodifier": + c.writeln(nodes_names[i] + "." + devices_to_configuration_methods[nodes_types[i]] + "();") + c.dedent() + c.writeln("}") + # end method configureDevice + + + c.writeln("public " + basename + "_" + str(number) + "(Context ctx){") + c.indent() + c.write("NetContext nctx = new NetContext (ctx,new String[]") + c.write_list(nodes_names, wrapper="\"") + c.append(", new String[]") + c.write_list(nodes_addresses, wrapper="\"") + c.append(");\n") + c.writeln("Network net = new Network (ctx,new Object[]{nctx});") + # call method setDevices + c.writeln("setDevices(ctx, nctx, net);") + + #SET ADDRESS MAPPINGS + c.writeln("ArrayList<Tuple<NetworkObject,ArrayList<DatatypeExpr>>> adm = new ArrayList<Tuple<NetworkObject,ArrayList<DatatypeExpr>>>();") + # call doMappings + c.writeln("doMappings(nctx, adm);") + c.writeln("net.setAddressMappings(adm);") + + #CONFIGURE ROUTING TABLE + for i in range(0, len(nodes_names)): + c.writeln("ArrayList<Tuple<DatatypeExpr,NetworkObject>> rt_" + nodes_names[i] + " = new ArrayList<Tuple<DatatypeExpr,NetworkObject>>(); ") + c.writeln("setRouting" + nodes_names[i] + "(nctx, net, rt_" + nodes_names[i] + ");") + + #ATTACH DEVICES + c.write("net.attach(") + c.write_list(nodes_names, delimiter = False, wrapper="") + c.append(");\n") + + #CONFIGURE MIDDLE-BOXES + for i in range(0, len(nodes_names)): + c.writeln("configureDevice" + nodes_names[i] + "(nctx);") + + c.writeln("check = new Checker(ctx,nctx,net);") + + c.dedent() + c.writeln("}") + + c.dedent() + c.writeln("}") + + #write c object to file + print >>f, c.end() + + logging.debug("wrote test file " + os.path.abspath(dirname + "/" + basename + "_" + str(number)) + ".java" + " successfully!") + + +def main(argv): + #exit if any command line argument is missing + if len(argv) < 6: + print 'test_class_generator.py -c <chain_file> -f <conf_file> -o <output_name>' + sys.exit(1) + + #initialize json file names + chains_file = '' + configuration_file = '' + output_file = '' + + #parse command line arguments and exit in case of any error + try: + opts, args = getopt.getopt(argv,"hc:f:r:o:",["help","chain=","config=","route=","ofile="]) + except getopt.GetoptError as err: + print str(err) + print 'test_class_generator.py -c <chain_file> -f <conf_file> -o <output_name>' + sys.exit(2) + for opt, arg in opts: + if opt in ("-h", "--help"): + print 'test_class_generator.py -c <chain_file> -f <conf_file> -o <output_name' + sys.exit() + elif opt in ("-c", "--chain"): + chains_file = arg + elif opt in ("-f", "--config"): + configuration_file = arg + elif opt in ("-o", "--ofile"): + output_file = arg + + #set logging + logging.basicConfig(stream=sys.stderr, level=logging.DEBUG) + + #parse chains file + chains = convert_unicode_to_ascii(parse_json_file(chains_file)) + + #parse configuration file + configuration = convert_unicode_to_ascii(parse_json_file(configuration_file)) + + logging.debug(pformat((chains))) + logging.debug(pformat((configuration))) + + #custom formatted prints + print_chains(chains) + print_configuration(configuration) + + #counter for the number of chains + number_of_chains = 0 + + #generate test classes + for chain in chains["chains"]: + #increment the number of chains + number_of_chains += 1; + #generate test files + generate_test_file(chain, number_of_chains, configuration, output_file) + + +if __name__ == "__main__": + main(sys.argv[1:]) + diff --git a/verigraph/service/src/tests/j-verigraph-generator/test_generator.py b/verigraph/service/src/tests/j-verigraph-generator/test_generator.py new file mode 100644 index 0000000..f4629bb --- /dev/null +++ b/verigraph/service/src/tests/j-verigraph-generator/test_generator.py @@ -0,0 +1,160 @@ +#!/usr/bin/python + +############################################################################## +# Copyright (c) 2017 Politecnico di Torino and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +from pprint import pprint +from code_generator import CodeGeneratorBackend +import sys, getopt +import contextlib +import os +from utility import * +import logging + +def main(argv): + if len(argv) < 8: + print 'test_generator.py -i <inputfile> -o <outputfile> -s <source> -d <destination>' + sys.exit(2) + #initialize command line arguments values + inputfile = '' + outputfile = '' + source = '' + destination = '' + #parse command line arguments and exit if there is an error + try: + opts, args = getopt.getopt(argv,"hi:o:s:d:",["ifile=","ofile=","source=","destination="]) + except getopt.GetoptError: + print 'test_generator.py -i <inputfile> -o <outputfile> -s <source> -d <destination>' + sys.exit(2) + for opt, arg in opts: + if opt == '-h': + print 'test_generator.py -i <inputfile> -o <outputfile> -s <source> -d <destination>' + sys.exit() + elif opt in ("-i", "--ifile"): + inputfile = arg + elif opt in ("-o", "--ofile"): + outputfile = arg + elif opt in ("-s", "--source"): + source = arg + elif opt in ("-d", "--destination"): + destination = arg + #set logging + logging.basicConfig(stream=sys.stderr, level=logging.INFO) + #capitalize ouput filename + dirname = os.path.dirname(outputfile) + basename = os.path.basename(outputfile) + basename = os.path.splitext(basename)[0] + basename = basename[0].upper() + basename[1:] + + #print arguments + logging.debug('Input file is', inputfile) + logging.debug('Output file is', dirname + "/" + basename) + logging.debug('Source node is', source) + logging.debug('Destination node is', destination) + + #begin file generation + with smart_open(dirname + "/" + basename + ".java") as f: + c = CodeGeneratorBackend() + c.begin(tab=" ") + c.writeln("package tests;") + c.writeln("import java.util.Calendar;") + c.writeln("import java.util.Date;") + c.writeln("import java.util.HashMap;") + + c.writeln("import com.microsoft.z3.Context;") + c.writeln("import com.microsoft.z3.FuncDecl;") + c.writeln("import com.microsoft.z3.Model;") + c.writeln("import com.microsoft.z3.Status;") + c.writeln("import com.microsoft.z3.Z3Exception;") + c.writeln("import mcnet.components.IsolationResult;") + + + inputfile = os.path.basename(inputfile) + c.writeln("import tests.scenarios." + os.path.splitext(inputfile)[0] + ";") + c.writeln("public class " + basename + "{") + + c.indent() + c.writeln("Context ctx;") + + c.write("public void resetZ3() throws Z3Exception{\n\ + HashMap<String, String> cfg = new HashMap<String, String>();\n\ + cfg.put(\"model\", \"true\");\n\ + ctx = new Context(cfg);\n\ + \r\t}\n") + + c.write("public void printVector (Object[] array){\n\ + int i=0;\n\ + System.out.println( \"*** Printing vector ***\");\n\ + for (Object a : array){\n\ + i+=1;\n\ + System.out.println( \"#\"+i);\n\ + System.out.println(a);\n\ + System.out.println( \"*** \"+ i+ \" elements printed! ***\");\n\ + }\n\ + \r\t}\n") + + c.write("public void printModel (Model model) throws Z3Exception{\n\ + for (FuncDecl d : model.getFuncDecls()){\n\ + System.out.println(d.getName() +\" = \"+ d.toString());\n\ + System.out.println(\"\");\n\ + }\n\ + \r\t}\n") + + c.writeln("public int run() throws Z3Exception{") + c.indent() + + c.writeln(basename + " p = new " + basename + "();") + + #adding time estimation + #c.writeln("int k = 0;") + #c.writeln("long t = 0;") + + #c.writeln("for(;k<1;k++){") + #c.indent() + + c.writeln("p.resetZ3();") + + c.write(os.path.splitext(inputfile)[0] + " model = new " + os.path.splitext(inputfile)[0] + "(p.ctx);\n") + + #c.writeln("Calendar cal = Calendar.getInstance();") + #c.writeln("Date start_time = cal.getTime();") + + c.write("IsolationResult ret =model.check.checkIsolationProperty(model.") + c.append(source + ", model." + destination + ");\n") + #c.writeln("Calendar cal2 = Calendar.getInstance();") + #c.writeln("t = t+(cal2.getTime().getTime() - start_time.getTime());") + + c.writeln("if (ret.result == Status.UNSATISFIABLE){\n\ + System.out.println(\"UNSAT\");\n\ + return -1;\n\ + }else if (ret.result == Status.SATISFIABLE){\n\ + System.out.println(\"SAT\");\n\ + return 0;\n\ + }else{\n\ + System.out.println(\"UNKNOWN\");\n\ + return -2;\n\ + \r\t\t}") + + #c.dedent() + #c.writeln("}") + + #c.writeln("") + #c.writeln("System.out.printf(\"Mean execution time " + source + " -> " + destination + ": %.16f\", ((float) t/(float)1000)/k);") + + c.dedent() + c.writeln("}") + + c.dedent() + c.writeln("}") + + print >>f, c.end() + logging.debug("File " + os.path.abspath(dirname + "/" + basename + ".java") + " has been successfully generated!!") + +if __name__ == "__main__": + main(sys.argv[1:]) diff --git a/verigraph/service/src/tests/j-verigraph-generator/utility.py b/verigraph/service/src/tests/j-verigraph-generator/utility.py new file mode 100644 index 0000000..47d0180 --- /dev/null +++ b/verigraph/service/src/tests/j-verigraph-generator/utility.py @@ -0,0 +1,257 @@ +#!/usr/bin/python + +############################################################################## +# Copyright (c) 2017 Politecnico di Torino and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +import json +import contextlib +import sys +import os +import subprocess +from pprint import pprint + +#manages output easily (can either write to file or to stdout) +@contextlib.contextmanager +def smart_open(filename=None): + if filename and filename != '-': + fh = open(filename, 'w') + else: + fh = sys.stdout + try: + yield fh + finally: + if fh is not sys.stdout: + fh.close() + +def check_input_is_int(text): + while True: + data = raw_input(text) + try: + int_value = int(data) + except ValueError: + print "Please enter a valid number!" + continue + return int_value + +#parses a json file into a unicode dictionary +def parse_json_file(filename): + with open(filename) as json_file: + return json.load(json_file) + +#returns an ascii dictionary from a unicode one +def convert_unicode_to_ascii(input): + if isinstance(input, dict): + return {convert_unicode_to_ascii(key): convert_unicode_to_ascii(value) for key, value in input.iteritems()} + elif isinstance(input, list): + return [convert_unicode_to_ascii(element) for element in input] + elif isinstance(input, unicode): + return input.encode('utf-8') + else: + return input + +#parses a chains file +def parse_chains(chains_file): + chains_json = convert_unicode_to_ascii(parse_json_file(chains_file)) + + chains = {} + + for chn in chains_json["chains"]: + try: + chains[chn["id"]] = {} + #initiatlize the config dictionary for each node + for node in chn["nodes"]: + chains[chn["id"]][node["name"]] = {} + except: + raise KeyError("Chains file is not valid!") + + for chn in chains_json["chains"]: + try: + #set chn values ---> chn(name, (field, value)) + for node in chn["nodes"]: + for key, value in node.items(): + #name key is redundant in map + if key != "name": + chains[chn["id"]][node["name"]][key] = value + except: + raise KeyError("Chains file is not valid!") + return chains + +def check_chains_integrity(filename): + print "Checking input file..." + try: + chains = convert_unicode_to_ascii(parse_json_file(filename)) + print "File correctly parsed" + if isinstance(chains["chains"], list) == False: + print "Child of chains is not a list!" + return False + for chain in chains["chains"]: + print "Chain found, checking its fields..." + print "Checking chain id field... " + chain["id"] + print "OK!" + print "Checking chain flowspace field... " + chain["flowspace"] + print "OK!" + if isinstance(chain["nodes"], list) == False: + print "Chain #" + chain["id"] + " does not have a list of nodes!" + return False + for node in chain["nodes"]: + print "Node found, checking its fields..." + print "Checking node name... " + node["name"] + print "OK!" + print "Checking node functional_type field... " + node["functional_type"] + print "OK!" + print "Checking node address field... " + node["address"] + print "OK!" + except (KeyboardInterrupt, SystemExit): + raise + except: + print "One or more required fields are missing!" + return False + print filename + " validated successfully!" + return True + +def check_config_integrity(filename): + print "Checking input file..." + try: + config = convert_unicode_to_ascii(parse_json_file(filename)) + pprint(config) + print "File correctly parsed" + if isinstance(config["nodes"], list) == False: + print "Child of nodes is not a list!" + return False + for node in config["nodes"]: + print "Node found, checking its fields..." + print "Checking id field... " + node["id"] + print "OK!" + print "Checking description field... " + node["description"] + print "OK!" + print "Checking configuration field... " + node["configuration"] + print "OK!" + if isinstance(node["configuration"], list) == False: + print "Checking if node configuration is a list..." + print "Node with id " + node["id"] + " does not have a configuration list!" + return False + for c in node["configuration"]: + print "Checking if node configuration element is a string or a dictionary..." + if (isinstance(c, str) == False and isinstance(c, dict) == False): + print "At least one element of node with id " + node["id"] + " has an invalid configuration (it is neither a string or a map)" + return False + except (KeyboardInterrupt, SystemExit): + raise + except: + print "One or more required fields are missing!" + return False + print filename + " validated successfully!" + return True + +def check_routing_integrity(filename): + print "Checking input file..." + try: + routing = convert_unicode_to_ascii(parse_json_file(filename)) + print "File correctly parsed" + if isinstance(routing["routing_table"], list) == False: + print "Child of routing_table is not a list!" + return False + for node in routing["routing_table"]: + if isinstance(node, dict) == False: + print "Child of routing_table is not a map!" + return False + for n, rt in node.items(): + if isinstance(rt, list) == False: + print "Routing table of element " + n + " is not a list!" + return False + for entry in rt: + if isinstance(entry, dict) == False: + print "Invalid entry for node " + n + " (not a map)!" + return False + except (KeyboardInterrupt, SystemExit): + raise + except: + print "One or more required fields are missing!" + return False + return True + +#prints every node for each input chain +def print_chains(chains): + for chain in chains["chains"]: + print "CHAIN #" + str(chain["id"]) + for node in chain["nodes"]: + print "Name: " + str(node["name"]) + print "Functional type: " + str(node["functional_type"]) + print "Address: " + str(node["address"]) + print "-----------------------------------" + print "" + +#prints every node's configuration +def print_configuration(configuration): + print "NODES CONFIGURATION" + for node in configuration["nodes"]: + print "Name: " + str(node["id"]) + print "Description: " + str(node["description"]) + print "Configuration: " + pprint(node["configuration"]) + print "-----------------------------------" + print "" + +#print every node's routing table +def print_routing_table(routing): + print "ROUTING" + for table in routing["routing_table"]: + for node,rt in table.items(): + print "Name: " + str(node) + pprint(rt) + print "-----------------------------------" + print "" + +#returns a list of tuple [(k1, v1), (k2, v2)] from a list of maps like [{k1 : v1},{k2 : v2}] +def formatted_list_from_list_of_maps(maps): + l = [] + for map in maps: + if isinstance(map, dict): + for k, v in map.items(): + #l.append("(ctx." + str(k) + ", ctx." + str(v) + ")") + l.append(str(k)) + l.append(str(v)) + else: + #l.append("ctx." + map) + l.append(map) + return l + +def list_directories(dir): + #output = subprocess.call(["ls", "-d", "*/"]) + output = subprocess.call(["find", dir, "-type", "d"]) + + #TREE VERSION + #find = subprocess.Popen(["find", ".", "-type", "d"], stdout=subprocess.PIPE) + #output = subprocess.check_output(["sed", "-e", "s/[^-][^\/]*\// |/g", "-e", "s/|\([^ ]\)/|-\1/"], stdin=find.stdout) + #find.wait() + +# ps = subprocess.Popen(('ps', '-A'), stdout=subprocess.PIPE) +# output = subprocess.check_output(('grep', 'process_name'), stdin=ps.stdout) +# ps.wait() + return output + +def list_files(dir): + output = subprocess.call(["find", dir, "-type", "f"]) + return output + +def search_node_in_chains(n): + found = [] + for chain in chains["chains"]: + for node in chain["nodes"]: + if node["name"] == n: + found.append(node) + return found
\ No newline at end of file diff --git a/verigraph/src/main/java/it/polito/escape/verify/client/Neo4jManagerClient.java b/verigraph/src/main/java/it/polito/escape/verify/client/Neo4jManagerClient.java new file mode 100644 index 0000000..044c136 --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/client/Neo4jManagerClient.java @@ -0,0 +1,339 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.client; + +import java.io.StringWriter; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import javax.ws.rs.ProcessingException; +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; +import javax.xml.stream.FactoryConfigurationError; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; + +import it.polito.escape.verify.deserializer.PathsMessageBodyReader; +import it.polito.escape.verify.model.Entry; +import it.polito.nffg.neo4j.jaxb.ActionEnumType; +import it.polito.nffg.neo4j.jaxb.ActionType; +import it.polito.nffg.neo4j.jaxb.ActionsType; +import it.polito.nffg.neo4j.jaxb.CiType; +import it.polito.nffg.neo4j.jaxb.CiType.Attributes; +import it.polito.nffg.neo4j.jaxb.CiType.Attributes.Attribute; +import it.polito.nffg.neo4j.jaxb.CpType; +import it.polito.nffg.neo4j.jaxb.CpointsType; +import it.polito.nffg.neo4j.jaxb.CtrlInterfacesType; +import it.polito.nffg.neo4j.jaxb.EpCpType; +import it.polito.nffg.neo4j.jaxb.EpType; +import it.polito.nffg.neo4j.jaxb.EpType.Flowspace; +import it.polito.nffg.neo4j.jaxb.EpointsType; +import it.polito.nffg.neo4j.jaxb.EpsCpsType; +import it.polito.nffg.neo4j.jaxb.FlowrulesType; +import it.polito.nffg.neo4j.jaxb.FlowrulesType.Flowspace.Tcp; +import it.polito.nffg.neo4j.jaxb.MonParamsType; +import it.polito.nffg.neo4j.jaxb.MonParamsType.Parameter; +import it.polito.nffg.neo4j.jaxb.NeType; +import it.polito.nffg.neo4j.jaxb.NelementsType; +import it.polito.nffg.neo4j.jaxb.NfType; +import it.polito.nffg.neo4j.jaxb.Nffg; +import it.polito.nffg.neo4j.jaxb.NfunctionsType; +import it.polito.nffg.neo4j.jaxb.ObjectFactory; +import it.polito.nffg.neo4j.jaxb.Paths; +import it.polito.nffg.neo4j.jaxb.PortDirEnumType; +import it.polito.nffg.neo4j.jaxb.PortType; +import it.polito.nffg.neo4j.jaxb.SpecType; +import it.polito.nffg.neo4j.jaxb.SpecType.Cpu; +import it.polito.nffg.neo4j.jaxb.SpecType.Deployment; +import it.polito.nffg.neo4j.jaxb.SpecType.Image; +import it.polito.nffg.neo4j.jaxb.SpecType.Memory; +import it.polito.nffg.neo4j.jaxb.SpecType.Storage; + +public class Neo4jManagerClient { + + private JAXBContext jc; + + private String address; + + private Nffg nffg; + + private List<String> endpoints = new LinkedList<String>(); + + private List<String> firewalls = new LinkedList<String>(); + + private Map<String, List<Entry>> routingTable = new HashMap<String, List<Entry>>(); + + private String source; + + private String destination; + + private String xmlString; + + private WebTarget baseTarget; + + public Neo4jManagerClient() { + + } + + public Neo4jManagerClient( String address, String source, String destination, List<String> endpoints, + List<String> firewalls, Map<String, List<Entry>> routingTable) { + this.address = address; + this.source = source; + this.destination = destination; + this.endpoints = endpoints; + this.firewalls = firewalls; + this.routingTable = routingTable; + + Client client = ClientBuilder.newBuilder().register(PathsMessageBodyReader.class).build(); + + this.baseTarget = client.target(this.address); + } + + public Paths getPaths() throws Exception { + try { + this.generateCustomXml(); + } + catch (JAXBException e) { + throw (e); + } + + WebTarget graphsTarget = baseTarget.path("graphs"); + WebTarget pathSourceDestination = graphsTarget.path("{graphId}/paths"); + WebTarget deleteNffg = graphsTarget.path("{graphId}"); + + Response deleteNffgResponse = deleteNffg.resolveTemplate("graphId", "1").request().delete(); + if (deleteNffgResponse.getStatus() != javax.ws.rs.core.Response.Status.NO_CONTENT.getStatusCode() + && deleteNffgResponse.getStatus() != javax.ws.rs.core.Response.Status.NOT_FOUND.getStatusCode()) { + throw new Exception("graph deletion failed"); + } + + Response createNffgResponse = graphsTarget .request("application/xml") + .post(Entity.entity(this.xmlString, "application/xml")); + if (createNffgResponse.getStatus() != javax.ws.rs.core.Response.Status.CREATED.getStatusCode()) { + throw new Exception("graph creation failed"); + } + + System.out.println("Getting paths from node \"" + this.source + "\" to node \"" + this.destination + "\"..."); + Response getPath = pathSourceDestination.resolveTemplate("graphId", "1") + .queryParam("src", this.source) + .queryParam("dst", this.destination) + .queryParam("dir", "outgoing") + .request(MediaType.APPLICATION_XML) + .get(); + + System.out.println("Paths from node \"" + this.source + "\" to node \"" + this.destination + "\":"); + + Paths paths = null; + try { + paths = getPath.readEntity(Paths.class); + } + catch (ProcessingException e) { + throw (e); + } + catch (IllegalStateException e) { + throw (e); + } + + return paths; + } + + private void generateCustomXml() throws JAXBException { + + jc = JAXBContext.newInstance("it.polito.nffg.neo4j.jaxb"); + + nffg = new Nffg(); + nffg.setId("nffg_1"); + + generateEndpoints(); + generateFirewalls(); + generateConnections(); + + MonParamsType monitoring_parameters = new MonParamsType(); + nffg.setMonitoringParameters(monitoring_parameters); + + JAXBElement<Nffg> root = (new ObjectFactory()).createNffg(nffg); + + Marshaller m; + try { + m = jc.createMarshaller(); + m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); + + StringWriter stringWriter = new StringWriter(); + try { + XMLStreamWriter xmlStreamWriter = XMLOutputFactory.newInstance().createXMLStreamWriter(stringWriter); + m.marshal(root, xmlStreamWriter); + xmlString = stringWriter.getBuffer().toString(); + } + catch (XMLStreamException e) { + e.printStackTrace(); + } + catch (FactoryConfigurationError e) { + + e.printStackTrace(); + } + // m.marshal( root, new File("nffg.xml") ); + System.out.println(xmlString); + + } + catch (JAXBException e) { + throw (e); + } + } + + private void generateConnections() { + NelementsType network_elements = new NelementsType(); + NeType network_element = new NeType(); + network_element.setId("ne_1"); + network_element.setType("BiSBiS"); + EpsCpsType ep_cps = new EpsCpsType(); + + for (String node : routingTable.keySet()) { + EpCpType ep_cp = new EpCpType(); + ep_cp.setIdRef(node); + FlowrulesType flowrules = new FlowrulesType(); + it.polito.nffg.neo4j.jaxb.FlowrulesType.Flowspace flowspace = + new it.polito.nffg.neo4j.jaxb.FlowrulesType.Flowspace(); + flowrules.setFlowspace(flowspace); + ActionsType actions = new ActionsType(); + for (Entry e : routingTable.get(node)) { + ActionType action = new ActionType(); + action.setType(ActionEnumType.fromValue(e.getDirection())); + action.setPort(e.getDestination()); + actions.getAction().add(action); + } + flowrules.setActions(actions); + + ep_cp.getFlowrules().add(flowrules); + ep_cps.getEpCp().add(ep_cp); + } + network_element.setEpsCps(ep_cps); + + MonParamsType monitoring_parameters = new MonParamsType(); + Parameter parameter = new Parameter(); + parameter.getValue().add("Bandwith ep_1 cp_1 100mbit"); + monitoring_parameters.getParameter().add(parameter); + Parameter parameter2 = new Parameter(); + parameter2.getValue().add("Delay ep_1 cp_1 50ms"); + monitoring_parameters.getParameter().add(parameter2); + + network_element.setMonitoringParameters(monitoring_parameters); + + network_elements.getNetworkElement().add(network_element); + + nffg.setNetworkElements(network_elements); + + } + + private void generateFirewalls() { + NfunctionsType network_functions = new NfunctionsType(); + + for (String firewall : firewalls) { + NfType nf = new NfType(); + nf.setId(firewall); + nf.setFunctionalType("firewall"); + + SpecType specification = new SpecType(); + Deployment deployment = new Deployment(); + deployment.setType("PolitoFirewall"); + Image image = new Image(); + image.setUri("http://www.polito.it"); + Cpu cpu = new Cpu(); + cpu.setNumCores((short) (7)); + Memory memory = new Memory(); + memory.setSize("10MiB"); + Storage storage = new Storage(); + storage.setSize("100MiB"); + specification.setDeployment(deployment); + specification.setImage(image); + specification.setCpu(cpu); + specification.setMemory(memory); + specification.setStorage(storage); + + CpointsType connection_points = new CpointsType(); + CpType connection_point = new CpType(); + connection_point.setId(firewall + "_in"); + PortType port = new PortType(); + port.setId(79); + port.setDirection(PortDirEnumType.IN); + port.setType("GbE"); + connection_point.setPort(port); + connection_points.getConnectionPoint().add(connection_point); + + CpType connection_point2 = new CpType(); + connection_point2.setId(firewall + "_out"); + PortType port2 = new PortType(); + port2.setId(77); + port2.setDirection(PortDirEnumType.OUT); + port2.setType("10GbE"); + connection_point2.setPort(port2); + + connection_points.getConnectionPoint().add(connection_point2); + + CtrlInterfacesType control_interfaces = new CtrlInterfacesType(); + CiType control_interface = new CiType(); + control_interface.setId(firewall + "_ci"); + + Attributes attributes = new Attributes(); + Attribute attribute = new Attribute(); + attribute.setValue("tcp://127.0.0.1:5555"); + attributes.getAttribute().add(attribute); + Attribute attribute2 = new Attribute(); + attribute2.setValue("Netconf"); + attributes.getAttribute().add(attribute2); + control_interface.setAttributes(attributes); + + control_interfaces.getControlInterface().add(control_interface); + + MonParamsType monitoring_parameters = new MonParamsType(); + Parameter parameter = new Parameter(); + parameter.getValue().add("Measure script"); + monitoring_parameters.getParameter().add(parameter); + + nf.setSpecification(specification); + nf.setConnectionPoints(connection_points); + nf.setControlInterfaces(control_interfaces); + nf.setMonitoringParameters(monitoring_parameters); + + network_functions.getNetworkFunction().add(nf); + + } + nffg.setNetworkFunctions(network_functions); + + } + + private void generateEndpoints() { + EpointsType eps = new EpointsType(); + + for (String e : endpoints) { + EpType endpoint = new EpType(); + endpoint.setId(e); + Flowspace flowspace = new Flowspace(); + flowspace.setIngPhysPort("10"); + Tcp tcp = new Tcp(); + tcp.setSrc(80); + flowspace.setTcp(tcp); + endpoint.setFlowspace(flowspace); + eps.getEndpoint().add(endpoint); + } + nffg.setEndpoints(eps); + } + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/client/VerifyClient.java b/verigraph/src/main/java/it/polito/escape/verify/client/VerifyClient.java new file mode 100644 index 0000000..1997553 --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/client/VerifyClient.java @@ -0,0 +1,444 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.client; + +import java.io.File; +import java.io.FileReader; +import java.io.FilenameFilter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.ws.rs.ProcessingException; +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.ResponseProcessingException; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import it.polito.escape.verify.model.ErrorMessage; +import it.polito.escape.verify.model.Graph; +import it.polito.escape.verify.model.Neighbour; +import it.polito.escape.verify.model.Node; +import it.polito.escape.verify.model.Verification; + +public class VerifyClient { + + private WebTarget baseTarget; + + private WebTarget graphsTarget; + + private WebTarget graphTarget; + + private WebTarget nodesTarget; + + private WebTarget nodeTarget; + + private WebTarget neighboursTarget; + + private WebTarget neighbourTarget; + + private WebTarget reachabilityTarget; + + private WebTarget isolationTarget; + + private WebTarget traversalTarget; + + public VerifyClient(String address) { + Client client = ClientBuilder.newClient(); + + this.baseTarget = client.target(address); + this.graphsTarget = baseTarget.path("graphs"); + this.graphTarget = graphsTarget.path("/{graphId}"); + this.nodesTarget = graphTarget.path("/nodes"); + this.nodeTarget = nodesTarget.path("//{nodeId}"); + this.neighboursTarget = nodeTarget.path("/neighbours"); + this.neighbourTarget = neighboursTarget.path("/{neighbourId}"); + this.reachabilityTarget = graphTarget.path("/policy"); + this.isolationTarget = graphTarget.path("/policy"); + this.traversalTarget = graphTarget.path("/policy"); + } + + public void checkResponse(Response response) throws VerifyClientException { + int status = response.getStatus(); + + // 400 + if (status == Response.Status.BAD_REQUEST.getStatusCode()) { + try { + // String responseString = response.readEntity(String.class); + // System.out.println(responseString); + ErrorMessage errorMessage = response.readEntity(ErrorMessage.class); + String message = errorMessage.getErrorMessage(); + throw new VerifyClientException("Bad request: " + message); + } + catch (ProcessingException e) { + throw new VerifyClientException("the content of the message cannot be mapped to an entity of the 'ErrorMessage': " + + e.getMessage()); + } + catch (IllegalStateException e) { + throw new VerifyClientException("the entity is not backed by an input stream or the original entity input stream has already been consumed without buffering the entity data prior consuming: " + + e.getMessage()); + } + } + // 403 + if (status == Response.Status.FORBIDDEN.getStatusCode()) { + try { + ErrorMessage errorMessage = response.readEntity(ErrorMessage.class); + String message = errorMessage.getErrorMessage(); + throw new VerifyClientException("Forbidden: " + message); + } + catch (ProcessingException e) { + throw new VerifyClientException("the content of the message cannot be mapped to an entity of the 'ErrorMessage': " + + e.getMessage()); + } + catch (IllegalStateException e) { + throw new VerifyClientException("the entity is not backed by an input stream or the original entity input stream has already been consumed without buffering the entity data prior consuming: " + + e.getMessage()); + } + } + // 404 + if (status == Response.Status.NOT_FOUND.getStatusCode()) { + try { + ErrorMessage errorMessage = response.readEntity(ErrorMessage.class); + String message = errorMessage.getErrorMessage(); + throw new VerifyClientException("Not found: " + message); + } + catch (ProcessingException e) { + throw new VerifyClientException("the content of the message cannot be mapped to an entity of the 'ErrorMessage': " + + e.getMessage()); + } + catch (IllegalStateException e) { + throw new VerifyClientException("the 'Response' entity is not backed by an input stream or the original entity input stream has already been consumed without buffering the entity data prior consuming: " + + e.getMessage()); + } + } + // 500 + if (status == Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()) { + try { + ErrorMessage errorMessage = response.readEntity(ErrorMessage.class); + String message = errorMessage.getErrorMessage(); + throw new VerifyClientException("Internal server error: " + message); + } + catch (ProcessingException e) { + throw new VerifyClientException("the content of the message cannot be mapped to an entity of the 'ErrorMessage': " + + e.getMessage()); + } + catch (IllegalStateException e) { + throw new VerifyClientException("the entity is not backed by an input stream or the original entity input stream has already been consumed without buffering the entity data prior consuming: " + + e.getMessage()); + } + } + if (status != Response.Status.ACCEPTED.getStatusCode() && status != Response.Status.CREATED.getStatusCode() + && status != Response.Status.NO_CONTENT.getStatusCode() && status != Response.Status.OK.getStatusCode()) + throw new VerifyClientException("Unknown error"); + } + + public Response createGraph(Graph graph) throws VerifyClientException, ResponseProcessingException, ProcessingException { + Response response = graphsTarget.request().post(Entity.json(graph)); + checkResponse(response); + return response; + } + + public Response createGraph(String graph) throws VerifyClientException, ResponseProcessingException, ProcessingException { + Response response = graphsTarget.request().post(Entity.entity(graph, "application/json")); + checkResponse(response); + return response; + } + + public Response retrieveGraph(long graphId) throws VerifyClientException, ProcessingException { + Response response = graphTarget.resolveTemplate("graphId", graphId).request().get(); + checkResponse(response); + return response; + } + + public Response updateGraph(long graphId, Graph graph) throws VerifyClientException, ResponseProcessingException, ProcessingException { + Response response = graphTarget.resolveTemplate("graphId", graphId).request().put(Entity.json(graph)); + checkResponse(response); + return response; + } + + public Response deleteGraph(long graphId) throws VerifyClientException, ResponseProcessingException, ProcessingException { + Response response = graphTarget.resolveTemplate("graphId", graphId).request().delete(); + checkResponse(response); + return response; + } + + public Response createNode(long graphId, Node node) throws VerifyClientException, ResponseProcessingException, ProcessingException { + Response response = nodesTarget.resolveTemplate("graphId", graphId).request().post(Entity.json(node)); + checkResponse(response); + return response; + } + + public Response retrieveNode(long graphId, long nodeId) throws VerifyClientException, ProcessingException { + Response response = nodeTarget .resolveTemplate("graphId", graphId) + .resolveTemplate("nodeId", nodeId) + .request() + .get(); + checkResponse(response); + return response; + } + + public Response updateNode(long graphId, long nodeId, Node node) throws VerifyClientException, ResponseProcessingException, ProcessingException { + Response response = nodeTarget .resolveTemplate("graphId", graphId) + .resolveTemplate("nodeId", nodeId) + .request() + .put(Entity.json(node)); + checkResponse(response); + return response; + } + + public Response deleteNode(long graphId, long nodeId) throws VerifyClientException, ResponseProcessingException, ProcessingException { + Response response = nodeTarget .resolveTemplate("graphId", graphId) + .resolveTemplate("nodeId", nodeId) + .request() + .delete(); + checkResponse(response); + return response; + } + + public Response createNeighbour(long graphId, long nodeId, Neighbour neighbour) throws VerifyClientException, ResponseProcessingException, ProcessingException { + Response response = neighboursTarget.resolveTemplate("graphId", graphId) + .resolveTemplate("nodeId", nodeId) + .request() + .post(Entity.json(neighbour)); + checkResponse(response); + return response; + } + + public Response retrieveNeighbour(long graphId, long nodeId, long neighbourId) throws VerifyClientException, ProcessingException { + Response response = neighbourTarget .resolveTemplate("graphId", graphId) + .resolveTemplate("nodeId", nodeId) + .resolveTemplate("neighbourId", neighbourId) + .request() + .get(); + checkResponse(response); + return response; + } + + public Response updateNeighbour(long graphId, long nodeId, long neighbourId, + Neighbour neighbour) throws VerifyClientException, ResponseProcessingException, ProcessingException { + Response response = neighbourTarget .resolveTemplate("graphId", graphId) + .resolveTemplate("nodeId", nodeId) + .resolveTemplate("neighbourId", neighbourId) + .request() + .put(Entity.json(neighbour)); + checkResponse(response); + return response; + } + + public Response deleteNeighbour(long graphId, long nodeId, long neighbourId) throws VerifyClientException, ResponseProcessingException, ProcessingException { + Response response = neighbourTarget .resolveTemplate("graphId", graphId) + .resolveTemplate("nodeId", nodeId) + .resolveTemplate("neighbourId", neighbourId) + .request() + .delete(); + checkResponse(response); + return response; + } + + public Verification getReachability(long graphId, String source, String destination) throws VerifyClientException, ProcessingException{ + Response response = reachabilityTarget.resolveTemplate("graphId", graphId) + .queryParam("source", source) + .queryParam("destination", destination) + .queryParam("type", "reachability") + .request() + .get(); + checkResponse(response); + try{ + Verification verification = response.readEntity(Verification.class); + return verification; + } + catch (ProcessingException e) { + throw new VerifyClientException("the content of the message cannot be mapped to an entity of the 'Verification': " + + e.getMessage()); + } + catch (IllegalStateException e) { + throw new VerifyClientException("the 'Verification' entity is not backed by an input stream or the original entity input stream has already been consumed without buffering the entity data prior consuming: " + + e.getMessage()); + } + } + + public Verification getIsolation(long graphId, String source, String destination, String middlebox) throws VerifyClientException, ProcessingException{ + Response response = isolationTarget.resolveTemplate("graphId", graphId) + .queryParam("source", source) + .queryParam("destination", destination) + .queryParam("middlebox", middlebox) + .queryParam("type", "isolation") + .request() + .get(); + checkResponse(response); + try{ + Verification verification = response.readEntity(Verification.class); + return verification; + } + catch (ProcessingException e) { + throw new VerifyClientException("the content of the message cannot be mapped to an entity of the 'Verification': " + + e.getMessage()); + } + catch (IllegalStateException e) { + throw new VerifyClientException("the 'Verification' entity is not backed by an input stream or the original entity input stream has already been consumed without buffering the entity data prior consuming: " + + e.getMessage()); + } + } + + public Verification getTraversal(long graphId, String source, String destination, String middlebox) throws VerifyClientException, ProcessingException{ + Response response = traversalTarget.resolveTemplate("graphId", graphId) + .queryParam("source", source) + .queryParam("destination", destination) + .queryParam("middlebox", middlebox) + .queryParam("type", "traversal") + .request() + .get(); + checkResponse(response); + try{ + Verification verification = response.readEntity(Verification.class); + return verification; + } + catch (ProcessingException e) { + throw new VerifyClientException("the content of the message cannot be mapped to an entity of the 'Verification': " + + e.getMessage()); + } + catch (IllegalStateException e) { + throw new VerifyClientException("the 'Verification' entity is not backed by an input stream or the original entity input stream has already been consumed without buffering the entity data prior consuming: " + + e.getMessage()); + } + } + + @SuppressWarnings("unused") + private static String deserializeString(File file) throws IOException { + int len; + char[] chr = new char[4096]; + final StringBuffer buffer = new StringBuffer(); + final FileReader reader = new FileReader(file); + try { + while ((len = reader.read(chr)) > 0) { + buffer.append(chr, 0, len); + } + } + finally { + reader.close(); + } + return buffer.toString(); + } + + public List<File> getFiles() { + List<File> filesList = new ArrayList<File>(); + + String folderString = System.getProperty("folder"); + File folder; + if (folderString == null) + folder = new File(System.getProperty("user.dir") + "/examples"); + else + folder = new File(folderString); + + System.out.println("Folder set to " + folder.getAbsolutePath()); + + File[] files = folder.listFiles(new FilenameFilter() { + + @Override + public boolean accept(File dir, String name) { + return name.endsWith(".json"); + } + }); + + for (File f : files) { + filesList.add(f); + } + + return filesList; + } + + public Graph addGraphFromFile(File file) throws JsonParseException, JsonMappingException, IOException, Exception { + System.out.println("Parsing graph of file '" + file.getAbsolutePath() + "'..."); + Graph graph = new ObjectMapper().readValue(file, Graph.class); + Response createGraphResponse = createGraph(graph); + if (createGraphResponse.getStatus() != Status.CREATED.getStatusCode()) { + throw new Exception("Creation of graph contained in file '" + file.getAbsolutePath() + "' returned status " + + createGraphResponse.getStatus()); + } + String responseString = createGraphResponse.readEntity(String.class); + System.out.println("Response:"); + System.out.println(responseString); + Graph response = new ObjectMapper().readValue(responseString, Graph.class); + printGraph(response); + return response; + } + + public void printGraph(Graph graph) { + System.out.println("Graph " + graph.getId()); + for (Node n : graph.getNodes().values()) { + System.out.println("\tNode " + n.getId()); + System.out.println("\tName " + n.getName()); + System.out.println("\tFunctional type: " + n.getFunctional_type()); + for (Neighbour neighbour : n.getNeighbours().values()) { + System.out.println("\t\tNeighbour " + neighbour.getId()); + System.out.println("\t\tName: " + neighbour.getName()); + } + } + } + + public Map<String, Graph> addGraphsFromFiles(List<File> files) throws JsonParseException, JsonMappingException, IOException, + Exception { + Map<String, Graph> graphs = new HashMap<String, Graph>(); + + for (File f : files) { + Graph graph = addGraphFromFile(f); + graphs.put(f.getName(), graph); + } + + for (Map.Entry<String, Graph> graph : graphs.entrySet()) { + System.out.println(graph.getKey() + " -> graph " + graph.getValue().getId()); + } + System.out.println("Graphs added"); + + return graphs; + } + + public static void main(String[] args) throws IOException, Exception { + System.out.println("Adding graphs"); + + VerifyClient verifyClient = new VerifyClient("http://localhost:8080/verify/api"); + + List<File> files = verifyClient.getFiles(); + Map<String, Graph> graphs = verifyClient.addGraphsFromFiles(files); + + for (Graph g : graphs.values()) { + Response response = verifyClient.retrieveGraph(g.getId()); + String responseString = response.readEntity(String.class); + + System.out.println("Response"); + System.out.println(responseString); + Graph graph = new ObjectMapper().readValue(responseString, Graph.class); + System.out.println("Read graph " + graph.getId()); + System.out.println(response.getStatus()); + } + + Graph graph = graphs.get("budapest_sat.json"); + System.out.println("graphId set to " + graph.getId()); + System.out.println("Getting reachability from 'user1' to 'websever' in 'budapest' graph (expecting SAT)..."); + Verification verification = verifyClient.getReachability(graph.getId(), "user1", "webserver"); + System.out.println(verification.getResult()); + graph = graphs.get("budapest_unsat.json"); + System.out.println("graphId set to " + graph.getId()); + System.out.println("Getting reachability from 'user1' to 'websever' in 'budapest' graph (expecting UNSAT)..."); + verification = verifyClient.getReachability(graph.getId(), "user1", "webserver"); + System.out.println(verification.getResult()); + + } + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/client/VerifyClientException.java b/verigraph/src/main/java/it/polito/escape/verify/client/VerifyClientException.java new file mode 100644 index 0000000..d91d31e --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/client/VerifyClientException.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.client; + + +public class VerifyClientException extends Exception{ + + /** + * + */ + private static final long serialVersionUID = 4794956747093682854L; + + public VerifyClientException(String message){ + super(message); + } + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/database/DatabaseClass.java b/verigraph/src/main/java/it/polito/escape/verify/database/DatabaseClass.java new file mode 100644 index 0000000..7837e51 --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/database/DatabaseClass.java @@ -0,0 +1,175 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.database; + +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import com.fasterxml.jackson.core.JsonGenerationException; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.type.TypeFactory; + +import it.polito.escape.verify.exception.InternalServerErrorException; +import it.polito.escape.verify.model.Graph; +import it.polito.escape.verify.model.Neighbour; +import it.polito.escape.verify.model.Node; +import it.polito.escape.verify.service.GraphService; + +public class DatabaseClass { + + private static final DatabaseClass instance = new DatabaseClass(); + + private static ConcurrentHashMap<Long, Graph> graphs; + + private static String persistenceFile; + + private static boolean enablePersistence; + + protected DatabaseClass() { + initialize(); + if (enablePersistence) + loadDatabase(); + } + + private void initialize() { + graphs = new ConcurrentHashMap<>(); + enablePersistence = false; + persistenceFile = System.getProperty("catalina.base") + "/webapps/verify/json/" + "database.json"; + } + + private void loadDatabase() { + ObjectMapper mapper = new ObjectMapper(); + + List<Graph> parsedGraphs = null; + try { + File databaseFile = new File(persistenceFile); + parsedGraphs = mapper.readValue(databaseFile, + TypeFactory.defaultInstance().constructCollectionType( List.class, + Graph.class)); + } + catch (JsonParseException e) { + System.out.println("Database not loaded due to a JsonParseException: " + e.getMessage()); + return; + } + catch (JsonMappingException e) { + System.out.println("Database not loaded due to a JsonMappingException: " + e.getMessage()); + return; + } + catch (IOException e) { + //retry changing path + persistenceFile = "src/main/webapp/json/" + "database.json"; + + try { + File databaseFile = new File(persistenceFile); + parsedGraphs = mapper.readValue(databaseFile, + TypeFactory.defaultInstance().constructCollectionType( List.class, + Graph.class)); + } catch (JsonParseException e1) { + System.out.println("Database not loaded due to a JsonParseException: " + e.getMessage()); + return; + } catch (JsonMappingException e1) { + System.out.println("Database not loaded due to a JsonMappingException: " + e.getMessage()); + return; + } catch (IOException e1) { + System.out.println("Database not loaded due to an IOException: " + e.getMessage()); + return; + } + } + + System.out.println("Loading database..."); + + for (Graph graph : parsedGraphs) { + + try { + GraphService.validateGraph(graph); + } + catch (Exception e) { + System.out.println("Invalid database file: at least one graph is invalid!"); + return; + } + + graph.setId(getNumberOfGraphs() + 1); + + for (Map.Entry<Long, Node> nodeEntry : graph.getNodes().entrySet()) { + nodeEntry.getValue().setId(nodeEntry.getKey()); + + for (Map.Entry<Long, Neighbour> neighbourEntry : nodeEntry.getValue().getNeighbours().entrySet()) { + neighbourEntry.getValue().setId(neighbourEntry.getKey()); + } + } + + graphs.put(graph.getId(), graph); + } + + System.out.println("Database loaded!"); + System.out.println(graphs.size() + " graphs added"); + } + + public static DatabaseClass getInstance() { + return instance; + } + + public ConcurrentHashMap<Long, Graph> getGraphs() { + return graphs; + } + + public synchronized int getNumberOfGraphs() { + return graphs.size(); + } + + public synchronized int getGraphNumberOfNodes(long graphId) { + Graph graph = graphs.get(graphId); + if (graph == null) + return 0; + Map<Long, Node> nodes = graph.getNodes(); + if (nodes == null) + return 0; + return nodes.size(); + } + + public static void persistDatabase() { + if (!enablePersistence) + return; + ObjectMapper mapper = new ObjectMapper(); + + try { + mapper.writeValue(new File(persistenceFile), graphs); + } + catch (JsonGenerationException e) { + throw new InternalServerErrorException("Unable to persist database due to a JsonGenerationException: " + + e.getMessage()); + } + catch (JsonMappingException e) { + throw new InternalServerErrorException("Unable to persist database due to a JsonMappingException: " + + e.getMessage()); + } + catch (IOException e) { + //retry changing path + persistenceFile = "src/main/webapp/json/" + "database.json"; + try { + mapper.writeValue(new File(persistenceFile), graphs); + } catch (JsonGenerationException e1) { + throw new InternalServerErrorException("Unable to persist database due to a JsonGenerationException: " + + e.getMessage()); + } catch (JsonMappingException e1) { + throw new InternalServerErrorException("Unable to persist database due to a JsonGenerationException: " + + e.getMessage()); + } catch (IOException e1) { + throw new InternalServerErrorException("Unable to persist database due to an IOException: " + + e.getMessage()); + } + } + } +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/deserializer/ConfigurationCustomDeserializer.java b/verigraph/src/main/java/it/polito/escape/verify/deserializer/ConfigurationCustomDeserializer.java new file mode 100644 index 0000000..5cdd084 --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/deserializer/ConfigurationCustomDeserializer.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.deserializer; + +import java.io.IOException; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; + +import it.polito.escape.verify.exception.InternalServerErrorException; +import it.polito.escape.verify.model.Configuration; + +public class ConfigurationCustomDeserializer extends JsonDeserializer<Configuration> { + + @Override + public Configuration deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, + JsonProcessingException { + try { + JsonNode root = jp.getCodec().readTree(jp); + + return new Configuration("", "", root); + } + catch (JsonProcessingException e) { + throw new InternalServerErrorException("Error parsing configuration: " + e.getMessage()); + } + catch (IOException e) { + throw new InternalServerErrorException("I/O error parsing configuration: " + e.getMessage()); + } + + } + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/deserializer/GraphCustomDeserializer.java b/verigraph/src/main/java/it/polito/escape/verify/deserializer/GraphCustomDeserializer.java new file mode 100644 index 0000000..f71c996 --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/deserializer/GraphCustomDeserializer.java @@ -0,0 +1,87 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.deserializer; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.type.TypeFactory; + +import it.polito.escape.verify.exception.BadRequestException; +import it.polito.escape.verify.exception.InternalServerErrorException; +import it.polito.escape.verify.model.Graph; +import it.polito.escape.verify.model.Node; + + +/** + * The Class GraphCustomDeserializer is a custom deserializer for a Graph object + */ +public class GraphCustomDeserializer extends JsonDeserializer<Graph>{ + + /* (non-Javadoc) + * @see com.fasterxml.jackson.databind.JsonDeserializer#deserialize(com.fasterxml.jackson.core.JsonParser, com.fasterxml.jackson.databind.DeserializationContext) + */ + @Override + public Graph deserialize(JsonParser jp, DeserializationContext context){ + JsonNode root = null; + try { + root = jp.getCodec().readTree(jp); + } + catch (JsonProcessingException e) { + throw new InternalServerErrorException("Error parsing a graph: " + e.getMessage()); + } + catch (IOException e) { + throw new InternalServerErrorException("I/O error parsing a graph: " + e.getMessage()); + } + + JsonNode nodesJson = root.get("nodes"); + + if(nodesJson == null) + throw new BadRequestException("Invalid graph"); + + List<Node> nodeList = null; + try { + nodeList = new ObjectMapper().readValue(nodesJson.toString(), TypeFactory.defaultInstance().constructCollectionType(List.class, Node.class)); + } + catch (JsonParseException e) { + throw new BadRequestException("Invalid content for a graph: " + e.getMessage()); + } + catch (JsonMappingException e) { + throw new BadRequestException("Invalid input json structure for a graph: " + e.getMessage()); + } + catch (IOException e) { + throw new InternalServerErrorException("I/O error parsing a graph: " + e.getMessage()); + } + + Graph graph = new Graph(); + if(root.get("id") != null){ + long graphId = root.get("id").asLong(); + graph.setId(graphId); + } + Map<Long, Node> nodes = graph.getNodes(); + + long numberOfNodes = 0; + for (Node node : nodeList){ + nodes.put(++numberOfNodes, node); + } + return graph; + + } + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/deserializer/NodeCustomDeserializer.java b/verigraph/src/main/java/it/polito/escape/verify/deserializer/NodeCustomDeserializer.java new file mode 100644 index 0000000..fb451db --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/deserializer/NodeCustomDeserializer.java @@ -0,0 +1,92 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.deserializer; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.type.TypeFactory; + +import it.polito.escape.verify.exception.BadRequestException; +import it.polito.escape.verify.exception.InternalServerErrorException; +import it.polito.escape.verify.model.Configuration; +import it.polito.escape.verify.model.Neighbour; +import it.polito.escape.verify.model.Node; + +public class NodeCustomDeserializer extends JsonDeserializer<Node> { + + @Override + public Node deserialize(JsonParser jp, DeserializationContext context) { + + try { + JsonNode root = jp.getCodec().readTree(jp); + JsonNode neighboursJson = root.get("neighbours"); + JsonNode configurationJson = root.get("configuration"); + + String nodeName = root.get("name").asText(); + String functionalType = root.get("functional_type").asText(); + + Node node = new Node(); + if(root.get("id") != null){ + long nodeId = root.get("id").asLong(); + node.setId(nodeId); + } + node.setName(nodeName); + node.setFunctional_type(functionalType); + + if (configurationJson == null) + node.setConfiguration(new Configuration(node.getName(), "", new ObjectMapper().createArrayNode())); + else { + Configuration conf = node.getConfiguration(); + conf.setId(node.getName()); + conf.setDescription(""); + conf.setConfiguration(configurationJson); + } + + try { + List<Neighbour> neighbourList = new ObjectMapper().readValue( neighboursJson.toString(), + TypeFactory .defaultInstance() + .constructCollectionType( List.class, + Neighbour.class)); + Map<Long, Neighbour> neighbours = node.getNeighbours(); + + long numberOfNeighbours = 0; + for (Neighbour neighbour : neighbourList) { + neighbours.put(++numberOfNeighbours, neighbour); + } + + return node; + } + catch (JsonParseException e) { + throw new BadRequestException("Invalid content for a node: " + e.getMessage()); + } + catch (JsonMappingException e) { + throw new BadRequestException("Invalid input json structure for a node: " + e.getMessage()); + } + } + catch (JsonProcessingException e) { + throw new InternalServerErrorException("Error parsing a node: " + e.getMessage()); + } + catch (IOException e) { + throw new InternalServerErrorException("I/O error parsing a node: " + e.getMessage()); + } + + } + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/deserializer/PathsMessageBodyReader.java b/verigraph/src/main/java/it/polito/escape/verify/deserializer/PathsMessageBodyReader.java new file mode 100644 index 0000000..3b54503 --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/deserializer/PathsMessageBodyReader.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.deserializer; + +import java.io.IOException; +import java.io.InputStream; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import javax.ws.rs.Consumes; +import javax.ws.rs.ProcessingException; +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.ext.MessageBodyReader; +import javax.ws.rs.ext.Provider; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; + +import it.polito.nffg.neo4j.jaxb.Paths; + +@Provider +@Consumes(MediaType.APPLICATION_XML) +public class PathsMessageBodyReader implements MessageBodyReader<Paths>{ + + @Override + public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { + return type == Paths.class; + } + + @Override + public Paths readFrom(Class<Paths> type, Type genericType, Annotation[] annotations, MediaType mediaType, + MultivaluedMap<String, String> httpHeaders, InputStream entityStream) + throws IOException, WebApplicationException { + try { + JAXBContext jaxbContext = JAXBContext.newInstance(Paths.class); + Paths paths = (Paths) jaxbContext.createUnmarshaller() + .unmarshal(entityStream); + return paths; + } catch (JAXBException jaxbException) { + throw new ProcessingException("Error deserializing a Paths object.", + jaxbException); + } + } + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/exception/BadRequestException.java b/verigraph/src/main/java/it/polito/escape/verify/exception/BadRequestException.java new file mode 100644 index 0000000..abbdbf0 --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/exception/BadRequestException.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.exception; + +public class BadRequestException extends RuntimeException { + + /** + * + */ + private static final long serialVersionUID = -548472179073745084L; + + public BadRequestException(String message) { + super(message); + } + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/exception/BadRequestExceptionMapper.java b/verigraph/src/main/java/it/polito/escape/verify/exception/BadRequestExceptionMapper.java new file mode 100644 index 0000000..8f1ba9c --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/exception/BadRequestExceptionMapper.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.exception; + +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.ext.ExceptionMapper; +import javax.ws.rs.ext.Provider; + +import it.polito.escape.verify.model.ErrorMessage; + +@Provider +public class BadRequestExceptionMapper implements ExceptionMapper<BadRequestException> { + + @Override + public Response toResponse(BadRequestException exception) { + ErrorMessage errorMessage = new ErrorMessage( exception.getMessage(), + 400, + "http://localhost:8080/verify/api-docs/"); + return Response.status(Status.BAD_REQUEST).entity(errorMessage).build(); + } + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/exception/DataNotFoundException.java b/verigraph/src/main/java/it/polito/escape/verify/exception/DataNotFoundException.java new file mode 100644 index 0000000..5cd1806 --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/exception/DataNotFoundException.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.exception; + +public class DataNotFoundException extends RuntimeException { + + /** + * + */ + private static final long serialVersionUID = -6012364193903183208L; + + public DataNotFoundException(String message) { + super(message); + } + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/exception/DataNotFoundExceptionMapper.java b/verigraph/src/main/java/it/polito/escape/verify/exception/DataNotFoundExceptionMapper.java new file mode 100644 index 0000000..62e3556 --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/exception/DataNotFoundExceptionMapper.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.exception; + +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.ext.ExceptionMapper; +import javax.ws.rs.ext.Provider; + +import it.polito.escape.verify.model.ErrorMessage; + +@Provider +public class DataNotFoundExceptionMapper implements ExceptionMapper<DataNotFoundException> { + + @Override + public Response toResponse(DataNotFoundException exception) { + ErrorMessage errorMessage = new ErrorMessage( exception.getMessage(), + 404, + "http://localhost:8080/verify/api-docs/"); + return Response.status(Status.NOT_FOUND).entity(errorMessage).build(); + } + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/exception/ForbiddenException.java b/verigraph/src/main/java/it/polito/escape/verify/exception/ForbiddenException.java new file mode 100644 index 0000000..dc79e97 --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/exception/ForbiddenException.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.exception; + +public class ForbiddenException extends RuntimeException { + + /** + * + */ + private static final long serialVersionUID = -4658914972167044321L; + + public ForbiddenException(String message) { + super(message); + } + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/exception/ForbiddenExceptionMapper.java b/verigraph/src/main/java/it/polito/escape/verify/exception/ForbiddenExceptionMapper.java new file mode 100644 index 0000000..d060b8b --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/exception/ForbiddenExceptionMapper.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.exception; + +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.ext.ExceptionMapper; +import javax.ws.rs.ext.Provider; + +import it.polito.escape.verify.model.ErrorMessage; + +@Provider +public class ForbiddenExceptionMapper implements ExceptionMapper<ForbiddenException> { + + @Override + public Response toResponse(ForbiddenException exception) { + ErrorMessage errorMessage = new ErrorMessage( exception.getMessage(), + 403, + "http://localhost:8080/verify/api-docs/"); + return Response.status(Status.FORBIDDEN).entity(errorMessage).build(); + } + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/exception/GenericExceptionMapper.java b/verigraph/src/main/java/it/polito/escape/verify/exception/GenericExceptionMapper.java new file mode 100644 index 0000000..96f7caa --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/exception/GenericExceptionMapper.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.exception; + +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.ext.ExceptionMapper; + +import it.polito.escape.verify.model.ErrorMessage; + +// @Provider +public class GenericExceptionMapper implements ExceptionMapper<Throwable> { + + @Override + public Response toResponse(Throwable exception) { + ErrorMessage errorMessage = new ErrorMessage("Generic exception: " + exception.getMessage(), + 500, + "http://localhost:8080/verify/api-docs/"); + return Response.status(Status.INTERNAL_SERVER_ERROR).entity(errorMessage).build(); + } + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/exception/InternalServerErrorException.java b/verigraph/src/main/java/it/polito/escape/verify/exception/InternalServerErrorException.java new file mode 100644 index 0000000..877edb5 --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/exception/InternalServerErrorException.java @@ -0,0 +1,23 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.exception; + +public class InternalServerErrorException extends RuntimeException { + + /** + * + */ + private static final long serialVersionUID = 156815197709461502L; + + public InternalServerErrorException(String message) { + super(message); + } + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/exception/InternalServerErrorExceptionMapper.java b/verigraph/src/main/java/it/polito/escape/verify/exception/InternalServerErrorExceptionMapper.java new file mode 100644 index 0000000..02b6765 --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/exception/InternalServerErrorExceptionMapper.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.exception; + +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.ext.ExceptionMapper; +import javax.ws.rs.ext.Provider; + +import it.polito.escape.verify.model.ErrorMessage; + +@Provider +public class InternalServerErrorExceptionMapper implements ExceptionMapper<InternalServerErrorException> { + + @Override + public Response toResponse(InternalServerErrorException exception) { + ErrorMessage errorMessage = new ErrorMessage( exception.getMessage(), + 500, + "http://localhost:8080/verify/api-docs/"); + return Response.status(Status.INTERNAL_SERVER_ERROR).entity(errorMessage).build(); + } + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/model/Configuration.java b/verigraph/src/main/java/it/polito/escape/verify/model/Configuration.java new file mode 100644 index 0000000..3498a10 --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/model/Configuration.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.model; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import it.polito.escape.verify.deserializer.ConfigurationCustomDeserializer; +import it.polito.escape.verify.serializer.CustomConfigurationSerializer; + +@XmlRootElement +@ApiModel("Configuration") +@JsonSerialize(using = CustomConfigurationSerializer.class) +@JsonDeserialize(using = ConfigurationCustomDeserializer.class) +public class Configuration { + + @ApiModelProperty(required = false, hidden = true) + @XmlTransient + private String id; + + @ApiModelProperty(required = false) + @XmlTransient + private String description = ""; + + @ApiModelProperty(required = true) + private JsonNode configuration; + + public Configuration() { + + } + + public Configuration(String id, String description, JsonNode configuration) { + this.id = id; + this.description = description; + this.configuration = configuration; + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public JsonNode getConfiguration() { + return configuration; + } + + public void setConfiguration(JsonNode configuration) { + this.configuration = configuration; + } + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/model/Entry.java b/verigraph/src/main/java/it/polito/escape/verify/model/Entry.java new file mode 100644 index 0000000..f2fdf14 --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/model/Entry.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.model; + +public class Entry { + private String direction; + private String destination; + + public Entry(String direction, String destination) { + this.direction = direction; + this.destination = destination; + } + + public String getDirection() { + return direction; + } + + public void setDirection(String direction) { + this.direction = direction; + } + + public String getDestination() { + return destination; + } + + public void setDestination(String destination) { + this.destination = destination; + } + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/model/ErrorMessage.java b/verigraph/src/main/java/it/polito/escape/verify/model/ErrorMessage.java new file mode 100644 index 0000000..e0e79d3 --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/model/ErrorMessage.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.model; + +import javax.xml.bind.annotation.XmlRootElement; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +@ApiModel(value = "Error") +@XmlRootElement +public class ErrorMessage { + + @ApiModelProperty(example = "Error message") + private String errorMessage; + @ApiModelProperty(allowableValues = "400,403,404,500", value = "HTTP error code", example = "[400,403,404,500]") + private int errorCode; + @ApiModelProperty(example = "http://localhost:8080/verify/api-docs/") + private String documentation; + + public ErrorMessage() { + + } + + public ErrorMessage(String errorMessage, int errorCode, String documentation) { + this.errorMessage = errorMessage; + this.errorCode = errorCode; + this.documentation = documentation; + } + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + public int getErrorCode() { + return errorCode; + } + + public void setErrorCode(int errorCode) { + this.errorCode = errorCode; + } + + public String getDocumentation() { + return documentation; + } + + public void setDocumentation(String documentation) { + this.documentation = documentation; + } + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/model/Graph.java b/verigraph/src/main/java/it/polito/escape/verify/model/Graph.java new file mode 100644 index 0000000..44a2273 --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/model/Graph.java @@ -0,0 +1,105 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.model; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import it.polito.escape.verify.deserializer.GraphCustomDeserializer; +import it.polito.escape.verify.serializer.CustomMapSerializer; + +@ApiModel(value = "Graph") +@XmlRootElement +@JsonDeserialize(using = GraphCustomDeserializer.class) +@JsonInclude(JsonInclude.Include.NON_EMPTY) +public class Graph { + + @ApiModelProperty(required = false, hidden = true) + @XmlTransient + private long id; + + @ApiModelProperty(name = "nodes", notes = "Nodes", dataType = "List[it.polito.escape.verify.model.Node]") + private Map<Long, Node> nodes = new HashMap<Long, Node>(); + + @ApiModelProperty(required = false, hidden = true) + @XmlTransient + private Set<Link> links = new HashSet<Link>(); + + public Graph() { + + } + + public Graph(long id) { + this.id = id; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + @JsonSerialize(using = CustomMapSerializer.class) + public Map<Long, Node> getNodes() { + return nodes; + } + + public void setNodes(Map<Long, Node> nodes) { + this.nodes = nodes; + } + + @XmlTransient + public Set<Link> getLinks() { + return links; + } + + public void setLinks(Set<Link> links) { + this.links = links; + } + + public void addLink(String url, String rel) { + Link link = new Link(); + link.setLink(url); + link.setRel(rel); + links.add(link); + } + + public Node searchNodeByName(String name) { + for (Node node : this.nodes.values()) { + if (node.getName().equals(name)) + return node; + } + return null; + } + + public int nodesWithName(String name) { + int occurrences = 0; + for (Node node : this.nodes.values()) { + if (node.getName().equals(name)) + occurrences++; + + } + return occurrences; + } + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/model/Link.java b/verigraph/src/main/java/it/polito/escape/verify/model/Link.java new file mode 100644 index 0000000..dc2b4c5 --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/model/Link.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.model; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +@ApiModel(value = "Link") +public class Link { + @ApiModelProperty(required = false, hidden = true) + private String link; + @ApiModelProperty(required = false, hidden = true) + private String rel; + + public String getLink() { + return link; + } + + public void setLink(String link) { + this.link = link; + } + + public String getRel() { + return rel; + } + + public void setRel(String rel) { + this.rel = rel; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((link == null) ? 0 : link.hashCode()); + result = prime * result + ((rel == null) ? 0 : rel.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Link other = (Link) obj; + if (link == null) { + if (other.link != null) + return false; + } + else if (!link.equals(other.link)) + return false; + if (rel == null) { + if (other.rel != null) + return false; + } + else if (!rel.equals(other.rel)) + return false; + return true; + } + +}
\ No newline at end of file diff --git a/verigraph/src/main/java/it/polito/escape/verify/model/Neighbour.java b/verigraph/src/main/java/it/polito/escape/verify/model/Neighbour.java new file mode 100644 index 0000000..4b1206c --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/model/Neighbour.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.model; + +import javax.xml.bind.annotation.XmlTransient; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +@ApiModel(value = "Neighbour") +public class Neighbour { + + @ApiModelProperty(required = false, hidden = true) + @XmlTransient + private long id; + + @ApiModelProperty( required = true, + example = "nat", + value = "The neighbour name must refer to an existing node of the same graph") + private String name; + + public Neighbour() { + + } + + public Neighbour(long id, String name) { + this.id = id; + this.name = name; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + else + return false; + } + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/model/Node.java b/verigraph/src/main/java/it/polito/escape/verify/model/Node.java new file mode 100644 index 0000000..9f667ce --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/model/Node.java @@ -0,0 +1,152 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.model; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlTransient; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import it.polito.escape.verify.deserializer.NodeCustomDeserializer; +import it.polito.escape.verify.serializer.CustomMapSerializer; + +@ApiModel(value = "Node") +@XmlRootElement +@JsonDeserialize(using = NodeCustomDeserializer.class) +@JsonInclude(JsonInclude.Include.NON_EMPTY) +public class Node { + + @ApiModelProperty(required = false, hidden = true) + @XmlTransient + private long id; + + @ApiModelProperty(required = true, example = "ep", value = "The name of the node can be any string") + private String name; + + @ApiModelProperty( required = true, + example = "endpoint", + value = "The functional types that are currently supported are: endpoint, firewall, nat, antispam, webclient, webserver, mailclient, mailserver") + private String functional_type; + + @ApiModelProperty(required = false, hidden = true) + @XmlTransient + private Configuration configuration = new Configuration(); + + @ApiModelProperty( name = "neighbours", + notes = "Neighbours", + dataType = "List[it.polito.escape.verify.model.Neighbour]") + private Map<Long, Neighbour> neighbours = new HashMap<Long, Neighbour>(); + + @ApiModelProperty(required = false, hidden = true) + @XmlTransient + private Set<Link> links = new HashSet<>(); + + public Node() { + + } + + public Node(long id, String name, String functional_type, Configuration configuration) { + this.id = id; + this.name = name; + this.functional_type = functional_type; + this.configuration = configuration; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getFunctional_type() { + return functional_type; + } + + public void setFunctional_type(String functional_type) { + this.functional_type = functional_type; + } + + // @XmlTransient + public Configuration getConfiguration() { + return configuration; + } + + public void setConfiguration(Configuration configuration) { + this.configuration = configuration; + } + + @JsonSerialize(using = CustomMapSerializer.class) + public Map<Long, Neighbour> getNeighbours() { + return neighbours; + } + + public void setNeighbours(Map<Long, Neighbour> neighbours) { + this.neighbours = neighbours; + } + + public long getId() { + return this.id; + } + + public void setId(long id) { + this.id = id; + } + + public Set<Link> getLinks() { + return links; + } + + public void setLinks(Set<Link> links) { + this.links = links; + } + + public void addLink(String url, String rel) { + Link link = new Link(); + link.setLink(url); + link.setRel(rel); + links.add(link); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + else + return false; + } + + public Neighbour searchNeighbourByName(String name) { + for (Neighbour neighbour : this.neighbours.values()) { + if (neighbour.getName().equals(name)) + return neighbour; + } + return null; + } + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/model/Test.java b/verigraph/src/main/java/it/polito/escape/verify/model/Test.java new file mode 100644 index 0000000..1127abc --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/model/Test.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.model; + +import java.util.ArrayList; +import java.util.List; + +public class Test { + private List<Node> nodes = new ArrayList<Node>(); + private String result; + + public Test() { + + } + + public Test(List<Node> paths, int result) { + switch (result) { + case 0: + this.result = "SAT"; + break; + case -1: + this.result = "UNSAT"; + break; + case -2: + this.result = "UNKNOWN"; + break; + default: + this.result = "UNKNWON"; + break; + } + this.nodes = paths; + } + + public Test(List<Node> paths, String result) { + this.nodes = paths; + this.result = result; + } + + public List<Node> getPath() { + return nodes; + } + + public void setPath(List<Node> paths) { + this.nodes = paths; + } + + public String getResult() { + return result; + } + + public void setResult(String result) { + this.result = result; + } + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/model/Verification.java b/verigraph/src/main/java/it/polito/escape/verify/model/Verification.java new file mode 100644 index 0000000..60b4ddb --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/model/Verification.java @@ -0,0 +1,69 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.model; + +import java.util.ArrayList; +import java.util.List; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +@ApiModel(value = "Policy verification") +public class Verification { + + @ApiModelProperty(example = "SAT | UNSAT | UNKNOWN") + private String result; + private String comment; + private List<Test> tests = new ArrayList<Test>(); + + public Verification() { + + } + + public Verification(String result) { + this.result = result; + } + + public Verification(String result, List<Test> tests, String comment){ + this.result = result; + this.tests = tests; + this.comment = comment; + } + + public Verification(String result, String comment){ + this.result = result; + this.comment = comment; + } + + public String getResult() { + return result; + } + + public void setResult(String result) { + this.result = result; + } + + public List<Test> getTests() { + return tests; + } + + public void setTests(List<Test> tests) { + this.tests = tests; + } + + public String getComment() { + return comment; + } + + public void setComment(String comment) { + this.comment = comment; + } + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/model/jaxb.properties b/verigraph/src/main/java/it/polito/escape/verify/model/jaxb.properties new file mode 100644 index 0000000..5837a4c --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/model/jaxb.properties @@ -0,0 +1 @@ +javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
\ No newline at end of file diff --git a/verigraph/src/main/java/it/polito/escape/verify/resources/GraphResource.java b/verigraph/src/main/java/it/polito/escape/verify/resources/GraphResource.java new file mode 100644 index 0000000..e610f1d --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/resources/GraphResource.java @@ -0,0 +1,167 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.resources; + +import java.net.URI; +import java.util.List; + +import javax.ws.rs.BeanParam; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import it.polito.escape.verify.model.ErrorMessage; +import it.polito.escape.verify.model.Graph; +import it.polito.escape.verify.model.Verification; +import it.polito.escape.verify.resources.beans.VerificationBean; +import it.polito.escape.verify.service.GraphService; +import it.polito.escape.verify.service.VerificationService; + +@Path("/graphs") +@Api(value = "/graphs", description = "Manage graphs") +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +public class GraphResource { + GraphService graphService = new GraphService(); + VerificationService verificationService = new VerificationService(); + + @GET + @ApiOperation( httpMethod = "GET", + value = "Returns all graphs", + notes = "Returns an array of graphs", + response = Graph.class, + responseContainer = "List") + @ApiResponses(value = { @ApiResponse( code = 200, + message = "All the graphs have been returned in the message body", + response = Graph.class, + responseContainer = "List"), + @ApiResponse(code = 500, message = "Internal server error", response = ErrorMessage.class)}) + public List<Graph> getGraphs() { + return graphService.getAllGraphs(); + } + + @POST + @ApiOperation( httpMethod = "POST", + value = "Creates a graph", + notes = "Creates a signle graph", + response = Response.class) + @ApiResponses(value = { @ApiResponse(code = 400, message = "Invalid graph supplied", response = ErrorMessage.class), + @ApiResponse(code = 500, message = "Internal server error", response = ErrorMessage.class), + @ApiResponse(code = 201, message = "Graph successfully created", response = Graph.class) }) + public Response addGraph( @ApiParam(value = "New graph object", required = true) Graph graph, + @Context UriInfo uriInfo) { + Graph newGraph = graphService.addGraph(graph); + String newId = String.valueOf(newGraph.getId()); + URI uri = uriInfo.getAbsolutePathBuilder().path(newId).build(); + return Response.created(uri).entity(newGraph).build(); + } + + @GET + @Path("/{graphId}") + @ApiOperation( httpMethod = "GET", + value = "Returns a graph", + notes = "Returns a signle graph", + response = Graph.class) + @ApiResponses(value = { @ApiResponse(code = 403, message = "Invalid graph id", response = ErrorMessage.class), + @ApiResponse(code = 404, message = "Graph not found", response = ErrorMessage.class), + @ApiResponse(code = 500, message = "Internal server error", response = ErrorMessage.class), + @ApiResponse( code = 200, + message = "The requested graph has been returned in the message body", + response = Graph.class) }) + public Graph getGraph( @ApiParam(value = "Graph id", required = true) @PathParam("graphId") long graphId, + @Context UriInfo uriInfo) { + Graph graph = graphService.getGraph(graphId); + graph.addLink(getUriForSelf(uriInfo, graph), "self"); + graph.addLink(getUriForNodes(uriInfo, graph), "nodes"); + return graph; + } + + @PUT + @Path("/{graphId}") + @ApiOperation(httpMethod = "PUT", value = "Edits a graph", notes = "Edits a single graph", response = Graph.class) + @ApiResponses(value = { @ApiResponse(code = 400, message = "Invalid graph object", response = ErrorMessage.class), + @ApiResponse(code = 403, message = "Invalid graph id", response = ErrorMessage.class), + @ApiResponse(code = 404, message = "Graph not found", response = ErrorMessage.class), + @ApiResponse(code = 500, message = "Internal server error", response = ErrorMessage.class), + @ApiResponse(code = 200, message = "Graph edited successfully", response = Graph.class) }) + public Graph updateGraph( @ApiParam(value = "Graph id", required = true) @PathParam("graphId") long id, + @ApiParam(value = "Updated graph object", required = true) Graph graph) { + graph.setId(id); + return graphService.updateGraph(graph); + } + + @DELETE + @Path("/{graphId}") + @ApiOperation(httpMethod = "DELETE", value = "Deletes a graph", notes = "Deletes a signle graph") + @ApiResponses(value = { @ApiResponse(code = 403, message = "Invalid graph id", response = ErrorMessage.class), + @ApiResponse(code = 500, message = "Internal server error", response = ErrorMessage.class), + @ApiResponse(code = 204, message = "Graph successfully deleted") }) + public void deleteGraph(@ApiParam(value = "Graph id", required = true) @PathParam("graphId") long id) { + graphService.removeGraph(id); + } + + @GET + @Path("/{graphId}/policy") + @ApiOperation( httpMethod = "GET", + value = "Verifies a given policy in a graph", + notes = "In order to verify a given policy (e.g. 'reachability') all nodes of the desired graph must have a valid configuration.") + @ApiResponses(value = { @ApiResponse( code = 403, + message = "Invalid graph id or invalid configuration for source and/or destination node", + response = ErrorMessage.class), + @ApiResponse( code = 404, + message = "Graph not found or source node not found or destination node not found or configuration for source and/or destination node not available", + response = ErrorMessage.class), + @ApiResponse(code = 500, message = "Internal server error", response = ErrorMessage.class),}) + public Verification verifyGraph(@ApiParam(value = "Graph id", required = true) @PathParam("graphId") long graphId, + @ApiParam( value = "'source' and 'destination' must refer to names of existing nodes in the same graph, 'type' refers to the required verification between the two (e.g. 'reachability')", + required = true) @BeanParam VerificationBean verificationBean) { + + return verificationService.verify(graphId, verificationBean); + } + + private String getUriForSelf(UriInfo uriInfo, Graph graph) { + String uri = uriInfo.getBaseUriBuilder() + .path(GraphResource.class) + .path(Long.toString(graph.getId())) + .build() + .toString(); + return uri; + } + + private String getUriForNodes(UriInfo uriInfo, Graph graph) { + String uri = uriInfo.getBaseUriBuilder() + .path(GraphResource.class) + .path(GraphResource.class, "getNodeResource") + // .path(NodeResource.class) + .resolveTemplate("graphId", graph.getId()) + .build() + .toString(); + return uri; + } + + @Path("/{graphId}/nodes") + public NodeResource getNodeResource() { + return new NodeResource(); + } +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/resources/NeighbourResource.java b/verigraph/src/main/java/it/polito/escape/verify/resources/NeighbourResource.java new file mode 100644 index 0000000..63376da --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/resources/NeighbourResource.java @@ -0,0 +1,141 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.resources; + +import java.net.URI; +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import it.polito.escape.verify.model.ErrorMessage; +import it.polito.escape.verify.model.Neighbour; +import it.polito.escape.verify.service.NeighbourService; + +//@Path("/") +@Api( hidden= true, value = "", description = "Manage neighbours" ) +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +public class NeighbourResource { + private NeighbourService neighboursService = new NeighbourService(); + + @GET + @ApiOperation( + httpMethod = "GET", + value = "Returns all neighbours of a given node belonging to a given graph", + notes = "Returns an array of neighbours of a given node belonging to a given graph", + response = Neighbour.class, + responseContainer = "List") + @ApiResponses(value = { @ApiResponse(code = 403, message = "Invalid graph and/or node id", response=ErrorMessage.class), + @ApiResponse(code = 404, message = "Graph and/or node not found", response=ErrorMessage.class), + @ApiResponse(code = 500, message = "Internal server error", response = ErrorMessage.class), + @ApiResponse(code = 200, message = "All the neighbours have been returned in the message body", response=Neighbour.class, responseContainer="List")}) + public List<Neighbour> getAllNeighbours( + @ApiParam(value = "Graph id", required = true) @PathParam("graphId") long graphId, + @ApiParam(value = "Node id", required = true) @PathParam("nodeId") long nodeId){ + return neighboursService.getAllNeighbours(graphId, nodeId); + } + + @POST + @ApiOperation( + httpMethod = "POST", + value = "Adds a neighbour to a given node belonging to a given graph", + notes = "Adds single neighbour to a given node belonging to a given graph", + response = Neighbour.class) + @ApiResponses(value = { @ApiResponse(code = 403, message = "Invalid graph and/or node id", response=ErrorMessage.class), + @ApiResponse(code = 404, message = "Graph and/or node not found", response=ErrorMessage.class), + @ApiResponse(code = 400, message = "Invalid neighbour object", response=ErrorMessage.class), + @ApiResponse(code = 500, message = "Internal server error", response = ErrorMessage.class), + @ApiResponse(code = 201, message = "Neighbour successfully created", response=Neighbour.class)}) + public Response addNeighbour( + @ApiParam(value = "Graph id", required = true) @PathParam("graphId") long graphId, + @ApiParam(value = "Node id", required = true) @PathParam("nodeId") long nodeId, + @ApiParam(value = "New neighbour object. Neighbour name must refer to the name of an existing node of the same graph", required = true) Neighbour neighbour, + @Context UriInfo uriInfo){ + Neighbour newNeighbour = neighboursService.addNeighbour(graphId, nodeId, neighbour); + String newId = String.valueOf(newNeighbour.getId()); + URI uri = uriInfo.getAbsolutePathBuilder().path(newId).build(); + return Response.created(uri) + .entity(newNeighbour) + .build(); + } + + @PUT + @Path("{neighbourId}") + @ApiOperation( + httpMethod = "PUT", + value = "Edits a neighbour of a given node belonging to a given graph", + notes = "Edits a single neighbour of a given node belonging to a given graph", + response = Neighbour.class) + @ApiResponses(value = { @ApiResponse(code = 403, message = "Invalid graph and/or node and/or neighbour id", response=ErrorMessage.class), + @ApiResponse(code = 404, message = "Graph and/or node and /or neighbour not found", response=ErrorMessage.class), + @ApiResponse(code = 400, message = "Invalid neighbour object", response=ErrorMessage.class), + @ApiResponse(code = 500, message = "Internal server error", response = ErrorMessage.class), + @ApiResponse(code = 200, message = "Neighbour edited successfully", response=Neighbour.class)}) + public Neighbour updateNeighbour( + @ApiParam(value = "Graph id", required = true) @PathParam("graphId") long graphId, + @ApiParam(value = "Node id", required = true) @PathParam("nodeId") long nodeId, + @ApiParam(value = "Neighbour id", required = true) @PathParam("neighbourId") long neighbourId, + @ApiParam(value = "Updated neighbour object. Neighbour name must refer to the name of an existing node of the same graph", required = true) Neighbour neighbour){ + neighbour.setId(neighbourId); + return neighboursService.updateNeighbour(graphId, nodeId, neighbour); + } + + @DELETE + @Path("{neighbourId}") + @ApiOperation( + httpMethod = "DELETE", + value = "Removes a neighbour from a given node belonging to a given graph", + notes = "Deletes a single neighbour of a given node belonging to a given graph", + response = Neighbour.class) + @ApiResponses(value = { @ApiResponse(code = 403, message = "Invalid graph and/or node and/or neighbour id", response=ErrorMessage.class), + @ApiResponse(code = 404, message = "Graph and/or node not found", response=ErrorMessage.class), + @ApiResponse(code = 500, message = "Internal server error", response = ErrorMessage.class), + @ApiResponse(code = 204, message = "Node successfully deleted")}) + public void deleteNeighbour( + @ApiParam(value = "Graph id", required = true) @PathParam("graphId") long graphId, + @ApiParam(value = "Node id", required = true) @PathParam("nodeId") long nodeId, + @ApiParam(value = "Neighbour id", required = true) @PathParam("neighbourId") long neighbourId){ + neighboursService.removeNeighbour(graphId, nodeId, neighbourId); + } + + @GET + @Path("{neighbourId}") + @ApiOperation( + httpMethod = "GET", + value = "Returns a neighbour of a given node belonging to a given graph", + notes = "Returns a single neighbour of a given node belonging to a given graph", + response = Neighbour.class) + @ApiResponses(value = { @ApiResponse(code = 403, message = "Invalid graph and/or node and/or neighbour id", response=ErrorMessage.class), + @ApiResponse(code = 404, message = "Graph and/or node and /or neighbour not found", response=ErrorMessage.class), + @ApiResponse(code = 500, message = "Internal server error", response = ErrorMessage.class), + @ApiResponse(code = 200, message = "The requested neighbour has been returned in the message body", response=Neighbour.class)}) + public Neighbour getNeighbour( + @ApiParam(value = "Graph id", required = true) @PathParam("graphId") long graphId, + @ApiParam(value = "Node id", required = true) @PathParam("nodeId") long nodeId, + @ApiParam(value = "Neighbour id", required = true) @PathParam("neighbourId") long neighbourId){ + return neighboursService.getNeighbour(graphId, nodeId, neighbourId); + } +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/resources/NodeResource.java b/verigraph/src/main/java/it/polito/escape/verify/resources/NodeResource.java new file mode 100644 index 0000000..58d4064 --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/resources/NodeResource.java @@ -0,0 +1,230 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.resources; + +import java.net.URI; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import it.polito.escape.verify.exception.BadRequestException; +import it.polito.escape.verify.exception.ForbiddenException; +import it.polito.escape.verify.model.Configuration; +import it.polito.escape.verify.model.ErrorMessage; +import it.polito.escape.verify.model.Graph; +import it.polito.escape.verify.model.Neighbour; +import it.polito.escape.verify.model.Node; +import it.polito.escape.verify.service.GraphService; +import it.polito.escape.verify.service.NodeService; + +@Api( hidden= true, value = "", description = "Manage nodes" ) +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +public class NodeResource { + + NodeService nodeService = new NodeService(); + + + @GET + @ApiOperation( + httpMethod = "GET", + value = "Returns all nodes of a given graph", + notes = "Returns an array of nodes belonging to a given graph", + response = Node.class, + responseContainer = "List") + @ApiResponses(value = { @ApiResponse(code = 403, message = "Invalid graph id", response = ErrorMessage.class), + @ApiResponse(code = 404, message = "Graph not found", response = ErrorMessage.class), + @ApiResponse(code = 500, message = "Internal server error", response = ErrorMessage.class), + @ApiResponse(code = 200, message = "All the nodes have been returned in the message body", response = Node.class, responseContainer = "List") }) + public List<Node> getNodes(@ApiParam(value = "Graph id", required = true) @PathParam("graphId") long graphId){ + return nodeService.getAllNodes(graphId); + } + + @POST + @ApiOperation( + httpMethod = "POST", + value = "Creates a node in a given graph", + notes = "Creates a single node for a given graph", + response = Response.class) + @ApiResponses(value = { @ApiResponse(code = 400, message = "Invalid node supplied", response = ErrorMessage.class), + @ApiResponse(code = 403, message = "Invalid graph id", response = ErrorMessage.class), + @ApiResponse(code = 404, message = "Graph not found", response = ErrorMessage.class), + @ApiResponse(code = 500, message = "Internal server error", response = ErrorMessage.class), + @ApiResponse(code = 201, message = "Node successfully created", response = Node.class)}) + public Response addNode( + @ApiParam(value = "Graph id", required = true) @PathParam("graphId") long graphId, + @ApiParam(value = "New node object", required = true) Node node, + @Context UriInfo uriInfo) { + Node newNode = nodeService.addNode(graphId, node); + String newId = String.valueOf(newNode.getId()); + URI uri = uriInfo.getAbsolutePathBuilder().path(newId).build(); + return Response.created(uri) + .entity(newNode) + .build(); + } + + @GET + @Path("{nodeId}") + @ApiOperation( + httpMethod = "GET", + value = "Returns a node of a given graph", + notes = "Returns a single node of a given graph", + response = Node.class) + @ApiResponses(value = { @ApiResponse(code = 403, message = "Invalid graph and/or node id", response = ErrorMessage.class), + @ApiResponse(code = 404, message = "Graph and/or node not found", response = ErrorMessage.class), + @ApiResponse(code = 500, message = "Internal server error", response = ErrorMessage.class), + @ApiResponse(code = 200, message = "The requested node has been returned in the message body", response = Node.class)}) + public Node getNode( + @ApiParam(value = "Graph id", required = true) @PathParam("graphId") long graphId, + @ApiParam(value = "Node id", required = true) @PathParam("nodeId") long nodeId, + @Context UriInfo uriInfo){ + Node node = nodeService.getNode(graphId, nodeId); + node.addLink(getUriForSelf(uriInfo, graphId, node), "self"); + node.addLink(getUriForNeighbours(uriInfo, graphId, node), "neighbours"); + return node; + } + + @PUT + @Path("{nodeId}/configuration") + @ApiOperation( + httpMethod = "PUT", + value = "Adds/edits a configuration to a node of a given graph", + notes = "Configures a node. Once all the nodes of a graph have been configured a given policy can be verified for the graph (e.g. 'reachability' between two nodes).") + @ApiResponses(value = { @ApiResponse(code = 403, message = "Invalid graph and/or node id", response = ErrorMessage.class), + @ApiResponse(code = 404, message = "Graph and/or node not found", response = ErrorMessage.class), + @ApiResponse(code = 500, message = "Internal server error", response = ErrorMessage.class), + @ApiResponse(code = 200, message = "Configuration updated for the requested node")}) + public void addNodeConfiguration( + @ApiParam(value = "Graph id", required = true) @PathParam("graphId") long graphId, + @ApiParam(value = "Node id", required = true) @PathParam("nodeId") long nodeId, + @ApiParam(value = "Node configuration", required = true) Configuration nodeConfiguration, + @Context UriInfo uriInfo){ + if (graphId <= 0) { + throw new ForbiddenException("Illegal graph id: " + graphId); + } + if (nodeId <= 0) { + throw new ForbiddenException("Illegal node id: " + nodeId); + } + Graph graph = new GraphService().getGraph(graphId); + if (graph == null){ + throw new BadRequestException("Graph with id " + graphId + " not found"); + } + Node node = nodeService.getNode(graphId, nodeId); + if (node == null){ + throw new BadRequestException("Node with id " + nodeId + " not found in graph with id " + graphId); + } + Node nodeCopy = new Node(); + nodeCopy.setId(node.getId()); + nodeCopy.setName(node.getName()); + nodeCopy.setFunctional_type(node.getFunctional_type()); + Map<Long,Neighbour> nodes = new HashMap<Long,Neighbour>(); + nodes.putAll(node.getNeighbours()); + nodeCopy.setNeighbours(nodes); + nodeConfiguration.setId(nodeCopy.getName()); + nodeCopy.setConfiguration(nodeConfiguration); + + Graph graphCopy = new Graph(); + graphCopy.setId(graph.getId()); + graphCopy.setNodes(new HashMap<Long, Node>(graph.getNodes())); + graphCopy.getNodes().remove(node.getId()); + + NodeService.validateNode(graphCopy, nodeCopy); + graph.getNodes().put(nodeId, nodeCopy); + } + + + @PUT + @Path("{nodeId}") + @ApiOperation( + httpMethod = "PUT", + value = "Edits a node of a given graph", + notes = "Edits a single node of a given graph", + response = Node.class) + @ApiResponses(value = { @ApiResponse(code = 400, message = "Invalid node object", response = ErrorMessage.class), + @ApiResponse(code = 403, message = "Invalid graph and/or node id", response = ErrorMessage.class), + @ApiResponse(code = 404, message = "Graph and/or node not found", response = ErrorMessage.class), + @ApiResponse(code = 500, message = "Internal server error", response = ErrorMessage.class), + @ApiResponse(code = 200, message = "Node edited successfully", response = Node.class)}) + public Node updateNode( + @ApiParam(value = "Graph id", required = true) @PathParam("graphId") long graphId, + @ApiParam(value = "Node id", required = true) @PathParam("nodeId") long nodeId, + @ApiParam(value = "Updated node object", required = true) Node node){ + node.setId(nodeId); + return nodeService.updateNode(graphId, node); + } + + @DELETE + @Path("{nodeId}") + @ApiOperation( + httpMethod = "DELETE", + value = "Deletes a node of a given graph", + notes = "Deletes a single node of a given graph") + @ApiResponses(value = { @ApiResponse(code = 403, message = "Invalid graph and/or node id", response = ErrorMessage.class), + @ApiResponse(code = 500, message = "Internal server error", response = ErrorMessage.class), + @ApiResponse(code = 204, message = "Node successfully deleted")}) + public void deleteNode( + @ApiParam(value = "Graph id", required = true) @PathParam("graphId") long graphId, + @ApiParam(value = "Node id", required = true) @PathParam("nodeId") long nodeId){ + nodeService.removeNode(graphId, nodeId); + } + + private String getUriForSelf(UriInfo uriInfo, long graphId, Node node) { + String uri = uriInfo.getBaseUriBuilder() + //.path(NodeResource.class) + .path(GraphResource.class) + .path(GraphResource.class, "getNodeResource") + .resolveTemplate("graphId", graphId) + .path(Long.toString(node.getId())) + .build() + .toString(); + return uri; + } + + private String getUriForNeighbours(UriInfo uriInfo, long graphId, Node node) { + String uri = uriInfo.getBaseUriBuilder() + .path(GraphResource.class) + .path(GraphResource.class, "getNodeResource") + .resolveTemplate("graphId", graphId) + .path(Long.toString(node.getId())) + .path("neighbours") + .build() + .toString(); +// .path(NodeResource.class) +// .path(NodeResource.class, "getNeighbourResource") +// .path(NeighbourResource.class) +// .resolveTemplate("nodeId", node.getId()) +// .build() +// .toString(); + return uri; + } + + @Path("{nodeId}/neighbours") + public NeighbourResource getNeighbourResource(){ + return new NeighbourResource(); + } +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/resources/beans/VerificationBean.java b/verigraph/src/main/java/it/polito/escape/verify/resources/beans/VerificationBean.java new file mode 100644 index 0000000..d6f9ca6 --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/resources/beans/VerificationBean.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.resources.beans; + +import javax.ws.rs.QueryParam; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +@ApiModel("Verification") +public class VerificationBean { + + @ApiModelProperty(example = "webclient", value = "Source node. Must refer to an existing node of the same graph") + private @QueryParam("source") String source; + + @ApiModelProperty( example = "webserver", + value = "Destination node. Must refer to an existing node of the same graph") + private @QueryParam("destination") String destination; + + @ApiModelProperty( example = "reachability", + value = "Verification policy ('reachability', 'isolation', 'traversal')") + private @QueryParam("type") String type; + + @ApiModelProperty( example = "firewall", + value = "Absent if verification type is 'reachability', equal to the name of a middlebox to be avoided if verification type is 'isolation', equal to the name of a middlebox to be traversed if verification type is 'traversal'") + private @QueryParam("middlebox") String middlebox; + + public String getSource() { + return source; + } + + public void setSource(String source) { + this.source = source; + } + + public String getDestination() { + return destination; + } + + public void setDestination(String destination) { + this.destination = destination; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getMiddlebox() { + return middlebox; + } + + public void setMiddlebox(String middlebox) { + this.middlebox = middlebox; + } + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/serializer/CustomConfigurationSerializer.java b/verigraph/src/main/java/it/polito/escape/verify/serializer/CustomConfigurationSerializer.java new file mode 100644 index 0000000..e28273f --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/serializer/CustomConfigurationSerializer.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.serializer; + +import java.io.IOException; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +import it.polito.escape.verify.exception.InternalServerErrorException; +import it.polito.escape.verify.model.Configuration; + +public class CustomConfigurationSerializer extends JsonSerializer<Configuration> { + + @Override + public void serialize(Configuration conf, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonProcessingException { + try { + jgen.writeObject(conf.getConfiguration()); + } catch (IOException e) { + throw new InternalServerErrorException("I/O error serializing a configuration object: " + e.getMessage()); + } + + } + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/serializer/CustomMapSerializer.java b/verigraph/src/main/java/it/polito/escape/verify/serializer/CustomMapSerializer.java new file mode 100644 index 0000000..e811365 --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/serializer/CustomMapSerializer.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.serializer; + +import java.io.IOException; +import java.util.Map; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +import it.polito.escape.verify.exception.InternalServerErrorException; + +public class CustomMapSerializer extends JsonSerializer<Map<?, ?>> { + @Override + public void serialize(final Map<?, ?> value, final JsonGenerator jgen, final SerializerProvider provider) { + try { + jgen.writeObject(value.values()); + } catch (IOException e) { + throw new InternalServerErrorException("I/O error serializing a map: " + e.getMessage()); + } + } +}
\ No newline at end of file diff --git a/verigraph/src/main/java/it/polito/escape/verify/service/GraphService.java b/verigraph/src/main/java/it/polito/escape/verify/service/GraphService.java new file mode 100644 index 0000000..b34eb08 --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/service/GraphService.java @@ -0,0 +1,129 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import it.polito.escape.verify.database.DatabaseClass; +import it.polito.escape.verify.exception.DataNotFoundException; +import it.polito.escape.verify.exception.ForbiddenException; +import it.polito.escape.verify.model.Graph; +import it.polito.escape.verify.model.Neighbour; +import it.polito.escape.verify.model.Node; + +public class GraphService { + + private Map<Long, Graph> graphs = DatabaseClass.getInstance().getGraphs(); + + public GraphService() { + + } + + public List<Graph> getAllGraphs() { + return new ArrayList<Graph>(graphs.values()); + } + + public Graph getGraph(long id) { + if (id <= 0) { + throw new ForbiddenException("Illegal graph id: " + id); + } + Graph graph = graphs.get(id); + if (graph == null) { + throw new DataNotFoundException("Graph with id " + id + " not found"); + } + return graph; + } + + public Graph updateGraph(Graph graph) { + if (graph.getId() <= 0) { + throw new ForbiddenException("Illegal graph id: " + graph.getId()); + } + Graph localGraph = graphs.get(graph.getId()); + if (localGraph == null) { + throw new DataNotFoundException("Graph with id " + graph.getId() + " not found"); + } + + validateGraph(graph); + +// int numberOfNodes = 0; +// for (Node node : graph.getNodes().values()) { +// +// node.setId(++numberOfNodes); +// +// int numberOfNodeNeighbours = 0; +// for (Neighbour neighbour : node.getNeighbours().values()) { +// neighbour.setId(++numberOfNodeNeighbours); +// } +// } + + for (Map.Entry<Long, Node> nodeEntry : graph.getNodes().entrySet()){ + nodeEntry.getValue().setId(nodeEntry.getKey()); + + for (Map.Entry<Long, Neighbour> neighbourEntry : nodeEntry.getValue().getNeighbours().entrySet()){ + neighbourEntry.getValue().setId(neighbourEntry.getKey()); + } + } + + synchronized(this){ + graphs.put(graph.getId(), graph); + DatabaseClass.persistDatabase(); + return graph; + } + } + + public Graph removeGraph(long id) { + if (id <= 0) { + throw new ForbiddenException("Illegal graph id: " + id); + } + synchronized(this){ + return graphs.remove(id); + } + } + + public Graph addGraph(Graph graph) { + validateGraph(graph); + + synchronized (this) { + graph.setId(DatabaseClass.getInstance().getNumberOfGraphs() + 1); + } +// int numberOfNodes = 0; +// for (Node node : graph.getNodes().values()) { +// +// node.setId(++numberOfNodes); +// +// int numberOfNodeNeighbours = 0; +// for (Neighbour neighbour : node.getNeighbours().values()) { +// neighbour.setId(++numberOfNodeNeighbours); +// } +// } + + for (Map.Entry<Long, Node> nodeEntry : graph.getNodes().entrySet()){ + nodeEntry.getValue().setId(nodeEntry.getKey()); + + for (Map.Entry<Long, Neighbour> neighbourEntry : nodeEntry.getValue().getNeighbours().entrySet()){ + neighbourEntry.getValue().setId(neighbourEntry.getKey()); + } + } + + synchronized(this){ + graphs.put(graph.getId(), graph); + DatabaseClass.persistDatabase(); + return graph; + } + } + + public static void validateGraph(Graph graph) { + for (Node node : graph.getNodes().values()) { + NodeService.validateNode(graph, node); + } + } +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/service/JsonValidationService.java b/verigraph/src/main/java/it/polito/escape/verify/service/JsonValidationService.java new file mode 100644 index 0000000..1ac6c1f --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/service/JsonValidationService.java @@ -0,0 +1,136 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.service; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Iterator; +import java.util.Map.Entry; + +import org.apache.commons.lang3.text.WordUtils; + +import com.fasterxml.jackson.databind.JsonNode; + +import it.polito.escape.verify.exception.BadRequestException; +import it.polito.escape.verify.model.Graph; +import it.polito.escape.verify.model.Node; + +public class JsonValidationService { + + private Graph graph = new Graph(); + + private Node node = new Node(); + + public JsonValidationService() { + + } + + public JsonValidationService(Graph graph, Node node) { + this.graph = graph; + this.node = node; + } + + public boolean validateFieldAgainstNodeNames(String value) { + for (Node node : this.graph.getNodes().values()) { + if (node.getName().equals(value)) + return true; + } + return false; + } + + public void validateFieldsAgainstNodeNames(JsonNode node) { + if (node.isTextual()) { + boolean isValid = validateFieldAgainstNodeNames(node.asText()); + if (!isValid) { + System.out.println(node.asText() + " is not a valid string!"); + throw new BadRequestException("String '" + node.asText() + + "' is not valid for the configuration of node '" + this.node.getName() + + "'"); + } + } + if (node.isArray()) { + for (JsonNode object : node) { + validateFieldsAgainstNodeNames(object); + } + } + if (node.isObject()) { + Iterator<Entry<String, JsonNode>> iter = node.fields(); + + while (iter.hasNext()) { + Entry<String, JsonNode> item = iter.next(); + validateFieldsAgainstNodeNames(item.getValue()); + } + } + + } + + public boolean validateNodeConfiguration() { + String className = WordUtils.capitalize(node.getFunctional_type()) + "Validator"; + + Class<?> validator; + try { + validator = Class.forName("it.polito.escape.verify.validation." + className); + } + catch (ClassNotFoundException e) { + System.out.println(className + " not found, configuration properties of node '" + node.getName() + + "' will be validated against node names"); + return false; + } + + Class<?> graphClass; + Class<?> nodeClass; + Class<?> configurationClass; + try { + graphClass = Class.forName("it.polito.escape.verify.model.Graph"); + nodeClass = Class.forName("it.polito.escape.verify.model.Node"); + configurationClass = Class.forName("it.polito.escape.verify.model.Configuration"); + } + catch (ClassNotFoundException e) { + throw new RuntimeException("Model classes not found"); + } + + Class<?>[] paramTypes = new Class[3]; + paramTypes[0] = graphClass; + paramTypes[1] = nodeClass; + paramTypes[2] = configurationClass; + + String methodName = "validate"; + + Object instance; + try { + instance = validator.newInstance(); + } + catch (InstantiationException e) { + throw new RuntimeException("'" + className + "' cannot be instantiated"); + } + catch (IllegalAccessException e) { + throw new RuntimeException("Illegal access to '" + className + "' instantiation"); + } + + Method myMethod; + try { + myMethod = validator.getDeclaredMethod(methodName, paramTypes); + } + catch (NoSuchMethodException e) { + throw new RuntimeException("'" + methodName + "' method has to be implemented in " + className + " class"); + } + try { + myMethod.invoke(instance, graph, node, node.getConfiguration()); + } + catch (IllegalAccessException e) { + throw new RuntimeException("Illegal access to '" + methodName + "' method in " + className + " instance"); + } + catch (InvocationTargetException e) { + throw new BadRequestException("Validation failed for node '" + node.getName() + "': " + + e.getTargetException().getMessage()); + } + return true; + } +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/service/NeighbourService.java b/verigraph/src/main/java/it/polito/escape/verify/service/NeighbourService.java new file mode 100644 index 0000000..ecf4e69 --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/service/NeighbourService.java @@ -0,0 +1,182 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import it.polito.escape.verify.database.DatabaseClass; +import it.polito.escape.verify.exception.BadRequestException; +import it.polito.escape.verify.exception.DataNotFoundException; +import it.polito.escape.verify.exception.ForbiddenException; +import it.polito.escape.verify.model.Graph; +import it.polito.escape.verify.model.Neighbour; +import it.polito.escape.verify.model.Node; + +public class NeighbourService { + + private Map<Long, Graph> graphs = DatabaseClass.getInstance().getGraphs(); + + public List<Neighbour> getAllNeighbours(long graphId, long nodeId) { + if (graphId <= 0) { + throw new ForbiddenException("Illegal graph id: " + graphId); + } + if (nodeId <= 0) { + throw new ForbiddenException("Illegal node id: " + nodeId); + } + Graph graph = graphs.get(graphId); + if (graph == null) + throw new DataNotFoundException("Graph with id " + graphId + " not found"); + Map<Long, Node> nodes = graph.getNodes(); + Node node = nodes.get(nodeId); + if (node == null) + throw new DataNotFoundException("Node with id " + nodeId + " not found in graph with id " + graphId); + Map<Long, Neighbour> neighbours = node.getNeighbours(); + return new ArrayList<Neighbour>(neighbours.values()); + } + + public Neighbour getNeighbour(long graphId, long nodeId, long neighbourId) { + if (graphId <= 0) { + throw new ForbiddenException("Illegal graph id: " + graphId); + } + if (nodeId <= 0) { + throw new ForbiddenException("Illegal node id: " + nodeId); + } + if (neighbourId <= 0) { + throw new ForbiddenException("Illegal neighbour id: " + neighbourId); + } + Graph graph = graphs.get(graphId); + if (graph == null) + throw new DataNotFoundException("Graph with id " + graphId + " not found"); + Map<Long, Node> nodes = graph.getNodes(); + Node node = nodes.get(nodeId); + if (node == null) { + throw new DataNotFoundException("Node with id " + nodeId + " not found in graph with id " + graphId); + } + Map<Long, Neighbour> neighbours = node.getNeighbours(); + Neighbour neighbour = neighbours.get(neighbourId); + if (neighbour == null) { + throw new DataNotFoundException("Neighbour with id " + neighbourId + " not found for node with id " + nodeId + + " in graph with id " + graphId); + } + return neighbour; + } + + public Neighbour addNeighbour(long graphId, long nodeId, Neighbour neighbour) { + if (graphId <= 0) { + throw new ForbiddenException("Illegal graph id: " + graphId); + } + if (nodeId <= 0) { + throw new ForbiddenException("Illegal node id: " + nodeId); + } + Graph graph = graphs.get(graphId); + if (graph == null) + throw new DataNotFoundException("Graph with id " + graphId + " not found"); + Map<Long, Node> nodes = graph.getNodes(); + Node node = nodes.get(nodeId); + if (node == null) { + throw new DataNotFoundException("Node with id " + nodeId + " not found in graph with id " + graphId); + } + Map<Long, Neighbour> neighbours = node.getNeighbours(); + + validateNeighbour(graph, node, neighbour); + + synchronized (this) { + neighbour.setId(neighbours.size() + 1); + neighbours.put(neighbour.getId(), neighbour); + DatabaseClass.persistDatabase(); + return neighbour; + } + } + + public Neighbour updateNeighbour(long graphId, long nodeId, Neighbour neighbour) { + if (graphId <= 0) { + throw new ForbiddenException("Illegal graph id: " + graphId); + } + if (nodeId <= 0) { + throw new ForbiddenException("Illegal node id: " + nodeId); + } + if (neighbour.getId() <= 0) { + throw new ForbiddenException("Illegal neighbour id: " + nodeId); + } + Graph graph = graphs.get(graphId); + if (graph == null) + throw new DataNotFoundException("Graph with id " + graphId + " not found"); + Map<Long, Node> nodes = graph.getNodes(); + Node node = nodes.get(nodeId); + if (node == null) { + throw new DataNotFoundException("Node with id " + nodeId + " not found in graph with id " + graphId); + } + Map<Long, Neighbour> neighbours = node.getNeighbours(); + Neighbour currentNeighbour = neighbours.get(neighbour.getId()); + if (currentNeighbour == null) { + throw new DataNotFoundException("Neighbour with id " + neighbour.getId() + " not found for node with id " + + nodeId + " in graph with id " + graphId); + } + + validateNeighbour(graph, node, neighbour); + + synchronized (this) { + neighbours.put(neighbour.getId(), neighbour); + DatabaseClass.persistDatabase(); + return neighbour; + } + } + + public Neighbour removeNeighbour(long graphId, long nodeId, long neighbourId) { + if (graphId <= 0) { + throw new ForbiddenException("Illegal graph id: " + graphId); + } + if (nodeId <= 0) { + throw new ForbiddenException("Illegal node id: " + nodeId); + } + if (neighbourId <= 0) { + throw new ForbiddenException("Illegal neighbour id: " + nodeId); + } + Graph graph = graphs.get(graphId); + if (graph == null) + throw new DataNotFoundException("Graph with id " + graphId + " not found"); + Map<Long, Node> nodes = graph.getNodes(); + Node node = nodes.get(nodeId); + if (node == null) { + throw new DataNotFoundException("Node with id " + nodeId + " not found in graph with id " + graphId); + } + Map<Long, Neighbour> neighbours = node.getNeighbours(); + + synchronized(this){ + return neighbours.remove(neighbourId); + } + } + + public static void validateNeighbour(Graph graph, Node node, Neighbour neighbour) { + if (graph == null) + throw new BadRequestException("Neighbour validation failed: cannot validate null graph"); + if (node == null) + throw new BadRequestException("Neighbour validation failed: cannot validate null node"); + if (neighbour == null) + throw new BadRequestException("Neighbour validation failed: cannot validate null neighbour"); + + if (neighbour.getName() == null) + throw new BadRequestException("Neighbour validation failed: neighbour 'name' field cannot be null"); + if (neighbour.getName().equals("")) + throw new BadRequestException("Neighbour validation failed: neighbour 'name' field cannot be an empty string"); + + Node nodeFound = graph.searchNodeByName(neighbour.getName()); + if ((nodeFound == null) || (nodeFound.getName().equals(node.getName()))) + throw new BadRequestException("Neighbour validation failed: '" + neighbour.getName() + + "' is not a valid name for a neighbour of node '" + node.getName() + "'"); + + Neighbour neighbourFound = node.searchNeighbourByName(neighbour.getName()); + if ((neighbourFound != null) && (neighbourFound.equals(neighbour) == false)) + throw new BadRequestException("Neighbour validation failed: node '" + node.getName() + + "' already has a neighbour named '" + neighbour.getName() + "'"); + } +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/service/NodeService.java b/verigraph/src/main/java/it/polito/escape/verify/service/NodeService.java new file mode 100644 index 0000000..e6ad672 --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/service/NodeService.java @@ -0,0 +1,258 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.service; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Scanner; + +import javax.ws.rs.InternalServerErrorException; + +import com.fasterxml.jackson.databind.JsonNode; +import com.github.fge.jsonschema.core.exceptions.ProcessingException; +import com.github.fge.jsonschema.main.JsonSchema; + +import it.polito.escape.verify.database.DatabaseClass; +import it.polito.escape.verify.exception.BadRequestException; +import it.polito.escape.verify.exception.DataNotFoundException; +import it.polito.escape.verify.exception.ForbiddenException; +import it.polito.escape.verify.model.Configuration; +import it.polito.escape.verify.model.Graph; +import it.polito.escape.verify.model.Neighbour; +import it.polito.escape.verify.model.Node; + +public class NodeService { + + private Map<Long, Graph> graphs = DatabaseClass.getInstance().getGraphs(); + + public NodeService() { + + } + + public List<Node> getAllNodes(long graphId) { + if (graphId <= 0) { + throw new ForbiddenException("Illegal graph id: " + graphId); + } + Graph graph = graphs.get(graphId); + if (graph == null) + throw new DataNotFoundException("Graph with id " + graphId + " not found"); + Map<Long, Node> nodes = graph.getNodes(); + return new ArrayList<Node>(nodes.values()); + } + + public Node getNode(long graphId, long nodeId) { + if (graphId <= 0) { + throw new ForbiddenException("Illegal graph id: " + graphId); + } + if (nodeId <= 0) { + throw new ForbiddenException("Illegal node id: " + nodeId); + } + Graph graph = graphs.get(graphId); + if (graph == null) + throw new DataNotFoundException("Graph with id " + graphId + " not found"); + Map<Long, Node> nodes = graph.getNodes(); + Node node = nodes.get(nodeId); + if (node == null) { + throw new DataNotFoundException("Node with id " + nodeId + " not found in graph with id " + graphId); + } + return node; + } + + public Node updateNode(long graphId, Node node) { + if (graphId <= 0) { + throw new ForbiddenException("Illegal graph id: " + graphId); + } + if (node.getId() <= 0) { + throw new ForbiddenException("Illegal node id: " + node.getId()); + } + Graph graph = graphs.get(graphId); + if (graph == null) + throw new DataNotFoundException("Graph with id " + graphId + " not found"); + Map<Long, Node> nodes = graph.getNodes(); + Node localNode = nodes.get(node.getId()); + if (localNode == null) { + throw new DataNotFoundException("Node with id " + node.getId() + " not found in graph with id " + graphId); + } + + Graph graphCopy = new Graph(); + graphCopy.setId(graph.getId()); + graphCopy.setNodes(new HashMap<Long, Node>(graph.getNodes())); + graphCopy.getNodes().remove(node.getId()); + + // int numberOfNeighbours = 0; + // for(Neighbour neighbour : node.getNeighbours().values()){ + // neighbour.setId(++numberOfNeighbours); + // } + + for (Map.Entry<Long, Neighbour> neighbourEntry : node.getNeighbours().entrySet()) { + neighbourEntry.getValue().setId(neighbourEntry.getKey()); + } + + validateNode(graphCopy, node); + + synchronized (this) { + nodes.put(node.getId(), node); + DatabaseClass.persistDatabase(); + return node; + } + } + + public Node removeNode(long graphId, long nodeId) { + if (graphId <= 0) { + throw new ForbiddenException("Illegal graph id: " + graphId); + } + if (nodeId <= 0) { + throw new ForbiddenException("Illegal node id: " + nodeId); + } + Graph graph = graphs.get(graphId); + if (graph == null) + throw new DataNotFoundException("Graph with id " + graphId + " not found"); + Map<Long, Node> nodes = graph.getNodes(); + + synchronized (this) { + return nodes.remove(nodeId); + } + } + + public Node addNode(long graphId, Node node) { + if (graphId <= 0) { + throw new ForbiddenException("Illegal graph id: " + graphId); + } + Graph graph = graphs.get(graphId); + if (graph == null) + throw new DataNotFoundException("Graph with id " + graphId + " not found"); + Map<Long, Node> nodes = graph.getNodes(); + + validateNode(graph, node); + + synchronized (this) { + node.setId(DatabaseClass.getInstance().getGraphNumberOfNodes(graphId) + 1); + } + + // int numberOfNeighbours = 0; + + for (Map.Entry<Long, Neighbour> neighbourEntry : node.getNeighbours().entrySet()) { + neighbourEntry.getValue().setId(neighbourEntry.getKey()); + } + + // for (Neighbour neighbour : node.getNeighbours().values()) { + // neighbour.setId(++numberOfNeighbours); + // } + + synchronized (this) { + nodes.put(node.getId(), node); + DatabaseClass.persistDatabase(); + return node; + } + } + + public Node searchByName(long graphId, String nodeName) { + if (graphId <= 0) { + throw new ForbiddenException("Illegal graph id: " + graphId); + } + Graph graph = graphs.get(graphId); + if (graph == null) + throw new DataNotFoundException("Graph with id " + graphId + " not found"); + Map<Long, Node> nodes = graph.getNodes(); + + for (Node node : nodes.values()) { + if (node.getName().equals(nodeName)) + return node; + } + return null; + } + + public static void validateNode(Graph graph, Node node) { + if (graph == null) + throw new BadRequestException("Node validation failed: cannot validate null graph"); + if (node == null) + throw new BadRequestException("Node validation failed: cannot validate null node"); + + if (node.getName() == null) + throw new BadRequestException("Node validation failed: node 'name' field cannot be null"); + if (node.getFunctional_type() == null) + throw new BadRequestException("Node validation failed: node 'functional_type' field cannot be null"); + + if (node.getName().equals("")) + throw new BadRequestException("Node validation failed: node 'name' field cannot be an empty string"); + if (node.getFunctional_type().equals("")) + throw new BadRequestException("Node validation failed: node 'functional_type' field cannot be an empty string"); + + Node nodeFound = graph.searchNodeByName(node.getName()); + if ((nodeFound != null) && (nodeFound.equals(node) == false)) + throw new BadRequestException("Node validation failed: graph already has a node named '" + node.getName() + + "'"); + Configuration configuration = node.getConfiguration(); + if (configuration != null) { + JsonNode configurationJsonNode = configuration.getConfiguration(); + // validate configuration against schema file + validateNodeConfigurationAgainstSchemaFile(node, configurationJsonNode); + JsonValidationService jsonValidator = new JsonValidationService(graph, node); + boolean hasCustomValidator = jsonValidator.validateNodeConfiguration(); + if (!hasCustomValidator) { + jsonValidator.validateFieldsAgainstNodeNames(configurationJsonNode); + } + } + + // validate neighbours + Map<Long, Neighbour> nodeNeighboursMap = node.getNeighbours(); + if (nodeNeighboursMap == null) + throw new BadRequestException("Node validation failed: node 'neighbours' cannot be null"); + for (Neighbour neighbour : nodeNeighboursMap.values()) { + NeighbourService.validateNeighbour(graph, node, neighbour); + } + } + + public static void validateNodeConfigurationAgainstSchemaFile(Node node, JsonNode configurationJson) { + String schemaFileName = node.getFunctional_type() + ".json"; + + File schemaFile = new File(System.getProperty("catalina.base") + "/webapps/verify/json/" + schemaFileName); + + if (!schemaFile.exists()) { + //if no REST client, try gRPC application + schemaFile = new File("src/main/webapp/json/" + schemaFileName); + + if (!schemaFile.exists()) { + throw new ForbiddenException("Functional type '" + node.getFunctional_type() + + "' is not supported! Please edit 'functional_type' field of node '" + + node.getName() + "'"); + } + } + + JsonSchema schemaNode = null; + try { + schemaNode = ValidationUtils.getSchemaNode(schemaFile); + } + catch (IOException e) { + throw new InternalServerErrorException("Unable to load '" + schemaFileName + "' schema file"); + } + catch (ProcessingException e) { + throw new InternalServerErrorException("Unable to resolve '" + schemaFileName + + "' schema file as a schema node"); + } + + try { + ValidationUtils.validateJson(schemaNode, configurationJson); + } + catch (ProcessingException e) { + throw new BadRequestException("Something went wrong trying to validate node '" + node.getName() + + "' with the following configuration: '" + configurationJson.toString() + + "' against the json schema '" + schemaFile.getName() + "': " + + e.getMessage()); + + } + + } +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/service/ValidationUtils.java b/verigraph/src/main/java/it/polito/escape/verify/service/ValidationUtils.java new file mode 100644 index 0000000..77ef4f7 --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/service/ValidationUtils.java @@ -0,0 +1,132 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.service; + +import java.io.File; +import java.io.IOException; +import java.net.URL; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.github.fge.jackson.JsonLoader; +import com.github.fge.jsonschema.core.exceptions.ProcessingException; +import com.github.fge.jsonschema.core.report.ProcessingMessage; +import com.github.fge.jsonschema.core.report.ProcessingReport; +import com.github.fge.jsonschema.main.JsonSchema; +import com.github.fge.jsonschema.main.JsonSchemaFactory; + +public class ValidationUtils { + + public static final String JSON_V4_SCHEMA_IDENTIFIER = "http://json-schema.org/draft-04/schema#"; + public static final String JSON_SCHEMA_IDENTIFIER_ELEMENT = "$schema"; + + public static JsonNode getJsonNode(String jsonText) throws IOException { + return JsonLoader.fromString(jsonText); + } // getJsonNode(text) ends + + public static JsonNode getJsonNode(File jsonFile) throws IOException { + return JsonLoader.fromFile(jsonFile); + } // getJsonNode(File) ends + + public static JsonNode getJsonNode(URL url) throws IOException { + return JsonLoader.fromURL(url); + } // getJsonNode(URL) ends + + public static JsonNode getJsonNodeFromResource(String resource) throws IOException { + return JsonLoader.fromResource(resource); + } // getJsonNode(Resource) ends + + public static JsonSchema getSchemaNode(String schemaText) throws IOException, ProcessingException { + final JsonNode schemaNode = getJsonNode(schemaText); + return _getSchemaNode(schemaNode); + } // getSchemaNode(text) ends + + public static JsonSchema getSchemaNode(File schemaFile) throws IOException, ProcessingException { + final JsonNode schemaNode = getJsonNode(schemaFile); + return _getSchemaNode(schemaNode); + } // getSchemaNode(File) ends + + public static JsonSchema getSchemaNode(URL schemaFile) throws IOException, ProcessingException { + final JsonNode schemaNode = getJsonNode(schemaFile); + return _getSchemaNode(schemaNode); + } // getSchemaNode(URL) ends + + public static JsonSchema getSchemaNodeFromResource(String resource) throws IOException, ProcessingException { + final JsonNode schemaNode = getJsonNodeFromResource(resource); + return _getSchemaNode(schemaNode); + } // getSchemaNode() ends + + public static void validateJson(JsonSchema jsonSchemaNode, JsonNode jsonNode) throws ProcessingException { + ProcessingReport report = jsonSchemaNode.validate(jsonNode); + if (!report.isSuccess()) { + for (ProcessingMessage processingMessage : report) { + throw new ProcessingException(processingMessage); + } + } + } // validateJson(Node) ends + + public static boolean isJsonValid(JsonSchema jsonSchemaNode, JsonNode jsonNode) throws ProcessingException { + ProcessingReport report = jsonSchemaNode.validate(jsonNode); + return report.isSuccess(); + } // validateJson(Node) ends + + public static boolean isJsonValid(String schemaText, String jsonText) throws ProcessingException, IOException { + final JsonSchema schemaNode = getSchemaNode(schemaText); + final JsonNode jsonNode = getJsonNode(jsonText); + return isJsonValid(schemaNode, jsonNode); + } // validateJson(Node) ends + + public static boolean isJsonValid(File schemaFile, File jsonFile) throws ProcessingException, IOException { + final JsonSchema schemaNode = getSchemaNode(schemaFile); + final JsonNode jsonNode = getJsonNode(jsonFile); + return isJsonValid(schemaNode, jsonNode); + } // validateJson(Node) ends + + public static boolean isJsonValid(URL schemaURL, URL jsonURL) throws ProcessingException, IOException { + final JsonSchema schemaNode = getSchemaNode(schemaURL); + final JsonNode jsonNode = getJsonNode(jsonURL); + return isJsonValid(schemaNode, jsonNode); + } // validateJson(Node) ends + + public static void validateJson(String schemaText, String jsonText) throws IOException, ProcessingException { + final JsonSchema schemaNode = getSchemaNode(schemaText); + final JsonNode jsonNode = getJsonNode(jsonText); + validateJson(schemaNode, jsonNode); + } // validateJson(text) ends + + public static void validateJson(File schemaFile, File jsonFile) throws IOException, ProcessingException { + final JsonSchema schemaNode = getSchemaNode(schemaFile); + final JsonNode jsonNode = getJsonNode(jsonFile); + validateJson(schemaNode, jsonNode); + } // validateJson(File) ends + + public static void validateJson(URL schemaDocument, URL jsonDocument) throws IOException, ProcessingException { + final JsonSchema schemaNode = getSchemaNode(schemaDocument); + final JsonNode jsonNode = getJsonNode(jsonDocument); + validateJson(schemaNode, jsonNode); + } // validateJson(URL) ends + + public static void validateJsonResource(String schemaResource, String jsonResource) throws IOException, + ProcessingException { + final JsonSchema schemaNode = getSchemaNode(schemaResource); + final JsonNode jsonNode = getJsonNodeFromResource(jsonResource); + validateJson(schemaNode, jsonNode); + } // validateJsonResource() ends + + private static JsonSchema _getSchemaNode(JsonNode jsonNode) throws ProcessingException { + final JsonNode schemaIdentifier = jsonNode.get(JSON_SCHEMA_IDENTIFIER_ELEMENT); + if (null == schemaIdentifier) { + ((ObjectNode) jsonNode).put(JSON_SCHEMA_IDENTIFIER_ELEMENT, JSON_V4_SCHEMA_IDENTIFIER); + } + + final JsonSchemaFactory factory = JsonSchemaFactory.byDefault(); + return factory.getJsonSchema(jsonNode); + } // _getSchemaNode() ends +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/service/VerificationService.java b/verigraph/src/main/java/it/polito/escape/verify/service/VerificationService.java new file mode 100644 index 0000000..1d31ae9 --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/service/VerificationService.java @@ -0,0 +1,1185 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.service; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileWriter; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import javax.tools.Diagnostic; +import javax.tools.DiagnosticCollector; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; +import javax.ws.rs.ProcessingException; +import javax.xml.bind.JAXBException; + +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; + +import com.fasterxml.jackson.databind.JsonNode; + +import it.polito.escape.verify.client.Neo4jManagerClient; +import it.polito.escape.verify.exception.BadRequestException; +import it.polito.escape.verify.exception.DataNotFoundException; +import it.polito.escape.verify.exception.ForbiddenException; +import it.polito.escape.verify.exception.InternalServerErrorException; +import it.polito.escape.verify.model.Configuration; +import it.polito.escape.verify.model.Entry; +import it.polito.escape.verify.model.Graph; +import it.polito.escape.verify.model.Neighbour; +import it.polito.escape.verify.model.Node; +import it.polito.escape.verify.model.Test; +import it.polito.escape.verify.model.Verification; +import it.polito.escape.verify.resources.beans.VerificationBean; +import it.polito.nffg.neo4j.jaxb.Paths; +import qj.util.ReflectUtil; +import qj.util.lang.DynamicClassLoader; + +public class VerificationService { + + private static final String generatorFolder = System.getProperty("catalina.base") + + "/webapps/verify/WEB-INF/classes/tests/j-verigraph-generator"; + + private static final String generatorFolderForGrpc = "service/src/tests/j-verigraph-generator"; + + private String testClassGenerator = generatorFolder + "/test_class_generator.py"; + + private String testGenerator = generatorFolder + "/test_generator.py"; + + public VerificationService() { + + } + + private Paths getPaths(Graph graph, Node sourceNode, Node destinationNode) { + + String source = sourceNode.getName() + "_" + sourceNode.getId(); + String destination = destinationNode.getName() + "_" + destinationNode.getId(); + + List<String> endpoints = new ArrayList<>(); + List<String> firewalls = new ArrayList<>(); + Map<String, List<Entry>> routingTable = new HashMap<>(); + + for (Node node : graph.getNodes().values()) { + // if firewall + if (node.getFunctional_type().equals("NF")) { + // add 2 connection points to RT + routingTable.put(node.getName() + "_" + node.getId() + "_in", new ArrayList<Entry>()); + routingTable.put(node.getName() + "_" + node.getId() + "_out", new ArrayList<Entry>()); + // add node to firewalls + firewalls.add(node.getName() + "_" + node.getId()); + // scan neighbours + for (Neighbour neighbour : node.getNeighbours().values()) { + // check if neighbour is a firewall + Node hop = graph.searchNodeByName(neighbour.getName()); + // if neighbour is a firewall connect to its input port + if (hop.getFunctional_type().equals("NF")) + routingTable.get(node.getName() + "_" + node.getId() + "_out") + .add(new Entry("output", neighbour.getName() + "_" + hop.getId() + "_in")); + else + // connect + // normally to + // node + routingTable.get(node.getName() + "_" + node.getId() + + "_out") + .add(new Entry( "output", + neighbour.getName() + "_" + + hop.getId())); + } + } + // if endpoint + else { + // add endpoint to RT + routingTable.put(node.getName() + "_" + node.getId(), new ArrayList<Entry>()); + // add to endpoints + endpoints.add(node.getName() + "_" + node.getId()); + // scan neighbours + for (Neighbour neighbour : node.getNeighbours().values()) { + // check if neighbour is a firewall + Node hop = graph.searchNodeByName(neighbour.getName()); + // if neighbour is a firewall connect to its input port + if (hop.getFunctional_type().equals("NF")) + routingTable.get(node.getName() + "_" + node.getId()) + .add(new Entry("output", neighbour.getName() + "_" + hop.getId() + "_in")); + else { + // connect + // normally to + // node + routingTable.get(node.getName() + "_" + node.getId()) + .add(new Entry("output", neighbour.getName() + "_" + hop.getId())); + } + } + } + + // end node scan + } + // debug print + System.out.println("Endpoints:"); + for (String endpoint : endpoints) { + System.out.println(endpoint); + } + System.out.println("Firewalls:"); + for (String firewall : firewalls) { + System.out.println(firewall); + } + System.out.println("Source: " + source); + System.out.println("Destination: " + destination); + for (String key : routingTable.keySet()) { + System.out.println("RT for node " + key); + for (Entry entry : routingTable.get(key)) { + System.out.println("\t" + entry.getDirection() + "->" + entry.getDestination()); + } + } + // end debug print + + Neo4jManagerClient client = new Neo4jManagerClient( "http://localhost:8080/neo4jmanager/rest/", + source, + destination, + endpoints, + firewalls, + routingTable); + + Paths paths = null; + try { + paths = client.getPaths(); + } + catch (JAXBException e) { + throw new InternalServerErrorException("Error generating input for neo4jmanager: " + e.getMessage()); + } + catch (ProcessingException e) { + throw new InternalServerErrorException("Response of neo4jmanager doesn't contain any path: " + + e.getMessage()); + } + catch (IllegalStateException e) { + throw new InternalServerErrorException("Error getting a response from neo4jmanager, no input stream for paths or input stream already consumed: " + + e.getMessage()); + } + catch (Exception e) { + throw new InternalServerErrorException("Unable to continue due to a neo4jmanager error: " + e.getMessage()); + } + + return paths; + + } + + private List<String> sanitizePath(String path) { + List<String> newPath = new ArrayList<String>(); + // find all nodes, i.e. all names between parentheses + Matcher m = Pattern.compile("\\(([^)]+)\\)").matcher(path); + while (m.find()) { + String node = m.group(1); + + int spaceIndex = node.lastIndexOf("_"); + if (spaceIndex != -1) { + node = node.substring(0, spaceIndex); + newPath.add(node); + } + } + return newPath; + + } + + private List<List<String>> sanitizePaths(Paths paths) { + List<List<String>> sanitizedPaths = new ArrayList<List<String>>(); + for (String path : paths.getPath()) { + System.out.println("Original path: " + path); + List<String> newPath = sanitizePath(path); + sanitizedPaths.add(newPath); + } + return sanitizedPaths; + } + + static private Map<String, Long> toMap(List<String> lst) { + return lst.stream().collect(Collectors.groupingBy(s -> s, Collectors.counting())); + } + + private void eliminateLoopsInPaths(List<List<String>> sanitizedPaths) { + List<List<String>> pathsToBeRemoved = new ArrayList<List<String>>(); + + for (List<String> path : sanitizedPaths) { + Map<String, Long> occurrencesMap = toMap(path); + for (long occurrences : occurrencesMap.values()) { + if (occurrences > 1) { + pathsToBeRemoved.add(path); + break; + } + } + } + for (List<String> path : pathsToBeRemoved) { + sanitizedPaths.remove(path); + } + } + + private void printListsOfStrings(String message, List<List<String>> lists) { + System.out.println(message); + for (List<String> element : lists) { + System.out.println(element); + } + } + + private static File createTempDir(String prefix) throws IOException { + String tmpDirStr = System.getProperty("java.io.tmpdir"); + if (tmpDirStr == null) { + throw new IOException("System property 'java.io.tmpdir' does not specify a tmp dir"); + } + + File tmpDir = new File(tmpDirStr); + if (!tmpDir.exists()) { + boolean created = tmpDir.mkdirs(); + if (!created) { + throw new IOException("Unable to create tmp dir " + tmpDir); + } + } + + File resultDir = null; + int suffix = (int) System.currentTimeMillis(); + int failureCount = 0; + do { + resultDir = new File(tmpDir, prefix + suffix % 10000); + suffix++; + failureCount++; + } while (resultDir.exists() && failureCount < 50); + + if (resultDir.exists()) { + throw new IOException(failureCount + + " attempts to generate a non-existent directory name failed, giving up"); + } + boolean created = resultDir.mkdir(); + if (!created) { + throw new IOException("Failed to create tmp directory"); + } + + return resultDir; + } + + @SuppressWarnings("unchecked") + private void generateChainsFile(Graph graph, List<List<String>> sanitizedPaths, String chainsFile) { + JSONObject root = new JSONObject(); + JSONArray chains = new JSONArray(); + + int chainCounter = 0; + + for (List<String> path : sanitizedPaths) { + Iterator<String> pathsIterator = path.iterator(); + JSONObject chain = new JSONObject(); + chain.put("id", ++chainCounter); + chain.put("flowspace", "tcp=80"); + JSONArray nodes = new JSONArray(); + while (pathsIterator.hasNext()) { + String nodeName = (String) pathsIterator.next(); + Node currentNode = graph.searchNodeByName(nodeName); + if (currentNode == null) { + throw new InternalServerErrorException("Unable to generate 'chains.json' for neo4jmanager: node " + + nodeName + " not found"); + } + JSONObject node = new JSONObject(); + node.put("name", currentNode.getName()); + // if(currentNode.getFunctional_type().equals("firewall")) + // node.put("address", "ip_nat"); + // else + node.put("address", "ip_" + currentNode.getName()); + node.put("functional_type", currentNode.getFunctional_type()); + nodes.add(node); + chain.put("nodes", nodes); + } + chains.add(chain); + } + root.put("chains", chains); + + try (FileWriter file = new FileWriter(chainsFile)) { + file.write(root.toJSONString()); + System.out.println("Successfully created 'chains.json' with the following content:"); + System.out.println(root); + } + catch (IOException e) { + throw new InternalServerErrorException("Error saving 'chains.json' for neo4jmanager"); + } + + } + + @SuppressWarnings("unchecked") + private void generateConfigFile(Graph graph, String configFile) { + JSONObject root = new JSONObject(); + JSONArray nodes = new JSONArray(); + + for (Node n : graph.getNodes().values()) { + JSONObject node = new JSONObject(); + // JSONArray configuration = new JSONArray(); + Configuration nodeConfig = n.getConfiguration(); + JsonNode configuration = nodeConfig.getConfiguration(); + + node.put("configuration", configuration); + node.put("id", nodeConfig.getId()); + node.put("description", nodeConfig.getDescription()); + + nodes.add(node); + + } + root.put("nodes", nodes); + + try (FileWriter file = new FileWriter(configFile)) { + file.write(root.toJSONString()); + System.out.println("Successfully created 'config.json' with the following content:"); + System.out.println(root); + } + catch (IOException e) { + throw new InternalServerErrorException("Error saving 'config.json' for neo4jmanager"); + } + + } + + private void printCommand(String[] cmd) { + for (String c : cmd) { + System.out.printf(c + " "); + } + System.out.println(""); + } + + private String platfromIndependentPath(String path) { + path = path.replaceAll("/", Matcher.quoteReplacement(Character.toString(File.separatorChar))); + return path; + } + + private void generateTestScenarios(String chainsFile, String configFile, String scenarioFile) { + + String[] cmd = { "python", platfromIndependentPath(testClassGenerator), "-c", + platfromIndependentPath(chainsFile), "-f", platfromIndependentPath(configFile), "-o", + platfromIndependentPath(scenarioFile) }; + printCommand(cmd); + + ProcessBuilder pb = new ProcessBuilder(cmd); + pb.redirectErrorStream(true); + Process process; + try { + process = pb.start(); + + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + String line; + while ((line = reader.readLine()) != null) + System.out.println("test_class_generator.py: " + line); + process.waitFor(); + if (process.exitValue() != 0) { + throw new InternalServerErrorException("Unable to generate test scenario file for the verification request: test_class_generator returned " + + process.exitValue()); + } + } + catch (IOException e) { + throw new InternalServerErrorException("Error generating tests for Z3: unable to execute generator"); + } + catch (InterruptedException e) { + throw new InternalServerErrorException("Error generating tests for Z3: generator got interrupted during execution"); + } + + } + + private void generateTests( int scenariosCounter, String scenariosBasename, String source, String destination, + String testsBasename) { + + List<String> scenarios = new ArrayList<String>(); + List<String> tests = new ArrayList<String>(); + for (int i = 0; i < scenariosCounter; i++) { + scenarios.add(scenariosBasename + "_" + (i + 1) + ".java"); + tests.add(testsBasename + "_" + (i + 1) + ".java"); + } + + for (int i = 0; i < scenariosCounter; i++) { + String[] cmd = { "python", platfromIndependentPath(testGenerator), "-i", + platfromIndependentPath(scenarios.get(i)), "-o", platfromIndependentPath(tests.get(i)), + "-s", source, "-d", destination }; + printCommand(cmd); + + ProcessBuilder pb = new ProcessBuilder(cmd); + pb.redirectErrorStream(true); + Process process; + try { + process = pb.start(); + + BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream())); + String line; + while ((line = reader.readLine()) != null) + System.out.println("test_generator.py: " + line); + process.waitFor(); + if (process.exitValue() != 0) { + throw new InternalServerErrorException("Unable to generate test file for the verification request: test_generator returned " + + process.exitValue()); + } + } + catch (IOException e) { + throw new InternalServerErrorException("Error generating tests for Z3: unable to execute generator"); + } + catch (InterruptedException e) { + throw new InternalServerErrorException("Error generating tests for Z3: generator got interrupted during execution"); + } + + } + + } + + private void prepareForCompilationAndExecution( int scenariosCounter, String scenarioBasename, String testBasename, + List<File> sourceFiles, List<File> classFiles) { + for (int i = 0; i < scenariosCounter; i++) { + String scenario = scenarioBasename + "_" + (i + 1) + ".java"; + sourceFiles.add(new File(scenario)); + System.out.println("Scenario file " + scenario + " added to compilation"); + + String testSource = testBasename + "_" + (i + 1) + ".java"; + String testClass = testBasename + "_" + (i + 1); + + sourceFiles.add(new File(testSource)); + System.out.println("Test file " + testSource + " added to copilation"); + classFiles.add(new File(testClass)); + System.out.println("Test file " + testClass + " added to execution"); + } + } + + private void compileFiles(List<File> files, String folder) { + + JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + if (compiler == null) { + throw new InternalServerErrorException("Error getting the Java compiler: JDK >= 1.8 required"); + } + StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null); + + try { + // fileManager.setLocation(StandardLocation.CLASS_OUTPUT, + // Arrays.asList(new File(projectFolder))); + + // String z3 = "/usr/lib/com.microsoft.z3.jar"; + // List<String> optionList = new ArrayList<String>(); + // optionList.add("-classpath"); + // optionList.add(System.getProperty("java.class.path") + ":" + z3); + List<String> optionList = new ArrayList<String>(); + optionList.add("-d"); + optionList.add(folder); + DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>(); + + boolean success = compiler + .getTask( null, + fileManager, + diagnostics, + optionList, + null, + fileManager.getJavaFileObjectsFromFiles(files)) + .call(); + if (!success) { + Locale myLocale = Locale.getDefault(); + StringBuilder msg = new StringBuilder(); + msg.append("Error compiling Z3 test files: "); + for (Diagnostic<? extends JavaFileObject> err : diagnostics.getDiagnostics()) { + msg.append('\n'); + msg.append(err.getKind()); + msg.append(": "); + if (err.getSource() != null) { + msg.append(err.getSource().getName()); + } + msg.append(':'); + msg.append(err.getLineNumber()); + msg.append(": "); + msg.append(err.getMessage(myLocale)); + } + throw new InternalServerErrorException(msg.toString()); + } + fileManager.close(); + + } + catch (IOException e) { + throw new InternalServerErrorException("Unable to set the location of the Z3 test files to be compiled"); + } + + } + + private int runIt(File filename, String folder) { + int endIndex = filename.getName().lastIndexOf("."); + String filenameNoExtension; + if (endIndex == -1) { + filenameNoExtension = filename.getName(); + } + else { + filenameNoExtension = filename.getName().substring(0, endIndex); + if (!filenameNoExtension.matches("\\w+")) { + filenameNoExtension = filename.getName(); + } + } + + System.out.println("Filename is: " + filenameNoExtension); + try { + Class<?> userClass = new DynamicClassLoader(folder).load("tests." + filenameNoExtension); + Object context = ReflectUtil.newInstance(userClass); + Object result = ReflectUtil.invoke("run", context); + return (int) result; + } + catch (Exception e) { + StringWriter errors = new StringWriter(); + e.printStackTrace(new PrintWriter(errors)); + throw new InternalServerErrorException("Error executing Z3 tests: " + e.getMessage() + + ". There are errors in the Z3 model."); + } + } + + private List<Test> runFiles(String folder, List<List<String>> paths, Graph graph, List<File> files) { + List<Test> tests = new ArrayList<Test>(); + for (int i = 0; i < files.size(); i++) { + System.out.println("Running test file \"" + files.get(i).getAbsolutePath() + "\""); + int result = runIt(files.get(i), folder); + System.out.println("Execution returned: " + result); + + List<Node> path = new ArrayList<Node>(); + for (String nodeString : paths.get(i)) { + Node node = graph.searchNodeByName(nodeString); + path.add(node); + } + Test t = new Test(path, result); + tests.add(t); + } + + return tests; + } + + @SuppressWarnings("unused") + private static boolean deleteDir(File dir) { + if (dir.isDirectory()) { + String[] children = dir.list(); + for (int i = 0; i < children.length; i++) { + boolean success = deleteDir(new File(dir, children[i])); + if (!success) { + return false; + } + } + } + + return dir.delete(); + + } + + @SuppressWarnings("unused") + private void deleteFilesWithPrefix(String directory, String prefix, String extension) { + final File scenarioFolder = new File(directory); + final File[] scenarioFiles = scenarioFolder.listFiles(new FilenameFilter() { + + @Override + public boolean accept(final File dir, final String name) { + return name.matches(prefix + ".*\\." + extension); + } + }); + for (final File file : scenarioFiles) { + if (!file.delete()) { + System.err.println("Can't remove " + file.getAbsolutePath()); + } + else { + System.out.println("Removed file " + file.getAbsolutePath()); + } + } + } + + public Verification verify(long graphId, VerificationBean verificationBean) { + if (graphId <= 0) { + throw new ForbiddenException("Illegal graph id: " + graphId); + } + GraphService graphService = new GraphService(); + Graph graph = graphService.getGraph(graphId); + if (graph == null) { + throw new DataNotFoundException("Graph with id " + graphId + " not found"); + } + String source = verificationBean.getSource(); + String destination = verificationBean.getDestination(); + String type = verificationBean.getType(); + if (source == null || source.equals("")) { + throw new BadRequestException("Please specify the 'source' parameter in your request"); + } + if (destination == null || destination.equals("")) { + throw new BadRequestException("Please specify the 'destination' parameter in your request"); + } + if (type == null || type.equals("")) { + throw new BadRequestException("Please specify the 'type' parameter in your request"); + } + + Node sourceNode = graph.searchNodeByName(verificationBean.getSource()); + Node destinationNode = graph.searchNodeByName(verificationBean.getDestination()); + + if (sourceNode == null) { + throw new BadRequestException("The 'source' parameter '" + source + "' is not valid, please insert the name of an existing node"); + } + if (destinationNode == null) { + throw new BadRequestException("The 'destination' parameter '" + destination + "' is not valid, please insert the name of an existing node"); + } + if ((!type.equals("reachability")) && (!type.equals("isolation")) && (!type.equals("traversal"))) { + throw new BadRequestException("The 'type' parameter '" + type + + "' is not valid: valid types are: 'reachability', 'isolation' and 'traversal'"); + } + + Verification v = null; + String middlebox; + Node middleboxNode; + switch (type) { + case "reachability": + v = reachabilityVerification(graph, sourceNode, destinationNode); + break; + case "isolation": + middlebox = verificationBean.getMiddlebox(); + if (middlebox == null || middlebox.equals("")) { + throw new BadRequestException("Please specify the 'middlebox' parameter in your request"); + } + + middleboxNode = graph.searchNodeByName(middlebox); + if (middleboxNode == null) { + throw new BadRequestException("The 'middlebox' parameter '" + middlebox + "' is not valid, please insert the name of an existing node"); + } + if (middleboxNode.getFunctional_type().equals("endpoint")) { + throw new BadRequestException("'" + middlebox + + "' is of type 'endpoint', please choose a valid middlebox"); + } + v = isolationVerification(graph, sourceNode, destinationNode, middleboxNode); + break; + case "traversal": + middlebox = verificationBean.getMiddlebox(); + if (middlebox == null || middlebox.equals("")) { + throw new BadRequestException("Please specify the 'middlebox' parameter in your request"); + } + + middleboxNode = graph.searchNodeByName(middlebox); + if (middleboxNode == null) { + throw new BadRequestException("The 'middlebox' parameter '" + middlebox + "' is not valid, please insert the name of an existing node"); + } + if (middleboxNode.getFunctional_type().equals("endpoint")) { + throw new BadRequestException("'" + middlebox + + "' is of type 'endpoint', please choose a valid middlebox"); + } + v = traversalVerification(graph, sourceNode, destinationNode, middleboxNode); + break; + default: + break; + } + + return v; + } + + private Verification isolationVerification(Graph graph, Node sourceNode, Node destinationNode, Node middleboxNode) { + + Paths paths = getPaths(graph, sourceNode, destinationNode); + if (paths.getPath().size() == 0) { + return new Verification("UNSAT", + "There are no available paths between '" + sourceNode.getName() + "' and '" + + destinationNode.getName() + "'"); + } + + List<List<String>> sanitizedPaths = sanitizePaths(paths); + + printListsOfStrings("Before loops removal", sanitizedPaths); + + eliminateLoopsInPaths(sanitizedPaths); + + printListsOfStrings("After loops removal", sanitizedPaths); + + if (sanitizedPaths.isEmpty()) { + return new Verification("UNSAT", + "There are no available paths between '" + sourceNode.getName() + "' and '" + + destinationNode.getName() + "'"); + } + + List<Test> tests = extractTestsFromPaths(graph, sanitizedPaths, "UNKNWON"); + + extractPathsWithMiddlebox(sanitizedPaths, middleboxNode.getName()); + + if (sanitizedPaths.isEmpty()) { + return new Verification("UNSAT", + tests, + "There are no available paths between '" + sourceNode.getName() + "' and '" + + destinationNode.getName() + "' which traverse middlebox '" + + middleboxNode.getName() + "'. See below all the available paths."); + } + + printListsOfStrings("Paths with middlebox '" + middleboxNode.getName() + "'", sanitizedPaths); + + File tempDir = null; + + try { + tempDir = createTempDir("isolation"); + } + catch (IOException e) { + throw new InternalServerErrorException("Unable to perform verification: " + e.getMessage()); + } + + String chainsFile = tempDir.getAbsolutePath() + "/chains.json"; + generateChainsFile(graph, sanitizedPaths, chainsFile); + + String configFile = tempDir.getAbsolutePath() + "/config.json"; + generateConfigFile(graph, configFile); + + String isolationScenariosBasename = tempDir.getAbsolutePath() + "/IsolationScenario"; + try{ + generateTestScenarios(chainsFile, configFile, isolationScenariosBasename); + }catch(Exception ex){ + testClassGenerator = generatorFolderForGrpc + "/test_class_generator.py"; + generateTestScenarios(chainsFile, configFile, isolationScenariosBasename); + } + + String isolationTestsBasename = tempDir.getAbsolutePath() + "/IsolationTest"; + try{ + generateTests( sanitizedPaths.size(), + isolationScenariosBasename, + sourceNode.getName(), + middleboxNode.getName(), + isolationTestsBasename); + }catch(InternalServerErrorException ex){ + testGenerator = generatorFolderForGrpc + "/test_generator.py"; + generateTests( sanitizedPaths.size(), + isolationScenariosBasename, + sourceNode.getName(), + middleboxNode.getName(), + isolationTestsBasename); + } + + List<File> sourceFiles = new ArrayList<File>(); + List<File> classFiles = new ArrayList<File>(); + prepareForCompilationAndExecution( sanitizedPaths.size(), + isolationScenariosBasename, + isolationTestsBasename, + sourceFiles, + classFiles); + + compileFiles(sourceFiles, tempDir.getAbsolutePath()); + + tests = runFiles(tempDir.getAbsolutePath(), sanitizedPaths, graph, classFiles); + + return evaluateIsolationResults(tests, + sourceNode.getName(), + destinationNode.getName(), + middleboxNode.getName()); + + } + + private List<Test> extractTestsFromPaths(Graph graph, List<List<String>> paths, String result) { + List<Test> tests = new ArrayList<Test>(); + for (List<String> path : paths) { + List<Node> nodes = new ArrayList<Node>(); + for (String nodeName : path) { + nodes.add(graph.searchNodeByName(nodeName)); + } + tests.add(new Test(nodes, result)); + } + return tests; + } + + private Verification evaluateIsolationResults( List<Test> tests, String source, String destination, + String middlebox) { + Verification v = new Verification(); + boolean isSat = false; + int unsatCounter = 0; + for (Test t : tests) { + v.getTests().add(t); + + if (t.getResult().equals("SAT")) { + isSat = true; + } + else if (t.getResult().equals("UNKNOWN")) { + v.setResult("UNKNWON"); + v.setComment("Isolation property with source '" + source + "', destination '" + destination + + "' and middlebox '" + middlebox + "' is UNKNOWN because although '" + source + + "' cannot reach '" + middlebox + "' in any path from '" + source + "' to '" + + destination + "' which traverses middlebox '" + middlebox + + "' at least one reachability test between '" + source + "' and '" + middlebox + + "' returned UNKNOWN (see below all the paths that have been checked)"); + } + else if (t.getResult().equals("UNSAT")) { + unsatCounter++; + } + } + if (isSat) { + v.setResult("UNSAT"); + v.setComment("Isolation property with source '" + source + "', destination '" + destination + + "' and middlebox '" + middlebox + "' is UNSATISFIED because reachability between '" + + source + "' and '" + middlebox + "' is SATISFIED in at least one path between '" + source + + "' and '" + destination + "' which traverses middlebox '" + middlebox + + "' (see below all the paths that have been checked)"); + } + else if (unsatCounter == tests.size()) { + v.setResult("SAT"); + v.setComment("Isolation property with source '" + source + "', destination '" + destination + + "' and middlebox '" + middlebox + "' is SATISFIED because reachability between '" + source + + "' and '" + middlebox + "' is UNSATISFIED in all paths between '" + source + "' and '" + + destination + "' which traverse middlebox '" + middlebox + + "' (see below all the paths that have been checked)"); + } + return v; + + } + + private void extractPathsWithMiddlebox(List<List<String>> sanitizedPaths, String middleboxName) { + List<List<String>> pathsToBeRemoved = new ArrayList<List<String>>(); + for (List<String> path : sanitizedPaths) { + boolean middleboxFound = false; + for (String node : path) { + if (node.equals(middleboxName)) { + middleboxFound = true; + break; + } + } + if (!middleboxFound) { + pathsToBeRemoved.add(path); + } + } + + for (List<String> path : pathsToBeRemoved) { + sanitizedPaths.remove(path); + } + + } + + private void extractPathsWithoutMiddlebox(List<List<String>> sanitizedPaths, String middleboxName) { + List<List<String>> pathsToBeRemoved = new ArrayList<List<String>>(); + for (List<String> path : sanitizedPaths) { + boolean middleboxFound = false; + for (String node : path) { + if (node.equals(middleboxName)) { + middleboxFound = true; + break; + } + } + if (middleboxFound) { + pathsToBeRemoved.add(path); + } + } + + for (List<String> path : pathsToBeRemoved) { + sanitizedPaths.remove(path); + } + + } + + private Verification traversalVerification(Graph graph, Node sourceNode, Node destinationNode, Node middleboxNode) { + + Paths paths = getPaths(graph, sourceNode, destinationNode); + if (paths.getPath().size() == 0) { + return new Verification("UNSAT", + "There are no available paths between '" + sourceNode.getName() + "' and '" + + destinationNode.getName() + "'"); + } + + List<List<String>> pathsBetweenSourceAndDestination = sanitizePaths(paths); + + printListsOfStrings("Before loops removal", pathsBetweenSourceAndDestination); + + eliminateLoopsInPaths(pathsBetweenSourceAndDestination); + + printListsOfStrings("After loops removal", pathsBetweenSourceAndDestination); + + if (pathsBetweenSourceAndDestination.isEmpty()) { + return new Verification("UNSAT", + "There are no available paths between '" + sourceNode.getName() + "' and '" + + destinationNode.getName() + "'"); + } + + List<Test> tests = extractTestsFromPaths(graph, pathsBetweenSourceAndDestination, "UNKNOWN"); + + List<List<String>> pathsWithMiddlebox = new ArrayList<List<String>>(); + for (List<String> path : pathsBetweenSourceAndDestination) { + pathsWithMiddlebox.add(path); + } + + extractPathsWithMiddlebox(pathsWithMiddlebox, middleboxNode.getName()); + + if (pathsWithMiddlebox.isEmpty()) { + return new Verification("UNSAT", + tests, + "There are no paths between '" + sourceNode.getName() + "' and '" + + destinationNode.getName() + "' which traverse middlebox '" + + middleboxNode.getName() + "'. See below all the available paths"); + } + + printListsOfStrings("Paths with middlebox '" + middleboxNode.getName() + "'", pathsWithMiddlebox); + + File tempDir = null; + + try { + tempDir = createTempDir("traversal"); + } + catch (IOException e) { + throw new InternalServerErrorException("Unable to perform verification: " + e.getMessage()); + } + + String chainsFile = tempDir.getAbsolutePath() + "/chains.json"; + generateChainsFile(graph, pathsWithMiddlebox, chainsFile); + + String configFile = tempDir.getAbsolutePath() + "/config.json"; + generateConfigFile(graph, configFile); + + String traversalScenariosBasename = tempDir.getAbsolutePath() + "/TraversalScenario"; + try{ + generateTestScenarios(chainsFile, configFile, traversalScenariosBasename); + }catch(Exception ex){ + testClassGenerator = generatorFolderForGrpc + "/test_class_generator.py"; + generateTestScenarios(chainsFile, configFile, traversalScenariosBasename); + } + + String traversalTestsBasename = tempDir.getAbsolutePath() + "/TraversalTest"; + try{ + generateTests( pathsWithMiddlebox.size(), + traversalScenariosBasename, + sourceNode.getName(), + destinationNode.getName(), + traversalTestsBasename); + }catch(InternalServerErrorException ex){ + testGenerator = generatorFolderForGrpc + "/test_generator.py"; + generateTests( pathsWithMiddlebox.size(), + traversalScenariosBasename, + sourceNode.getName(), + destinationNode.getName(), + traversalTestsBasename); + } + List<File> sourceFiles = new ArrayList<File>(); + List<File> classFiles = new ArrayList<File>(); + prepareForCompilationAndExecution( pathsWithMiddlebox.size(), + traversalScenariosBasename, + traversalTestsBasename, + sourceFiles, + classFiles); + + compileFiles(sourceFiles, tempDir.getAbsolutePath()); + + tests = runFiles(tempDir.getAbsolutePath(), pathsWithMiddlebox, graph, classFiles); + + for (Test t : tests) { + if (t.getResult().equals("UNSAT")) { + return new Verification("UNSAT", + tests, + "There is at least a path between '" + sourceNode.getName() + "' and '" + + destinationNode.getName() + "' traversing middlebox '" + + middleboxNode.getName() + "' where '" + sourceNode.getName() + + "' cannot reach '" + destinationNode.getName() + + "'. See below the paths that have been checked"); + } + if (t.getResult().equals("UNKNOWN")) { + return new Verification("UNKNOWN", + tests, + "There is at least a path between '" + sourceNode.getName() + "' and '" + + destinationNode.getName() + "' traversing middlebox '" + + middleboxNode.getName() + "' where it is not guaranteed that '" + + sourceNode.getName() + "' can effectively reach '" + + destinationNode.getName() + + "'. See below the paths that have been checked"); + } + } + + extractPathsWithoutMiddlebox(pathsBetweenSourceAndDestination, middleboxNode.getName()); + printListsOfStrings("Paths without middlebox '" + middleboxNode.getName() + "'", pathsBetweenSourceAndDestination); + + if (pathsBetweenSourceAndDestination.isEmpty()) { + return new Verification("SAT", + tests, + "All the paths between node '" + sourceNode.getName() + "' and '" + + destinationNode.getName() + "' traverse middlebox '" + + middleboxNode.getName() + "'"); + } + + tempDir = null; + + try { + tempDir = createTempDir("traversal"); + } + catch (IOException e) { + throw new InternalServerErrorException("Unable to perform verification: " + e.getMessage()); + } + + chainsFile = tempDir.getAbsolutePath() + "/chains.json"; + generateChainsFile(graph, pathsBetweenSourceAndDestination, chainsFile); + + configFile = tempDir.getAbsolutePath() + "/config.json"; + generateConfigFile(graph, configFile); + + traversalScenariosBasename = tempDir.getAbsolutePath() + "/TraversalScenario"; + generateTestScenarios(chainsFile, configFile, traversalScenariosBasename); + + traversalTestsBasename = tempDir.getAbsolutePath() + "/TraversalTest"; + generateTests( pathsBetweenSourceAndDestination.size(), + traversalScenariosBasename, + sourceNode.getName(), + destinationNode.getName(), + traversalTestsBasename); + + sourceFiles = new ArrayList<File>(); + classFiles = new ArrayList<File>(); + prepareForCompilationAndExecution( pathsBetweenSourceAndDestination.size(), + traversalScenariosBasename, + traversalTestsBasename, + sourceFiles, + classFiles); + + compileFiles(sourceFiles, tempDir.getAbsolutePath()); + + tests = runFiles(tempDir.getAbsolutePath(), pathsBetweenSourceAndDestination, graph, classFiles); + + return evaluateTraversalResults(tests, + sourceNode.getName(), + destinationNode.getName(), + middleboxNode.getName()); + + } + + private Verification evaluateTraversalResults( List<Test> tests, String source, String destination, + String middlebox) { + Verification v = new Verification(); + boolean isSat = false; + int unsatCounter = 0; + for (Test t : tests) { + v.getTests().add(t); + + if (t.getResult().equals("SAT")) { + isSat = true; + } + else if (t.getResult().equals("UNKNOWN")) { + v.setResult("UNKNWON"); + v.setComment("There is at least one path from '" + source + "' to '" + destination + + "' that doesn't traverse middlebox '" + middlebox + + "' (see below all the paths that have been checked)"); + } + else if (t.getResult().equals("UNSAT")) { + unsatCounter++; + } + } + if (isSat) { + v.setResult("UNSAT"); + v.setComment("There is at least one path from '" + source + "' to '" + destination + + "' that doesn't traverse middlebox '" + middlebox + + "' (see below all the paths that have been checked)"); + } + else if (unsatCounter == tests.size()) { + v.setResult("SAT"); + v.setComment("The only available paths from '" + source + "' to '" + destination + + "' are those that traverse middlebox '" + middlebox + + "' (see below the alternative paths that have been checked and are unusable)"); + } + return v; + } + + private Verification reachabilityVerification(Graph graph, Node sourceNode, Node destinationNode) { + Paths paths = getPaths(graph, sourceNode, destinationNode); + + if (paths.getPath().size() == 0) { + return new Verification("UNSAT", + "There are no available paths between '" + sourceNode.getName() + "' and '" + + destinationNode.getName() + "'"); + } + + List<List<String>> sanitizedPaths = sanitizePaths(paths); + + printListsOfStrings("Before loops removal", sanitizedPaths); + + eliminateLoopsInPaths(sanitizedPaths); + + printListsOfStrings("After loops removal", sanitizedPaths); + + if (sanitizedPaths.isEmpty()) { + return new Verification("UNSAT", + "There are no available paths between '" + sourceNode.getName() + "' and '" + + destinationNode.getName() + "'"); + } + + File tempDir = null; + + try { + tempDir = createTempDir("reachability"); + } + catch (IOException e) { + throw new InternalServerErrorException("Unable to perform verification: " + e.getMessage()); + } + + String chainsFile = tempDir.getAbsolutePath() + "/chains.json"; + generateChainsFile(graph, sanitizedPaths, chainsFile); + + String configFile = tempDir.getAbsolutePath() + "/config.json"; + generateConfigFile(graph, configFile); + + String reachabilityScenariosBasename = tempDir.getAbsolutePath() + "/ReachabilityScenario"; + try{ + generateTestScenarios(chainsFile, configFile, reachabilityScenariosBasename); + }catch(InternalServerErrorException ex){ + testClassGenerator = generatorFolderForGrpc + "/test_class_generator.py"; + generateTestScenarios(chainsFile, configFile, reachabilityScenariosBasename); + } + + + String reachabilityTestsBasename = tempDir.getAbsolutePath() + "/ReachabilityTest"; + try{ + generateTests( sanitizedPaths.size(), + reachabilityScenariosBasename, + sourceNode.getName(), + destinationNode.getName(), + reachabilityTestsBasename); + }catch(InternalServerErrorException ex){ + testGenerator = generatorFolderForGrpc + "/test_generator.py"; + generateTests( sanitizedPaths.size(), + reachabilityScenariosBasename, + sourceNode.getName(), + destinationNode.getName(), + reachabilityTestsBasename); + } + List<File> sourceFiles = new ArrayList<File>(); + List<File> classFiles = new ArrayList<File>(); + prepareForCompilationAndExecution( sanitizedPaths.size(), + reachabilityScenariosBasename, + reachabilityTestsBasename, + sourceFiles, + classFiles); + + compileFiles(sourceFiles, tempDir.getAbsolutePath()); + + List<Test> tests = runFiles(tempDir.getAbsolutePath(), sanitizedPaths, graph, classFiles); + + return evaluateReachabilityResult(tests, sourceNode.getName(), destinationNode.getName()); + } + + private Verification evaluateReachabilityResult(List<Test> tests, String source, String destination) { + Verification v = new Verification(); + boolean sat = false; + int unsat = 0; + for (Test t : tests) { + v.getTests().add(t); + + if (t.getResult().equals("SAT")) { + sat = true; + } + else if (t.getResult().equals("UNKNOWN")) { + v.setResult("UNKNWON"); + v.setComment("Reachability from '" + source + "' to '" + destination + + "' is unknown. See all the checked paths below"); + } + else if (t.getResult().equals("UNSAT")) { + unsat++; + } + } + if (sat) { + v.setResult("SAT"); + v.setComment("There is at least one path '" + source + "' can use to reach '" + destination + + "'. See all the available paths below"); + } + else if (unsat == tests.size()) { + v.setResult("UNSAT"); + v.setComment("There isn't any path '" + source + "' can use to reach '" + destination + + "'. See all the checked paths below"); + } + return v; + } + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/test/MultiThreadedTestCase.java b/verigraph/src/main/java/it/polito/escape/verify/test/MultiThreadedTestCase.java new file mode 100644 index 0000000..7989b37 --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/test/MultiThreadedTestCase.java @@ -0,0 +1,201 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.test; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Random; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +import javax.ws.rs.core.Response; + +import org.junit.Assert; +import org.junit.Test; + +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import it.polito.escape.verify.client.VerifyClient; +import it.polito.escape.verify.client.VerifyClientException; +import it.polito.escape.verify.model.Configuration; +import it.polito.escape.verify.model.Graph; +import it.polito.escape.verify.model.Node; + +public class MultiThreadedTestCase { + + private void testUpdateGraphStatus(final int threadCount) throws InterruptedException, ExecutionException, JsonParseException, JsonMappingException, IOException, VerifyClientException { + final VerifyClient verifyClient = new VerifyClient("http://localhost:8080/verify/api"); + + Response retrieveGraphResponse = verifyClient.retrieveGraph(1); + String responseString = retrieveGraphResponse.readEntity(String.class); + System.out.println(responseString); + + Graph graph = new ObjectMapper().readValue(responseString, Graph.class); + + UpdateGraph task = new UpdateGraph(verifyClient, 1, graph); + + List<MultiThreadedTestCase.UpdateGraph> tasks = Collections.nCopies(threadCount, task); + ExecutorService executorService = Executors.newFixedThreadPool(threadCount); + + List<Future<Response>> futures = executorService.invokeAll(tasks); + List<Integer> resultList = new ArrayList<Integer>(futures.size()); + + // Check for exceptions + for (Future<Response> future : futures) { + // Throws an exception if an exception was thrown by the task. + resultList.add(future.get().getStatus()); + } + // Validate the dimensions + Assert.assertEquals(threadCount, futures.size()); + List<Integer> expectedList = new ArrayList<Integer>(threadCount); + for (int i = 1; i <= threadCount; i++) { + expectedList.add(200); + } + // Validate expected results + Assert.assertEquals(expectedList, resultList); + } + + private void testUpdateGraph(final int threadCount) throws InterruptedException, ExecutionException, JsonParseException, JsonMappingException, IOException, VerifyClientException { + final VerifyClient verifyClient = new VerifyClient("http://localhost:8080/verify/api"); + + Response retrieveGraphResponse = verifyClient.retrieveGraph(2L); + String responseString = retrieveGraphResponse.readEntity(String.class); + System.out.println(responseString); + + Graph graph = new ObjectMapper().readValue(responseString, Graph.class); + + Node nodeToEdit = graph.getNodes().get(1L); + nodeToEdit.setFunctional_type("endpoint"); + nodeToEdit.setConfiguration(new Configuration(nodeToEdit.getName(), "", new ObjectMapper().createArrayNode())); + + String graphAsString = new ObjectMapper().writeValueAsString(graph); + System.out.println(graphAsString); + + UpdateGraph task = new UpdateGraph(verifyClient, 2, graph); + + List<MultiThreadedTestCase.UpdateGraph> tasks = Collections.nCopies(threadCount, task); + ExecutorService executorService = Executors.newFixedThreadPool(threadCount); + + List<Future<Response>> futures = executorService.invokeAll(tasks); + List<String> resultList = new ArrayList<String>(futures.size()); + + // Check for exceptions + for (Future<Response> future : futures) { + // Throws an exception if an exception was thrown by the task. + resultList.add(future.get().readEntity(String.class)); + } + // Validate dimensions + Assert.assertEquals(threadCount, futures.size()); + + List<String> expectedList = new ArrayList<String>(threadCount); + for (int i = 1; i <= threadCount; i++) { + expectedList.add(graphAsString); + } + // Validate expected results + Assert.assertEquals(expectedList, resultList); + } + + private void testCreateGraphStatus(final int threadCount, Graph graph) throws InterruptedException, ExecutionException, JsonParseException, JsonMappingException, IOException { + final VerifyClient verifyClient = new VerifyClient("http://localhost:8080/verify/api"); + + CreateGraph task = new CreateGraph(verifyClient, graph); + + List<MultiThreadedTestCase.CreateGraph> tasks = Collections.nCopies(threadCount, task); + ExecutorService executorService = Executors.newFixedThreadPool(threadCount); + + List<Future<Response>> futures = executorService.invokeAll(tasks); + List<Integer> resultList = new ArrayList<Integer>(futures.size()); + + // Check for exceptions + for (Future<Response> future : futures) { + // Throws an exception if an exception was thrown by the task. + resultList.add(future.get().getStatus()); + } + // Validate the IDs + Assert.assertEquals(threadCount, futures.size()); + + List<Integer> expectedList = new ArrayList<Integer>(threadCount); + for (int i = 1; i <= threadCount; i++) { + expectedList.add(201); + } + // Validate expected results + Assert.assertEquals(expectedList, resultList); + } + + private int randInt(int min, int max){ + Random rand = new Random(); + int randomNum = rand.nextInt((max - min) + 1) + min; + return randomNum; + } + + @Test + public void updateGraphStatusCheck() throws InterruptedException, ExecutionException, JsonParseException, JsonMappingException, IOException, VerifyClientException { + testUpdateGraphStatus(64); + } + + @Test + public void updateGraphResponseCheck() throws InterruptedException, ExecutionException, JsonParseException, JsonMappingException, IOException, VerifyClientException { + testUpdateGraph(16); + } + + @Test + public void createGraphStatusCheck() throws JsonParseException, JsonMappingException, InterruptedException, ExecutionException, IOException { + Graph graph = new Graph(); + testCreateGraphStatus(8, graph); + } + + class UpdateGraph implements Callable<Response> { + + private VerifyClient verifyClient; + + private int graphId; + + private Graph graph; + + public UpdateGraph(VerifyClient verifyClient, int graphId, Graph graph) { + this.graphId = graphId; + this.graph = graph; + this.verifyClient = verifyClient; + } + + @Override + public Response call() throws Exception { + Thread.sleep(randInt(0,2000)); + Response updateGraphResponse = this.verifyClient.updateGraph(this.graphId, this.graph); + return updateGraphResponse; + } + } + + class CreateGraph implements Callable<Response> { + + private VerifyClient verifyClient; + + private Graph graph; + + public CreateGraph(VerifyClient verifyClient, Graph graph) { + this.graph = graph; + this.verifyClient = verifyClient; + } + + @Override + public Response call() throws Exception { + Thread.sleep(randInt(0,2000)); + return this.verifyClient.createGraph(this.graph); + } + + } +}
\ No newline at end of file diff --git a/verigraph/src/main/java/it/polito/escape/verify/test/Scalability.java b/verigraph/src/main/java/it/polito/escape/verify/test/Scalability.java new file mode 100644 index 0000000..3039ca0 --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/test/Scalability.java @@ -0,0 +1,409 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.test; + +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import it.polito.escape.verify.client.VerifyClient; +import it.polito.escape.verify.client.VerifyClientException; +import it.polito.escape.verify.model.Configuration; +import it.polito.escape.verify.model.Graph; +import it.polito.escape.verify.model.Neighbour; +import it.polito.escape.verify.model.Node; +import it.polito.escape.verify.model.Verification; + +public class Scalability { + + private VerifyClient client = new VerifyClient("http://localhost:8080/verify/api"); + + public static void main(String[] args) throws VerifyClientException { + Scalability s = new Scalability(); + + reachabilityTest(s, 10); + + isolationTest(s,1500); + traversalTest(s,600); + } + + private static void reachabilityTest(Scalability s, int n) throws VerifyClientException { + System.out.printf("Reachability test with N=" + n + ": "); + printTimestamp(); + Graph graph = generateNatScenario(n); + Graph createdGraph = s.client.createGraph(graph).readEntity(Graph.class); + Verification result = s.client.getReachability(createdGraph.getId(), "client", "server"); + System.out.println("Test returned " + result.getResult()); + System.out.printf("Finished reachability test with N=" + n + ": "); + printTimestamp(); + System.out.println(); + } + + private static void isolationTest(Scalability s, int n) throws VerifyClientException { + System.out.printf("Isolation test with N=" + n + ": "); + printTimestamp(); + Graph graph = generateNatScenario(n); + Graph createdGraph = s.client.createGraph(graph).readEntity(Graph.class); + Verification result = s.client.getIsolation(createdGraph.getId(), "client", "server", "firewall"); + System.out.println("Test returned " + result.getResult()); + System.out.printf("Finished isolation test with N=" + n + ": "); + printTimestamp(); + System.out.println(); + } + + private static void traversalTest(Scalability s, int n) throws VerifyClientException { + System.out.printf("Traversal test with N=" + n + ": "); + printTimestamp(); + Graph graph = generateNatScenario(n); + Graph createdGraph = s.client.createGraph(graph).readEntity(Graph.class); + Verification result = s.client.getTraversal(createdGraph.getId(), "client", "server", "firewall"); + System.out.println("Test returned " + result.getResult()); +// System.out.println("Result explanation: " + result.getComment()); + System.out.printf("Finished traversal test with N=" + n + ": "); + printTimestamp(); + System.out.println(); + } + + private static void printTimestamp() { + java.util.Date date= new java.util.Date(); + System.out.println(new Timestamp(date.getTime())); + } + + private static Graph generateNatScenario(int n) { + List<Node> nodes = new ArrayList<Node>(); + + Node client = new Node(); + client.setName("client"); + client.setFunctional_type("endhost"); + ArrayNode clientConfigArray = new ObjectMapper().createArrayNode(); + JsonNode clientConfig = new ObjectMapper().createObjectNode(); + ((ObjectNode)clientConfig).put("url", "www.facebook.com"); + ((ObjectNode)clientConfig).put("body", "word"); + ((ObjectNode)clientConfig).put("destination","server"); + ((ObjectNode)clientConfig).put("protocol", "HTTP_REQUEST"); + clientConfigArray.add(clientConfig); + client.setConfiguration(new Configuration(client.getName(),"", clientConfigArray)); + + Map<Long, Neighbour> clientNeighbours = new HashMap<Long, Neighbour>(); + clientNeighbours.put(1L, new Neighbour(1L, "nat1")); + client.setNeighbours(clientNeighbours ); + //add client to list + nodes.add(client); + + for(int i=0; i< n;i++){ + Node nat = new Node(); + nat.setId(i+1); + nat.setName("nat" + (i+1)); + nat.setFunctional_type("nat"); + ArrayNode configArray = new ObjectMapper().createArrayNode(); + + Map<Long, Neighbour> natNeighbours = new HashMap<Long, Neighbour>(); + + //set left neighbour for each node except the first + if(nat.getId() != 1){ + natNeighbours.put(1L, new Neighbour(1L, "nat" + i)); + configArray.add("client"); + for (int j=1; j <= i; j++){ + configArray.add("nat" + j); + } + } + //first nat: set only client as neighbour and natted node + else{ + natNeighbours.put(1L, new Neighbour(1L, "client")); + configArray.add("client"); + } + //set right neighbour for each node except the last + if(nat.getId() != n){ + natNeighbours.put(2L, new Neighbour(1L, "nat" + (i+2))); + } + //last nat: set server as neighbour + else{ + natNeighbours.put(2L, new Neighbour(1L, "server")); + } + + nat.setNeighbours(natNeighbours); + nat.setConfiguration(new Configuration(nat.getName(),"", configArray)); + + //add nat to list + nodes.add(nat); + } + + Node server = new Node(); + server.setName("server"); + server.setFunctional_type("webserver"); + ArrayNode serverConfigArray = new ObjectMapper().createArrayNode(); + server.setConfiguration(new Configuration(server.getName(),"", serverConfigArray)); + + Map<Long, Neighbour> serverNeighbours = new HashMap<Long, Neighbour>(); + serverNeighbours.put(1L, new Neighbour(1L, "nat" + (n))); + server.setNeighbours(serverNeighbours ); + + //add server to list + nodes.add(server); + + //create graph + Graph g = new Graph(); + Map<Long, Node> graphNodes = new HashMap<Long, Node>(); + long index = 1L; + for (Node node : nodes){ + graphNodes.put(index, node); + index++; + } + g.setNodes(graphNodes); + + return g; + } + + private static Graph generateFirewallScenario(int n) { + List<Node> nodes = new ArrayList<Node>(); + + Node client = new Node(); + client.setName("client"); + client.setFunctional_type("endhost"); + ArrayNode clientConfigArray = new ObjectMapper().createArrayNode(); + JsonNode clientConfig = new ObjectMapper().createObjectNode(); + ((ObjectNode)clientConfig).put("url", "www.facebook.com"); + ((ObjectNode)clientConfig).put("body", "word"); + ((ObjectNode)clientConfig).put("destination","server"); + ((ObjectNode)clientConfig).put("protocol", "HTTP_REQUEST"); + clientConfigArray.add(clientConfig); + client.setConfiguration(new Configuration(client.getName(),"", clientConfigArray)); + + Map<Long, Neighbour> clientNeighbours = new HashMap<Long, Neighbour>(); + clientNeighbours.put(1L, new Neighbour(1L, "firewall1")); + client.setNeighbours(clientNeighbours ); + //add client to list + nodes.add(client); + + for(int i=0; i< n;i++){ + Node firewall = new Node(); + firewall.setId(i+1); + firewall.setName("firewall" + (i+1)); + firewall.setFunctional_type("firewall"); + ArrayNode configArray = new ObjectMapper().createArrayNode(); + + Map<Long, Neighbour> natNeighbours = new HashMap<Long, Neighbour>(); + + //set left neighbour for each node except the first + if(firewall.getId() != 1){ + natNeighbours.put(1L, new Neighbour(1L, "firewall" + i)); + } + //first firewall: set only client as neighbour and natted node + else{ + natNeighbours.put(1L, new Neighbour(1L, "client")); + } + //set right neighbour for each node except the last + if(firewall.getId() != n){ + natNeighbours.put(2L, new Neighbour(1L, "firewall" + (i+2))); + } + //last firewall: set server as neighbour + else{ + natNeighbours.put(2L, new Neighbour(1L, "server")); + } + + firewall.setNeighbours(natNeighbours); + firewall.setConfiguration(new Configuration(firewall.getName(),"", configArray)); + + //add nat to list + nodes.add(firewall); + } + + Node server = new Node(); + server.setName("server"); + server.setFunctional_type("webserver"); + ArrayNode serverConfigArray = new ObjectMapper().createArrayNode(); + server.setConfiguration(new Configuration(server.getName(),"", serverConfigArray)); + + Map<Long, Neighbour> serverNeighbours = new HashMap<Long, Neighbour>(); + serverNeighbours.put(1L, new Neighbour(1L, "firewall" + (n))); + server.setNeighbours(serverNeighbours ); + + //add server to list + nodes.add(server); + + //create graph + Graph g = new Graph(); + Map<Long, Node> graphNodes = new HashMap<Long, Node>(); + long index = 1L; + for (Node node : nodes){ + graphNodes.put(index, node); + index++; + } + g.setNodes(graphNodes); + + return g; + } + + private static Graph generateScenario(int n) { + List<Node> nodes = new ArrayList<Node>(); + + Node firewall = new Node(); + firewall.setName("firewall"); + firewall.setFunctional_type("firewall"); + ArrayNode firewallConfigArray = new ObjectMapper().createArrayNode(); + Map<Long, Neighbour> firewallNeighbours = new HashMap<Long, Neighbour>(); + + for (int i=0; i < n; i++){ + if(i!=0){ + JsonNode firewallEntry = new ObjectMapper().createObjectNode(); + ((ObjectNode) firewallEntry).put("server", "client" + (i+1)); + firewallConfigArray.add(firewallEntry); + } + firewallNeighbours.put(new Long(i+1), new Neighbour(new Long(i+1), "client" + (i+1))); + } + + firewallNeighbours.put(new Long(n+1), new Neighbour(new Long(n+1), "server")); + + firewall.setConfiguration(new Configuration(firewall.getName(),"", firewallConfigArray)); + + + firewall.setNeighbours(firewallNeighbours ); + //add client to list + nodes.add(firewall); + + for(int i=0; i< n;i++){ + Node client = new Node(); + client.setId(i+1); + client.setName("client" + (i+1)); + client.setFunctional_type("endhost"); + ArrayNode clientConfigArray = new ObjectMapper().createArrayNode(); + JsonNode clientConfig = new ObjectMapper().createObjectNode(); + ((ObjectNode)clientConfig).put("url", "www.facebook.com"); + ((ObjectNode)clientConfig).put("body", "word"); + ((ObjectNode)clientConfig).put("destination","server"); + ((ObjectNode)clientConfig).put("protocol", "HTTP_REQUEST"); + clientConfigArray.add(clientConfig); + + Map<Long, Neighbour> clientNeighbours = new HashMap<Long, Neighbour>(); + + clientNeighbours.put(1L, new Neighbour(1L, "firewall")); + + client.setNeighbours(clientNeighbours); + client.setConfiguration(new Configuration(client.getName(),"", clientConfigArray)); + + //add client to list + nodes.add(client); + } + + Node server = new Node(); + server.setName("server"); + server.setFunctional_type("webserver"); + ArrayNode serverConfigArray = new ObjectMapper().createArrayNode(); + server.setConfiguration(new Configuration(server.getName(),"", serverConfigArray)); + + Map<Long, Neighbour> serverNeighbours = new HashMap<Long, Neighbour>(); + serverNeighbours.put(1L, new Neighbour(1L, "firewall")); + server.setNeighbours(serverNeighbours ); + + //add server to list + nodes.add(server); + + //create graph + Graph g = new Graph(); + Map<Long, Node> graphNodes = new HashMap<Long, Node>(); + long index = 1L; + for (Node node : nodes){ + graphNodes.put(index, node); + index++; + } + g.setNodes(graphNodes); + + return g; + } + + private static Graph generateDpiScenario(int n) { + List<Node> nodes = new ArrayList<Node>(); + + Node client = new Node(); + client.setName("client"); + client.setFunctional_type("endhost"); + ArrayNode clientConfigArray = new ObjectMapper().createArrayNode(); + JsonNode clientConfig = new ObjectMapper().createObjectNode(); + ((ObjectNode)clientConfig).put("url", "www.facebook.com"); + ((ObjectNode)clientConfig).put("body", "word"); + ((ObjectNode)clientConfig).put("destination","server"); + ((ObjectNode)clientConfig).put("protocol", "HTTP_REQUEST"); + clientConfigArray.add(clientConfig); + client.setConfiguration(new Configuration(client.getName(),"", clientConfigArray)); + + Map<Long, Neighbour> clientNeighbours = new HashMap<Long, Neighbour>(); + clientNeighbours.put(1L, new Neighbour(1L, "dpi1")); + client.setNeighbours(clientNeighbours ); + //add client to list + nodes.add(client); + + for(int i=0; i< n;i++){ + Node dpi = new Node(); + dpi.setId(i+1); + dpi.setName("dpi" + (i+1)); + dpi.setFunctional_type("dpi"); + ArrayNode configArray = new ObjectMapper().createArrayNode(); + configArray.add("drug"); + + Map<Long, Neighbour> natNeighbours = new HashMap<Long, Neighbour>(); + + //set left neighbour for each node except the first + if(dpi.getId() != 1){ + natNeighbours.put(1L, new Neighbour(1L, "dpi" + i)); + } + //first firewall: set only client as neighbour and natted node + else{ + natNeighbours.put(1L, new Neighbour(1L, "client")); + } + //set right neighbour for each node except the last + if(dpi.getId() != n){ + natNeighbours.put(2L, new Neighbour(1L, "dpi" + (i+2))); + } + //last firewall: set server as neighbour + else{ + natNeighbours.put(2L, new Neighbour(1L, "server")); + } + + dpi.setNeighbours(natNeighbours); + dpi.setConfiguration(new Configuration(dpi.getName(),"", configArray)); + + //add nat to list + nodes.add(dpi); + } + + Node server = new Node(); + server.setName("server"); + server.setFunctional_type("webserver"); + ArrayNode serverConfigArray = new ObjectMapper().createArrayNode(); + server.setConfiguration(new Configuration(server.getName(),"", serverConfigArray)); + + Map<Long, Neighbour> serverNeighbours = new HashMap<Long, Neighbour>(); + serverNeighbours.put(1L, new Neighbour(1L, "dpi" + (n))); + server.setNeighbours(serverNeighbours ); + + //add server to list + nodes.add(server); + + //create graph + Graph g = new Graph(); + Map<Long, Node> graphNodes = new HashMap<Long, Node>(); + long index = 1L; + for (Node node : nodes){ + graphNodes.put(index, node); + index++; + } + g.setNodes(graphNodes); + + return g; + } + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/test/TestCase.java b/verigraph/src/main/java/it/polito/escape/verify/test/TestCase.java new file mode 100644 index 0000000..a4c85ab --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/test/TestCase.java @@ -0,0 +1,161 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.test; + +import java.util.HashMap; +import java.util.Map; + +import com.fasterxml.jackson.annotation.JsonAnyGetter; +import com.fasterxml.jackson.annotation.JsonAnySetter; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + +import it.polito.escape.verify.model.Graph; + +@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonPropertyOrder({ "id", "name", "description", "policy_url_parameters", "result", "graph" }) +public class TestCase { + + @JsonProperty("id") + private Integer id; + + @JsonProperty("name") + private String name; + + @JsonProperty("description") + private String description; + + @JsonProperty("policy_url_parameters") + private String policyUrlParameters; + + @JsonProperty("result") + private String result; + + @JsonProperty("graph") + private Graph graph; + + @JsonIgnore + private Map<String, Object> additionalProperties = new HashMap<String, Object>(); + + /** + * @return The id + */ + @JsonProperty("id") + public Integer getId() { + return id; + } + + /** + * @param id + * The id + */ + @JsonProperty("id") + public void setId(Integer id) { + this.id = id; + } + + /** + * @return The name + */ + @JsonProperty("name") + public String getName() { + return name; + } + + /** + * @param name + * The name + */ + @JsonProperty("name") + public void setName(String name) { + this.name = name; + } + + /** + * @return The description + */ + @JsonProperty("description") + public String getDescription() { + return description; + } + + /** + * @param description + * The description + */ + @JsonProperty("description") + public void setDescription(String description) { + this.description = description; + } + + /** + * @return The policyUrlParameters + */ + @JsonProperty("policy_url_parameters") + public String getPolicyUrlParameters() { + return policyUrlParameters; + } + + /** + * @param policyUrlParameters + * The policy_url_parameters + */ + @JsonProperty("policy_url_parameters") + public void setPolicyUrlParameters(String policyUrlParameters) { + this.policyUrlParameters = policyUrlParameters; + } + + /** + * @return The result + */ + @JsonProperty("result") + public String getResult() { + return result; + } + + /** + * @param result + * The result + */ + @JsonProperty("result") + public void setResult(String result) { + this.result = result; + } + + /** + * @return The graph + */ + @JsonProperty("graph") + public Graph getGraph() { + return graph; + } + + /** + * @param graph + * The graph + */ + @JsonProperty("graph") + public void setGraph(Graph graph) { + this.graph = graph; + } + + @JsonAnyGetter + public Map<String, Object> getAdditionalProperties() { + return this.additionalProperties; + } + + @JsonAnySetter + public void setAdditionalProperty(String name, Object value) { + this.additionalProperties.put(name, value); + } + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/test/TestExecutionException.java b/verigraph/src/main/java/it/polito/escape/verify/test/TestExecutionException.java new file mode 100644 index 0000000..8babe7b --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/test/TestExecutionException.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.test; + + +public class TestExecutionException extends Exception{ + + /** + * + */ + private static final long serialVersionUID = 4749065055436886197L; + + public TestExecutionException(String message){ + super(message); + } + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/test/Tester.java b/verigraph/src/main/java/it/polito/escape/verify/test/Tester.java new file mode 100644 index 0000000..4b85e1e --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/test/Tester.java @@ -0,0 +1,220 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.test; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; + +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.ResponseProcessingException; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.Response; + +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.fge.jsonschema.core.exceptions.ProcessingException; +import com.github.fge.jsonschema.main.JsonSchema; + +import it.polito.escape.verify.client.VerifyClient; +import it.polito.escape.verify.client.VerifyClientException; +import it.polito.escape.verify.model.Graph; +import it.polito.escape.verify.model.Verification; +import it.polito.escape.verify.service.ValidationUtils; + +public class Tester { + + private File schema; + + private List<File> testFiles = new ArrayList<File>(); + + private List<TestCase> testCases = new ArrayList<TestCase>(); + + private String target; + + private VerifyClient verifyClient; + + public Tester(String target, File schema, File folder) throws JsonParseException, JsonMappingException, IOException, + Exception { + init(target, schema, folder); + } + + private void init(String target, File schema, File folder) throws JsonParseException, JsonMappingException, + IOException, Exception { + this.target = target; + this.verifyClient = new VerifyClient(this.target); + this.schema = schema; + this.testFiles = getTests(folder); + this.testCases = getTestCases(this.testFiles); + } + + public List<File> getTests(File folder) { + List<File> filesList = new ArrayList<File>(); + + System.out.println("Test folder set to '" + folder.getAbsolutePath() + "'"); + + File[] files = folder.listFiles(new FilenameFilter() { + + @Override + public boolean accept(File dir, String name) { + return name.endsWith(".json"); + } + }); + + for (File f : files) { + filesList.add(f); + System.out.println("File '" + f.getName() + "' added to test files"); + } + + return filesList; + } + + public List<TestCase> getTestCases(List<File> files) throws JsonParseException, JsonMappingException, IOException, + Exception { + List<TestCase> testCases = new ArrayList<TestCase>(); + + for (File file : files) { + validateTestFile(file); + try { + TestCase tc = new ObjectMapper().readValue(file, TestCase.class); + testCases.add(tc); + } + catch (Exception e) { + throw e; + } + } + + return testCases; + } + + private void runTestCases() throws VerifyClientException, TestExecutionException { + int counter = 0; + for (TestCase tc : this.testCases) { + String result = runTestCase(tc); + if (!result.equals(tc.getResult())) + throw new TestExecutionException("Error running test given in file '" + this.testFiles.get(counter).getName() + + "'. Test returned '" + result + "' instead of '" + tc.getResult() + "'."); + else + System.out.println("Test given in file '" + this.testFiles.get(counter).getName() + "' returned '" + + result + "' as expected"); + counter++; + } + System.out.println("All tests PASSED"); + } + + private String runTestCase(TestCase tc) throws VerifyClientException, TestExecutionException{ + Client client = ClientBuilder.newClient(); + + Graph graph = tc.getGraph(); + Response response = null; + try{ + response = this.verifyClient.createGraph(graph); + } + catch(ResponseProcessingException e){ + throw new TestExecutionException("Response processing has failed: " + e.getResponse().readEntity(String.class)); + } + catch(javax.ws.rs.ProcessingException e){ + throw new TestExecutionException("HTTP request failed"); + } + Graph createdGraph = response.readEntity(Graph.class); + String urlParams = tc.getPolicyUrlParameters(); + WebTarget target = client.target(this.target + "/graphs/" + createdGraph.getId() + "/policy" + urlParams); + + response = target.request().get(); + Verification verification = response.readEntity(Verification.class); + return verification.getResult(); + } + + public void validateTestFile(File testFile) throws Exception { + JsonSchema schemaNode = null; + try { + schemaNode = ValidationUtils.getSchemaNode(schema); + } + catch (IOException e) { + throw new Exception("Unable to load '" + schema.getAbsolutePath() + "' schema file"); + } + catch (ProcessingException e) { + throw new Exception("Unable to resolve '" + schema.getAbsolutePath() + "' schema file as a schema node"); + } + + JsonNode jsonNode; + try { + jsonNode = ValidationUtils.getJsonNode(testFile); + } + catch (IOException e) { + throw new Exception("Unable to load '" + testFile.getAbsolutePath() + "' as a json node"); + } + + try { + ValidationUtils.validateJson(schemaNode, jsonNode); + } + catch (ProcessingException e) { + throw new Exception("There were errors in the validation of file '" + testFile.getAbsolutePath() + + "' against the json schema '" + schema.getAbsolutePath() + "': " + e.getMessage()); + + } + } + + public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException, + VerifyClientException, Exception { + String folderName = System.getProperty("user.dir") + "/tester/testcases"; + File folder = new File(folderName); + if (!folder.exists()) { + BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); + String s; + do{ + System.out.println("Please enter the testcases folder path: "); + s = in.readLine(); + if (isValidpath(s)){ + folder = new File(s); + break; + } + }while (s != null && s.length() != 0); + if(s == null) + System.exit(0); + } + String schemaName = System.getProperty("user.dir") + "/tester/testcase_schema.json"; + File schema = new File(schemaName); + if (!schema.exists()) { + BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); + String s; + do{ + System.out.println("Please enter the full path of 'testcase_schema.json': "); + s = in.readLine(); + if (isValidpath(s)){ + folder = new File(s); + break; + } + }while (s != null && s.length() != 0); + if(s == null) + System.exit(0); + } + + Tester tester = new Tester("http://localhost:8080/verify/api", schema, folder); + + tester.runTestCases(); + + } + + private static boolean isValidpath(String s) { + if (s==null) + return false; + File file = new File(s); + return file.exists(); + } + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/validation/DpiValidator.java b/verigraph/src/main/java/it/polito/escape/verify/validation/DpiValidator.java new file mode 100644 index 0000000..2666755 --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/validation/DpiValidator.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.validation; + +import com.fasterxml.jackson.databind.JsonNode; + +import it.polito.escape.verify.model.Configuration; +import it.polito.escape.verify.model.Graph; +import it.polito.escape.verify.model.Node; +import it.polito.escape.verify.validation.exception.ValidationException; + +public class DpiValidator implements ValidationInterface { + + public DpiValidator(){ + + } + + private void validateKey(String key) throws ValidationException { + if (!key.matches("\\w+")) + throw new ValidationException("'" + key + "' is not a valid configuration string for a 'dpi'"); + } + + @Override + public void validate(Graph graph, Node node, Configuration configuration) throws ValidationException { + + JsonNode conf = configuration.getConfiguration(); + + if (!conf.isArray()) { + throw new ValidationException("Configuration of a 'dpi' must be an array"); + } + for (JsonNode key : conf) { + if (!key.isTextual()) + throw new ValidationException("Configuration of a 'dpi' must be an array of strings"); + validateKey(key.asText()); + } + } + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/validation/EndhostValidator.java b/verigraph/src/main/java/it/polito/escape/verify/validation/EndhostValidator.java new file mode 100644 index 0000000..3d9eb75 --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/validation/EndhostValidator.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.validation; + +import it.polito.escape.verify.model.Configuration; +import it.polito.escape.verify.model.Graph; +import it.polito.escape.verify.model.Node; +import it.polito.escape.verify.validation.exception.ValidationException; + + +public class EndhostValidator implements ValidationInterface { + + @Override + public void validate(Graph graph, Node node, Configuration configuration) throws ValidationException { + + } + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/validation/ValidationInterface.java b/verigraph/src/main/java/it/polito/escape/verify/validation/ValidationInterface.java new file mode 100644 index 0000000..25608dd --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/validation/ValidationInterface.java @@ -0,0 +1,21 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.validation; + +import it.polito.escape.verify.model.Configuration; +import it.polito.escape.verify.model.Graph; +import it.polito.escape.verify.model.Node; +import it.polito.escape.verify.validation.exception.ValidationException; + +public interface ValidationInterface { + + void validate(Graph graph, Node node, Configuration configuration) throws ValidationException; + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/validation/VpnaccessValidator.java b/verigraph/src/main/java/it/polito/escape/verify/validation/VpnaccessValidator.java new file mode 100644 index 0000000..6abd603 --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/validation/VpnaccessValidator.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.validation; + +import com.fasterxml.jackson.databind.JsonNode; + +import it.polito.escape.verify.model.Configuration; +import it.polito.escape.verify.model.Graph; +import it.polito.escape.verify.model.Node; +import it.polito.escape.verify.validation.exception.ValidationException; + +public class VpnaccessValidator implements ValidationInterface { + + @Override + public void validate(Graph graph, Node node, Configuration configuration) throws ValidationException { + JsonNode configurationNode = configuration.getConfiguration(); + + if (!configurationNode.isArray()) + throw new ValidationException("configuration must be an array"); + + for (JsonNode object : configurationNode) { + JsonNode vpnexit = object.get("vpnexit"); + if (!vpnexit.isTextual()) + throw new ValidationException("value corresponding to the key 'vpnexit' must be a string"); + validateObject(graph, node, vpnexit.asText()); + } + + } + + private void validateObject(Graph g, Node node, String field) throws ValidationException { + boolean isValid = false; + for (Node n : g.getNodes().values()) { + if ((n.getFunctional_type().equals("vpnexit")) && (n.getName().equals(field))) + isValid = true; + } + + if (!isValid) + throw new ValidationException("'" + field + "' is not a valid value for the configuration of a type '" + + node.getFunctional_type() + + "'. Please use the name of an existing node of type 'vpnexit'."); + + } + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/validation/VpnexitValidator.java b/verigraph/src/main/java/it/polito/escape/verify/validation/VpnexitValidator.java new file mode 100644 index 0000000..782e124 --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/validation/VpnexitValidator.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.validation; + +import com.fasterxml.jackson.databind.JsonNode; + +import it.polito.escape.verify.model.Configuration; +import it.polito.escape.verify.model.Graph; +import it.polito.escape.verify.model.Node; +import it.polito.escape.verify.validation.exception.ValidationException; + +public class VpnexitValidator implements ValidationInterface { + + @Override + public void validate(Graph graph, Node node, Configuration configuration) throws ValidationException { + JsonNode configurationNode = configuration.getConfiguration(); + + if (!configurationNode.isArray()) + throw new ValidationException("configuration must be an array"); + + for (JsonNode object : configurationNode) { + JsonNode vpnexit = object.get("vpnaccess"); + if (!vpnexit.isTextual()) + throw new ValidationException("value corresponding to the key 'vpnaccess' must be a string"); + validateObject(graph, node, vpnexit.asText()); + } + + } + + private void validateObject(Graph g, Node node, String field) throws ValidationException { + boolean isValid = false; + for (Node n : g.getNodes().values()) { + if ((n.getFunctional_type().equals("vpnaccess")) && (n.getName().equals(field))) + isValid = true; + } + + if (!isValid) + throw new ValidationException("'" + field + "' is not a valid value for the configuration of a type '" + + node.getFunctional_type() + + "'. Please use the name of an existing node of type 'vpnaccess'."); + + } + +} diff --git a/verigraph/src/main/java/it/polito/escape/verify/validation/exception/ValidationException.java b/verigraph/src/main/java/it/polito/escape/verify/validation/exception/ValidationException.java new file mode 100644 index 0000000..8b94748 --- /dev/null +++ b/verigraph/src/main/java/it/polito/escape/verify/validation/exception/ValidationException.java @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.escape.verify.validation.exception; + + +public class ValidationException extends Exception { + + /** + * + */ + private static final long serialVersionUID = -8251271078519549101L; + + private String message; + + public ValidationException(String message){ +// super(message); + this.message = message; + } + + @Override + public String getMessage() { + return this.message; + } +} diff --git a/verigraph/src/main/java/it/polito/grpc/Client.java b/verigraph/src/main/java/it/polito/grpc/Client.java new file mode 100644 index 0000000..adc16da --- /dev/null +++ b/verigraph/src/main/java/it/polito/grpc/Client.java @@ -0,0 +1,550 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.grpc; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import com.google.protobuf.Message; + +import io.grpc.ManagedChannel; +import io.grpc.ManagedChannelBuilder; +import io.grpc.StatusRuntimeException; +import io.grpc.verigraph.ConfigurationGrpc; +import io.grpc.verigraph.GetRequest; +import io.grpc.verigraph.GraphGrpc; +import io.grpc.verigraph.NeighbourGrpc; +import io.grpc.verigraph.NewGraph; +import io.grpc.verigraph.NewNeighbour; +import io.grpc.verigraph.NewNode; +import io.grpc.verigraph.NodeGrpc; +import io.grpc.verigraph.NodeGrpc.FunctionalType; +import io.grpc.verigraph.Policy; +import io.grpc.verigraph.Policy.PolicyType; +import io.grpc.verigraph.RequestID; +import io.grpc.verigraph.Status; +import io.grpc.verigraph.TestGrpc; +import io.grpc.verigraph.VerificationGrpc; +import io.grpc.verigraph.VerigraphGrpc; + +public class Client { + + private final ManagedChannel channel; + private final VerigraphGrpc.VerigraphBlockingStub blockingStub; + + public Client(String host, int port) { + this(ManagedChannelBuilder.forAddress(host, port).usePlaintext(true)); + } + + /** Construct client for accessing RouteGuide server using the existing channel. */ + public Client(ManagedChannelBuilder<?> channelBuilder) { + channel = channelBuilder.build(); + blockingStub = VerigraphGrpc.newBlockingStub(channel); + } + + /** Get array of graphs */ + public List<GraphGrpc> getGraphs() { + List<GraphGrpc> graphsRecveived = new ArrayList<GraphGrpc>(); + GetRequest request = GetRequest.newBuilder().build(); + Iterator<GraphGrpc> graphs; + try { + graphs = blockingStub.getGraphs(request); + while (graphs.hasNext()) { + GraphGrpc graph = graphs.next(); + System.out.println("Graph id : "+graph.getId()); + if(graph.getErrorMessage().equals("")){ + System.out.println("Node id : "+graph.getId()); + graphsRecveived.add(graph); + }else{ + System.out.println("Error : " + graph.getErrorMessage()); + return graphsRecveived; + } + } + } catch (StatusRuntimeException ex) { + System.err.println("RPC failed: " + ex.getStatus()); + } + return graphsRecveived; + } + + /** Create new Graph */ + public NewGraph createGraph(GraphGrpc gr) { + NewGraph response; + try { + response = blockingStub.createGraph(gr); + if(response.getSuccess()){ + System.out.println("Successful operation "); + }else{ + System.out.println("Unsuccessful operation: " + response.getErrorMessage()); + } + } catch (StatusRuntimeException e) { + System.err.println("RPC failed: " + e.getStatus()); + return NewGraph.newBuilder().setSuccess(false).build(); + } + return response; + } + + /** Delete a Graph */ + public boolean deleteGraph(long idGraph) { + + RequestID id = RequestID.newBuilder().setIdGraph(idGraph).build(); + Status response; + try { + response = blockingStub.deleteGraph(id); + if(response.getSuccess()){ + System.out.println("Successful operation "); + return true; + }else{ + System.out.println("Unsuccessful operation: " + response.getErrorMessage()); + } + } catch (StatusRuntimeException e) { + System.err.println("RPC failed: " + e.getStatus()); + } + return false; + } + + /** Edits a single graph */ + public NewGraph updateGraph(long idGraph, GraphGrpc newGraph) { + + GraphGrpc gr = GraphGrpc.newBuilder(newGraph).setId(idGraph).build(); + NewGraph response; + try { + response = blockingStub.updateGraph(gr); + if(response.getSuccess()){ + System.out.println("Successful operation "); + }else{ + System.out.println("Unsuccessful operation: " + response.getErrorMessage()); + } + } catch (StatusRuntimeException e) { + System.err.println("RPC failed: " + e.getStatus()); + return NewGraph.newBuilder().setSuccess(false).build(); + } + return response; + } + + /** Get a single graph*/ + public GraphGrpc getGraph(long idGraph) { + + RequestID request = RequestID.newBuilder().setIdGraph(idGraph).build() ; + try { + GraphGrpc graph = blockingStub.getGraph(request); + if(!graph.getErrorMessage().equals("")){ + System.out.println("Error in operation: " + graph.getErrorMessage()); + } + return graph; + } catch (StatusRuntimeException ex) { + System.err.println("RPC failed: " + ex.getStatus()); + return null; + } + } + + /** Verify a given policy*/ + public VerificationGrpc verify(Policy policy) { + + VerificationGrpc response; + try { + response = blockingStub.verifyPolicy(policy); + if(!response.getErrorMessage().equals("")){ + System.out.println("Error in operation: " + response.getErrorMessage()); + } + System.out.println("Result : "+response.getResult()); + System.out.println("Comment : "+response.getComment()); + //uncomment if you want to print the paths + /*for(TestGrpc test:response.getTestList()){ + System.out.println("Test : "+test.getResult()+". Traversed nodes:"); + for(NodeGrpc node:test.getNodeList()){ + //prints only the name + System.out.println("Node "+node.getName()); + } + }*/ + return response; + } catch (StatusRuntimeException e) { + System.err.println("RPC failed: " + e.getStatus()); + return null; + } + } + + /*Node part*/ + + /** Get array of nodes */ + public List<NodeGrpc> getNodes(long idGraph) { + List<NodeGrpc> nodesReceived = new ArrayList<NodeGrpc>(); + RequestID request = RequestID.newBuilder().setIdGraph(idGraph).build() ; + Iterator<NodeGrpc> nodes; + try { + nodes = blockingStub.getNodes(request); + while (nodes.hasNext()) { + NodeGrpc node = nodes.next(); + if(node.getErrorMessage().equals("")){ + System.out.println("Node id : "+node.getId()); + nodesReceived.add(node); + }else{ + System.out.println("Error : " + node.getErrorMessage()); + return nodesReceived; + } + } + } catch (StatusRuntimeException ex) { + System.err.println("RPC failed: " + ex.getStatus()); + } + return nodesReceived; + } + + /** Create new Node */ + public NewNode createNode(NodeGrpc node, long idGraph) { + + NewNode response; + try { + NodeGrpc n = NodeGrpc.newBuilder(node).setIdGraph(idGraph).build(); + response = blockingStub.createNode(n); + if(response.getSuccess()){ + System.out.println("Successful operation "); + }else{ + System.out.println("Unsuccessful operation: " + response.getErrorMessage()); + } + } catch (StatusRuntimeException e) { + System.err.println("RPC failed: " + e.getStatus()); + return NewNode.newBuilder().setSuccess(false).build(); + } + return response; + } + + /** Delete a Node */ + public boolean deleteNode(long idGraph, long idNode) { + + RequestID id = RequestID.newBuilder().setIdGraph(idGraph).setIdNode(idNode).build(); + Status response; + try { + response = blockingStub.deleteNode(id); + if(response.getSuccess()){ + System.out.println("Successful operation "); + return true; + }else{ + System.out.println("Unsuccessful operation: " + response.getErrorMessage()); + } + } catch (StatusRuntimeException e) { + System.err.println("RPC failed: " + e.getStatus()); + } + return false; + } + + /** Edits a single Node */ + public NewNode updateNode(long idGraph, long idNode, NodeGrpc node) { + + NodeGrpc nu = NodeGrpc.newBuilder(node).setIdGraph(idGraph).setId(idNode).build(); + NewNode response; + try { + response = blockingStub.updateNode(nu); + if(response.getSuccess()){ + System.out.println("Successful operation "); + }else{ + System.out.println("Unsuccessful operation: " + response.getErrorMessage()); + } + } catch (StatusRuntimeException e) { + System.err.println("RPC failed: " + e.getStatus()); + return NewNode.newBuilder().setSuccess(false).build(); + } + return response; + } + + /** Get a single Node*/ + public NodeGrpc getNode(long idGraph, long idNode) { + + RequestID request = RequestID.newBuilder().setIdGraph(idGraph).setIdNode(idNode).build() ; + try { + NodeGrpc node = blockingStub.getNode(request); + if(!node.getErrorMessage().equals("")){ + System.out.println("Error in operation: " + node.getErrorMessage()); + } + return node; + } catch (StatusRuntimeException ex) { + System.err.println("RPC failed: " + ex.getStatus()); + return null; + } + } + + /** Configure a single Node*/ + public boolean configureNode(long idGraph, long idNode, ConfigurationGrpc configuration) { + + try { + ConfigurationGrpc request = ConfigurationGrpc.newBuilder(configuration) + .setIdGraph(idGraph).setIdNode(idNode).build() ; + + Status response = blockingStub.configureNode(request); + if(response.getSuccess()){ + System.out.println("Successful operation "); + return true; + }else{ + System.out.println("Unsuccessful operation: " + response.getErrorMessage()); + } + } catch (StatusRuntimeException e) { + System.err.println("RPC failed: " + e.getStatus()); + } + return false; + } + + /*Neighbour part*/ + + /** Get array of neighbours */ + public List<NeighbourGrpc> getNeighbours(long idGraph, long idNode) { + + List<NeighbourGrpc> neighboursReceived = new ArrayList<NeighbourGrpc>(); + RequestID request = RequestID.newBuilder().setIdGraph(idGraph).setIdNode(idNode).build() ; + Iterator<NeighbourGrpc> neighbours; + try { + neighbours = blockingStub.getNeighbours(request); + while (neighbours.hasNext()) { + NeighbourGrpc neighbour = neighbours.next(); + if(neighbour.getErrorMessage().equals("")){ + System.out.println("Neighbour id : "+neighbour.getId()); + neighboursReceived.add(neighbour); + }else{ + System.out.println("Error : " + neighbour.getErrorMessage()); + return neighboursReceived; + } + } + } catch (StatusRuntimeException ex) { + System.err.println("RPC failed: " + ex.getStatus()); + } + return neighboursReceived; + } + + /** Create new Neighbour */ + public NewNeighbour createNeighbour(NeighbourGrpc neighbour, long idGraph, long idNode) { + + NewNeighbour response; + try { + NeighbourGrpc n = NeighbourGrpc.newBuilder(neighbour).setIdGraph(idGraph) + .setIdNode(idNode).build(); + response = blockingStub.createNeighbour(n); + if(response.getSuccess()){ + System.out.println("Successful operation "); + }else{ + System.out.println("Unsuccessful operation: " + response.getErrorMessage()); + } + } catch (StatusRuntimeException e) { + System.err.println("RPC failed: " + e.getStatus()); + return NewNeighbour.newBuilder().setSuccess(false).build(); + } + return response; + } + + /** Delete a Neighbour */ + public boolean deleteNeighbour(long idGraph, long idNode, long idNeighbour) { + + RequestID id = RequestID.newBuilder().setIdGraph(idGraph).setIdNode(idNode).setIdNeighbour(idNeighbour).build(); + Status response; + try { + response = blockingStub.deleteNeighbour(id); + if(response.getSuccess()){ + System.out.println("Successful operation "); + return true; + }else{ + System.out.println("Unsuccesful operation: " + response.getErrorMessage()); + } + } catch (StatusRuntimeException e) { + System.err.println("RPC failed: " + e.getStatus()); + } + return false; + } + + /** Edits a single Neighbour */ + public NewNeighbour updateNeighbour(long idGraph, long idNode, long idNeighbour, NeighbourGrpc neighbour) { + + NeighbourGrpc nu = NeighbourGrpc.newBuilder(neighbour).setIdGraph(idGraph).setIdNode(idNode) + .setId(idNeighbour).build(); + NewNeighbour response; + try { + response = blockingStub.updateNeighbour(nu); + if(response.getSuccess()){ + System.out.println("Successful operation "); + }else{ + System.out.println("Unsuccessful operation: " + response.getErrorMessage()); + } + } catch (StatusRuntimeException e) { + System.err.println("RPC failed: " + e.getStatus()); + return NewNeighbour.newBuilder().setSuccess(false).build(); + } + return response; + } + + /** Get a single Neighbour*/ + public NeighbourGrpc getNeighbour(long idGraph, long idNode, long idNeighbour) { + + RequestID request = RequestID.newBuilder().setIdGraph(idGraph).setIdNode(idNode).setIdNeighbour(idNeighbour).build() ; + try { + NeighbourGrpc neighbour = blockingStub.getNeighbour(request); + if(!neighbour.getErrorMessage().equals("")){ + System.out.println("Error in operation: " + neighbour.getErrorMessage()); + } + return neighbour; + } catch (StatusRuntimeException ex) { + System.err.println("RPC failed: " + ex.getStatus()); + return null; + } + } + + public void shutdown() throws InterruptedException { + channel.shutdown().awaitTermination(5, TimeUnit.SECONDS); + } + + /** Test on the Server. */ + public static void main(String[] args) throws Exception { + + List<Long> listGraph = new ArrayList<Long>(); //list of ID + + Client client = new Client("localhost" , 50051); + try { + NodeGrpc node1 = createNodeGrpc("Node1", "endhost", null, null); + List<NeighbourGrpc> neighbours = new ArrayList<NeighbourGrpc>(); + NeighbourGrpc nb = createNeighbourGrpc("Node1"); + neighbours.add(nb); + NodeGrpc node2 = createNodeGrpc("Node2", "endpoint", neighbours, null); + List<NodeGrpc> nodes = new ArrayList<NodeGrpc>(); + nodes.add(node1); + nodes.add(node2); + + GraphGrpc graph = createGraphGrpc(nodes); + + NewGraph createdGraph = client.createGraph(graph); + if(createdGraph.getSuccess() == true){ + listGraph.add(createdGraph.getGraph().getId()); + System.out.println("Created graph with id :"+ createdGraph.getGraph().getId()); + } + + client.getGraphs(); + } catch(Exception ex){ + System.out.println("Error: " + ex.getMessage()); + ex.printStackTrace(); + }finally { + client.shutdown(); + } + } + + public static NeighbourGrpc createNeighbourGrpc(String name){ + return NeighbourGrpc.newBuilder().setName(name).build(); + } + + public static NodeGrpc createNodeGrpc(String name, String functionalType, List<NeighbourGrpc> neighbours, ConfigurationGrpc conf) throws Exception{ + NodeGrpc.Builder nb = NodeGrpc.newBuilder(); + + if(name != null) + nb.setName(name); + else + throw new Exception("Node must have a name"); + + if(functionalType != null) + nb.setFunctionalType(FunctionalType.valueOf(functionalType)); + else + throw new Exception("Node must have a functional type"); + + if( neighbours!= null){ + for(NeighbourGrpc value:neighbours) + nb.addNeighbour(value); + } + if(conf == null){ + try{ + conf = createConfigurationGrpc(null, null, null, null); + }catch(Exception e){ + throw new Exception(e.getMessage()); + } + } + nb.setConfiguration(conf); + return nb.build(); + } + + public static GraphGrpc createGraphGrpc(List<NodeGrpc> nodes){ + GraphGrpc.Builder gb = GraphGrpc.newBuilder(); + if(nodes != null){ + for(NodeGrpc value:nodes) + gb.addNode(value); + } + return gb.build(); + } + + public static Policy createPolicy(String src, String dst, String type, String middlebox, long idGraph) throws IllegalArgumentException{ + if(!validMiddlebox(type, middlebox)) + throw new IllegalArgumentException("Not valid middlebox valid with this type"); + Policy.Builder policy = Policy.newBuilder(); + policy.setIdGraph(idGraph); + if(src != null) + policy.setSource(src); + else{ + throw new IllegalArgumentException("Please insert source field"); + } + if(dst != null) + policy.setDestination(dst); + else{ + throw new IllegalArgumentException("Please insert destination field"); + } + if(type != null) + policy.setType(PolicyType.valueOf(type)); + if(middlebox != null) + policy.setMiddlebox(middlebox); + return policy.build(); + } + + public static ConfigurationGrpc createConfigurationGrpc(Map<String,String> parameters, List<String> lists, String id, String description) throws Exception{ + ConfigurationGrpc.Builder cb = ConfigurationGrpc.newBuilder(); + StringBuilder sb = new StringBuilder("["); + if(parameters != null && lists == null){ + int i = 0; + sb.append("{"); + for (String key: parameters.keySet()) { + sb.append("\""); + sb.append(key); + sb.append("\":\""); + sb.append(parameters.get(key)); + sb.append("\""); + if((i+1)<parameters.keySet().size()){ + sb.append(", "); + } + i++; + } + sb.append("}"); + } + else if(parameters == null && lists != null){ + int i = 0; + for (String value: lists) { + sb.append("\""); + sb.append(value); + sb.append("\""); + if((i+1)<lists.size()){ + sb.append(", "); + } + i++; + } + } + else if(parameters != null && lists != null){ + throw new Exception("Error, configuration must contains or a sequence name:value or sequence" + + "of string, but not both"); + } + sb.append("]"); + cb.setConfiguration(sb.toString()); + if(id != null) + cb.setId(id); + if(description != null) + cb.setDescription(description); + return cb.build(); + } + + private static boolean validMiddlebox(String type, String middlebox) { + if(type == null) + return false; + if(type.equals("reachability") && (middlebox == null || middlebox.equals(""))) + return true; + if(type.equals("isolation") && !(middlebox == null || middlebox.equals(""))) + return true; + if(type.equals("traversal") && !(middlebox == null || middlebox.equals(""))) + return true; + return false; + } +} diff --git a/verigraph/src/main/java/it/polito/grpc/GrpcUtils.java b/verigraph/src/main/java/it/polito/grpc/GrpcUtils.java new file mode 100644 index 0000000..0ed002c --- /dev/null +++ b/verigraph/src/main/java/it/polito/grpc/GrpcUtils.java @@ -0,0 +1,156 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.grpc; + +import java.io.IOException; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.base.Splitter; + +import io.grpc.verigraph.ConfigurationGrpc; +import io.grpc.verigraph.GraphGrpc; +import io.grpc.verigraph.NeighbourGrpc; +import io.grpc.verigraph.NodeGrpc; +import io.grpc.verigraph.TestGrpc; +import io.grpc.verigraph.VerificationGrpc; +import io.grpc.verigraph.NodeGrpc.FunctionalType; +import it.polito.escape.verify.model.Configuration; +import it.polito.escape.verify.model.Graph; +import it.polito.escape.verify.model.Neighbour; +import it.polito.escape.verify.model.Node; +import it.polito.escape.verify.model.Test; +import it.polito.escape.verify.model.Verification; + +public class GrpcUtils { + private static final Logger logger = Logger.getLogger(GrpcUtils.class.getName()); + + public static NeighbourGrpc obtainNeighbour(Neighbour ne){ + return NeighbourGrpc.newBuilder() + .setId(ne.getId()) + .setName(ne.getName()) + .build(); + } + + public static Neighbour deriveNeighbour(NeighbourGrpc request) { + //id is not present + Neighbour ne = new Neighbour(); + ne.setName(request.getName()); + return ne; + } + + public static ConfigurationGrpc obtainConfiguration(Configuration conf){ + return ConfigurationGrpc.newBuilder() + .setId(conf.getId()) + .setDescription(conf.getDescription()) + .setConfiguration(conf.getConfiguration().toString()) + .build(); + } + + public static Configuration deriveConfiguration(ConfigurationGrpc request) { + Configuration conf = new Configuration(); + conf.setId(request.getId()); + conf.setDescription(request.getDescription()); + ObjectMapper mapper = new ObjectMapper(); + JsonNode rootNode = null; + try { + if ("".equals(request.getConfiguration())) + rootNode=mapper.readTree("[]"); + else + rootNode = mapper.readTree(request.getConfiguration()); + } catch (IOException e) { + logger.log(Level.WARNING, e.getMessage()); + } + conf.setConfiguration(rootNode); + return conf; + } + + public static NodeGrpc obtainNode(Node node) { + NodeGrpc.Builder nr = NodeGrpc.newBuilder(); + nr.setId(node.getId()); + nr.setName(node.getName()); + nr.setFunctionalType(FunctionalType.valueOf(node.getFunctional_type())); + for(Neighbour neighbour:node.getNeighbours().values()){ + NeighbourGrpc ng = obtainNeighbour(neighbour); + nr.addNeighbour(ng); + } + nr.setConfiguration(obtainConfiguration(node.getConfiguration())); + return nr.build(); + } + + public static Node deriveNode(NodeGrpc request) { + //id is not present + Node node = new Node(); + node.setName(request.getName()); + node.setFunctional_type(request.getFunctionalType().toString()); + Configuration conf = deriveConfiguration(request.getConfiguration()); + node.setConfiguration(conf); + + Map<Long,Neighbour> neighours = node.getNeighbours(); + long i = 1; + for(NeighbourGrpc neighbour:request.getNeighbourList()){ + Neighbour ng = deriveNeighbour(neighbour); + neighours.put(i++, ng); + } + + return node; + } + + public static GraphGrpc obtainGraph(Graph graph){ + GraphGrpc.Builder gr = GraphGrpc.newBuilder(); + gr.setId(graph.getId()); + for(Node node:graph.getNodes().values()){ + NodeGrpc ng = obtainNode(node); + gr.addNode(ng); + } + return gr.build(); + } + + public static Graph deriveGraph(GraphGrpc request) { + //id is not present + Graph graph = new Graph(); + + long i=1; + Map<Long, Node> nodes = graph.getNodes(); + for(NodeGrpc node:request.getNodeList()){ + Node ng = deriveNode(node); + nodes.put(i++, ng); + } + + return graph; + } + + public static VerificationGrpc obtainVerification(Verification verify){ + VerificationGrpc.Builder ver = VerificationGrpc.newBuilder(); + ver.setComment(verify.getComment()); + ver.setResult(verify.getResult()); + for(Test test:verify.getTests()){ + TestGrpc.Builder tst = TestGrpc.newBuilder().setResult(test.getResult()); + for(Node node:test.getPath()){ + NodeGrpc ng = obtainNode(node); + tst.addNode(ng); + } + ver.addTest(tst); + } + return ver.build(); + } + + /**Intended for string that begins with "?" + * */ + public static Map<String,String> getParamGivenString(String str){ + String string = str.substring(1); + final Map<String, String> map = Splitter.on('&').trimResults().withKeyValueSeparator("="). + split(string); + return map; + } +} diff --git a/verigraph/src/main/java/it/polito/grpc/README.rst b/verigraph/src/main/java/it/polito/grpc/README.rst new file mode 100644 index 0000000..d089908 --- /dev/null +++ b/verigraph/src/main/java/it/polito/grpc/README.rst @@ -0,0 +1,442 @@ +.. This work is licensed under a Creative Commons Attribution 4.0 International License. +.. http://creativecommons.org/licenses/by/4.0 + +gRPC Project +============ + +This project contains the interfaces for a web service based on gRPC. + +How to install: +--------------- + +For gRPC interface, add to your ``pom.xml`` (in the project this part is +already present): + +:: + + <dependency> + <groupId>io.grpc</groupId> + <artifactId>grpc-netty</artifactId> + <version>${grpc.version}</version> + </dependency> + <dependency> + <groupId>io.grpc</groupId> + <artifactId>grpc-protobuf</artifactId> + <version>${grpc.version}</version> + </dependency> + <dependency> + <groupId>io.grpc</groupId> + <artifactId>grpc-stub</artifactId> + <version>${grpc.version}</version> + </dependency> + +For protobuf-based codegen integrated with the Maven build system, you +can use protobuf-maven-plugin : + +:: + + <build> + <extensions> + <extension> + <groupId>kr.motd.maven</groupId> + <artifactId>os-maven-plugin</artifactId> + <version>1.4.1.Final</version> + </extension> + </extensions> + <plugins> + <plugin> + <groupId>org.xolstice.maven.plugins</groupId> + <artifactId>protobuf-maven-plugin</artifactId> + <version>0.5.0</version> + <configuration> + <protocArtifact>com.google.protobuf:protoc:3.1.0:exe:${os.detected.classifier}</protocArtifact> + <pluginId>grpc-java</pluginId> + <pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}</pluginArtifact> + </configuration> + <executions> + <execution> + <goals> + <goal>compile</goal> + <goal>compile-custom</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + +| In order to run the gRPC server and the junit test, you need to download the Manven Ant Task library + from `here <https://mvnrepository.com/artifact/org.apache.maven/maven-ant-tasks/2.1.3>`__ + and copy into ``[verigraph]/lib/`` + +| Due to the fact that the project is intended for Eclipse, you need to + install an additional Eclipse plugin because + `m2e <https://www.eclipse.org/m2e/>`__ does not evaluate the extension + specified in a ``pom.xml``. `Download + ``os-maven-plugin-1.5.0.Final.jar`` <http://repo1.maven.org/maven2/kr/motd/maven/os-maven-plugin/1.5.0.Final/os-maven-plugin-1.5.0.Final.jar>`__ + and put it into the ``<ECLIPSE_HOME>/plugins`` directory. +| (As you might have noticed, ``os-maven-plugin`` is a Maven extension, + a Maven plugin, and an Eclipse plugin.) + +If you are using IntelliJ IDEA, you should not have any problem. + +If you are using other IDEs such as NetBeans, you need to set the system +properties ``os-maven-plugin`` sets manually when your IDE is launched. +You usually use JVM's ``-D`` flags like the following: + + | -Dos.detected.name=linux + | -Dos.detected.arch=x86\_64 + | -Dos.detected.classifier=linux-x86\_64 + +Included files: +--------------- + +Here you can find a brief description about useful files for the gRPC +interface: + +**src/main/java:** + +- *it.polito.grpc:* + +This package includes 2 classes that represent the client and server. + + **Client.java:** + + | Client of gRPC application. It implements all possible methods + necessary for communicate with server. + | It prints out the received response. + | Moreover it provides some static methods that are used for + creating the instances of requests. + + **Service.java:** + + | Server of gRPC application. It implements all possible methods + necessary for communicate with client. + | It saves the received request on log. + | This server could be accessed by multiple clients, because + synchronizes concurrent accesses. + | Each method that is possible to call is has the equivalent + operation in REST-interface. + + **GrpcUtils.java:** + + | This class provides some static methods that are used by + ``Service.java`` in order to translate a request into a class that + is accepted by Verigraph. + | Other methods are used to translate the class of Verigraph in the + proper gRPC response. + | These functionalities are exploited by test classes. + | Furthermore this set of methods is public, so in your application + you could call them, even if this should not be useful because + ``Client.java`` provides other high-level functions. + +- *it.polito.grpc.test:* + + This package includes classes for testing the gRPC application. + + **GrpcServerTest.java:** + + | For each possible method we test if works correctly. + | We create a fake client (so this test doesn't use the method that + are present in client class) and test if it receives the expected + response. + | In a nutshell, it tests the methods of Client in case of a fake + server. + | Please notice that the test prints some errors but this is + intentional, because the program tests also error case. + | Indeed, not all methods are tested, because we have another class + (ReachabilityTest.java) that is specialized for testing the + verification method. + + **GrpcTest.java:** + + | This set of tests is intended to control the most common use + cases, in particular all methods that are callable in Client and + Service class, apart from verifyPolicy for the same reason as + before. + | It tries also to raise an exception and verify if the behavior is + as expected. + + **MultiThreadTest.java:** + + | This test creates multiple clients that connect to the server and + verify is the result is correct. These methods test the + synchronization on + | server-side. + + **ReachabilityTest.java:** + + | This file tests the verification method, it exploits the test case + already present in the project and consequently has the certainty + of testing not so simple case. In particular it reads the file in + "src/main/webapp/json" and use this as starting point. + | Some exceptions are thrown in order to verify if they are handled + in a correct way. + +**src/main/proto:** + + **verigraph.proto:** + + | File containing the description of the service. This includes the + definition of all classes used in the application. + | Moreover contains the definition of the methods that is possible + to call. + | Each possible method called by REST API is mapped on a proper gRPC + method. + | In case of error a message containing the reason is returned to + the client. + | More details are available in the section about Proto Buffer. + +**taget/generated-sources/protobuf/java:** + +- *io.grpc.verigraph:* + + This package includes all classes generated from verigraph.proto by + means of protoc. For each object you can find 2 classes : + + **{NameObject}Grpc.java** + + **{NameObject}GrpcOrBuilder.java** + + The first is the real implementation, the second is the + interface. + +**taget/generated-sources/protobuf/grpc-java:** + +- *io.grpc.verigraph:* + + This package includes a single class generated from verigraph.proto + by means of protoc. + + **VerigraphGrpc.java:** + + This is useful in order to create the stubs that are necessary to + communicate both for client and server. + +**lib:** + +This folder includes a jar used for compiling the project with Ant. + + \*\*maven-ant-tasks-2.1.3.\ jar:** + + This file is used by build.xml in order to include the maven + dependencies. + +**pom.xml:** + +| Modified in order to add all necessary dependencies. It contains also + the build tag used for create the generated-sources folders. +| This part is added according to documentation of gRPC for java as + explained above in How To Install section. +| For further clarification go to `this + link <https://github.com/grpc/grpc-java/blob/master/README.md>`__. + +**build.xml:** + +This ant file permit to run and compile the program in a simple way, it +exploits the maven-ant-tasks-2.1.3.jar already present in project. + +It contains 3 fundamental tasks for gRPC interface: + +- **build:** compile the program + +- **run:** run both client and server + +- **run-client :** run only client + +- **run-server :** run only server + +- **run-test :** launch all tests that are present in the package, + prints out the partial results and global result. + +Note that the execution of these tests may take up to 1-2 minutes when +successful, according to your computer architecture. + +More Information About Proto Buffer: +------------------------------------ + +Further clarification about verigraph.proto: + +- A ``simple RPC`` where the client sends a request to the server using + the stub and waits for a response to come back, just like a normal + function call. + + .. code:: xml + + // Obtains a graph + rpc GetGraph (RequestID) returns (GraphGrpc) {} + +In this case we send a request that contains the id of the graph and the +response is a Graph. + +- A ``server-side streaming RPC`` where the client sends a request to + the server and gets a stream to read a sequence of messages back. The + client reads from the returned stream until there are no more + messages. As you can see in our example, you specify a server-side + streaming method by placing the stream keyword before the response + type. + + .. code:: xml + + + // Obtains a list of Nodes + rpc GetNodes (RequestID) returns (stream NodeGrpc) {} + +In this case we send a request that contains the id of the graph and the +response is a list of Nodes that are inside graph. + +Further possibilities are available but in this project are not +expolied. If you are curious see +`here <http://www.grpc.io/docs/tutorials/basic/java.html#defining-the-service>`__. + +Our ``.proto`` file also contains protocol buffer message type +definitions for all the request and response types used in our service +methods - for example, hereÂ’s the ``RequestID`` message type: + +.. code:: xml + + message RequestID { + int64 idGraph = 1; + int64 idNode = 2; + int64 idNeighbour = 3; + } + +The " = 1", " = 2" markers on each element identify the unique "tag" +that field uses in the binary encoding. Tag numbers 1-15 require one +less byte to encode than higher numbers, so as an optimization you can +decide to use those tags for the commonly used or repeated elements, +leaving tags 16 and higher for less-commonly used optional elements. +Each element in a repeated field requires re-encoding the tag number, so +repeated fields are particularly good candidates for this optimization. + +Protocol buffers are the flexible, efficient, automated solution to +solve exactly the problem of serialization. With protocol buffers, you +write a .proto description of the data structure you wish to store. From +that, the protocol buffer compiler creates a class that implements +automatic encoding and parsing of the protocol buffer data with an +efficient binary format. The generated class provides getters and +setters for the fields that make up a protocol buffer and takes care of +the details of reading and writing the protocol buffer as a unit. +Importantly, the protocol buffer format supports the idea of extending +the format over time in such a way that the code can still read data +encoded with the old format. + +:: + + syntax = "proto3"; + + package verigraph; + + option java_multiple_files = true; + option java_package = "io.grpc.verigraph"; + option java_outer_classname = "VerigraphProto"; + ``` + +This .proto file works for protobuf 3, that is slightly different from +the version 2, so be careful if you have code already installed. + +The .proto file starts with a package declaration, which helps to +prevent naming conflicts between different projects. In Java, the +package name is used as the ``Java package`` unless you have explicitly +specified a java\_package, as we have here. Even if you do provide a +``java_package``, you should still define a normal ``package`` as well +to avoid name collisions in the Protocol Buffers name space as well as +in non-Java languages. + +| After the package declaration, you can see two options that are + Java-specific: ``java_package`` and ``java_outer_classname``. + ``java_package`` specifies in what Java package name your generated + classes should live. If you don't specify this explicitly, it simply + matches the package name given by the package declaration, but these + names usually aren't appropriate Java package names (since they + usually don't start with a domain name). The ``java_outer_classname`` + option defines the class name which should contain all of the classes + in this file. If you don't give a ``java_outer_classname explicitly``, + it will be generated by converting the file name to camel case. For + example, "my\_proto.proto" would, by default, use "MyProto" as the + outer class name. +| In this case this file is not generated, because + ``java_multiple_files`` option is true, so for each message we + generate a different class. + +For further clarifications see +`here <https://developers.google.com/protocol-buffers/docs/javatutorial>`__ + +Notes +----- + +For gRPC interface you need that neo4jmanager service is already +deployed, so if this is not the case, please follow the instructions at +this +`link <https://github.com/netgroup-polito/verigraph/blob/a3c008a971a8b16552a20bf2484ebf8717735dd6/README.md>`__. + +In this version there are some modified files compared to the original +`Verigraph project <https://github.com/netgroup-polito/verigraph>`__ + +**it.polito.escape.verify.service.NodeService:** + +At line 213 we modified the path, because this service is intended to +run not only in container, as Tomcat, so we added other possibility that +files is placed in src/main/webapp/json/ folder. + +**it.polito.escape.verify.service.VerificationService:** + +In the original case it searches for python files in "webapps" folder, +that is present if the service is deployed in a container, but absent +otherwise. So we added another string that will be used in the case the +service doesn't run in Tomcat. + +**it.polito.escape.verify.databese.DatabaseClass:** + +Like before we added the possibility that files are not in "webapps" +folder, so is modified in order to run in any environment. Modification +in method loadDataBase() and persistDatabase(). + +| Pay attention that Python is needed for the project. If it is not + already present on your computer, please `download + it <https://www.python.org/download/releases/2.7.3/>`__. +| It works fine with Python 2.7.3, or in general Python 2. + +| If you have downloaded a Python version for 64-bit architecture please + copy the files in "service/z3\_64" and paste in "service/build" and + substitute them, +| because this project works with Python for 32-bit architecture. + +Python and Z3 must support the same architetcure. + +Moreover you need the following dependencies installed on your python +distribution: + +- "requests" python package -> +http://docs.python-requests.org/en/master/ + +- "jsonschema" python package -> https://pypi.python.org/pypi/jsonschema + +| HINT - to install a package you can raise the following command (Bash + on Linux or DOS shell on Windows): python -m pip install jsonschema + python -m pip install requests +| Pay attention that it is possible that you have to modify the PATH + environment variable because is necessary to address the python + folder, used for verification phase. + +Remember to read the +`README.rtf <https://gitlab.com/serena.spinoso/DP2.2017.SpecialProject2.gRPC/tree/master>`__ +and to follow the instructions in order to deploy the Verigraph service. + +| In the latest version of Maven there is the possibility that the + downloaded files are incompatible with Java Version of the project + (1.8). +| In this case you have to modify the file ``hk2-parent-2.4.0-b31.pom`` + under your local Maven repository (e.g. + 'C:\\Users\\Standard.m2\\repository') +| and in the path ``\org\glassfish\hk2\hk2-parent\2.4.0-b31`` find the + file and modify at line 1098 (in section ``profile``) the ``jdk`` + version to ``[1.8,)`` . + +| Admittedly, the version that is supported by the downloaded files from + Maven Dependencies is incompatible with jdk of the project. +| So modify the file ``gson-2.3.pom`` in Maven repository, under + ``com\google\code\gson\gson\2.3`` directory, in particular line 91, + from ``[1.8,`` to ``[1.8,)``. + +This project was also tested on Linux Ubuntu 15.10. diff --git a/verigraph/src/main/java/it/polito/grpc/Service.java b/verigraph/src/main/java/it/polito/grpc/Service.java new file mode 100644 index 0000000..8a77d05 --- /dev/null +++ b/verigraph/src/main/java/it/polito/grpc/Service.java @@ -0,0 +1,462 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.grpc; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +import io.grpc.Server; +import io.grpc.ServerBuilder; +import io.grpc.stub.StreamObserver; +import io.grpc.verigraph.ConfigurationGrpc; +import io.grpc.verigraph.GetRequest; +import io.grpc.verigraph.GraphGrpc; +import io.grpc.verigraph.NeighbourGrpc; +import io.grpc.verigraph.NewGraph; +import io.grpc.verigraph.NewNeighbour; +import io.grpc.verigraph.NewNode; +import io.grpc.verigraph.NodeGrpc; +import io.grpc.verigraph.Policy; +import io.grpc.verigraph.RequestID; +import io.grpc.verigraph.Status; +import io.grpc.verigraph.VerificationGrpc; +import io.grpc.verigraph.VerigraphGrpc; +import it.polito.escape.verify.exception.BadRequestException; +import it.polito.escape.verify.exception.DataNotFoundException; +import it.polito.escape.verify.exception.ForbiddenException; +import it.polito.escape.verify.model.Configuration; +import it.polito.escape.verify.model.Graph; +import it.polito.escape.verify.model.Neighbour; +import it.polito.escape.verify.model.Node; +import it.polito.escape.verify.model.Verification; +import it.polito.escape.verify.resources.beans.VerificationBean; +import it.polito.escape.verify.service.GraphService; +import it.polito.escape.verify.service.NeighbourService; +import it.polito.escape.verify.service.NodeService; +import it.polito.escape.verify.service.VerificationService; + +public class Service { + /** Port on which the server should run. */ + private static final Logger logger = Logger.getLogger(Service.class.getName()); + private static final int port = 50051; + private static final String internalError = "Internal Server Error"; + private Server server; + private GraphService graphService = new GraphService(); + private VerificationService verificationService = new VerificationService(); + private NodeService nodeService = new NodeService(); + private NeighbourService neighboursService = new NeighbourService(); + + public Service(int port) { + this(ServerBuilder.forPort(port), port); + } + + /** Create a RouteGuide server using serverBuilder as a base and features as data. */ + public Service(ServerBuilder<?> serverBuilder, int port) { + server = serverBuilder.addService(new VerigraphImpl()) + .build(); + } + + public void start() throws IOException { + server.start(); + logger.info("Server started, listening on "+ port); + Runtime.getRuntime().addShutdownHook(new Thread() { + @Override + public void run() { + logger.info("*** Shutting down gRPC server since JVM is shutting down"); + Service.this.stop(); + logger.info("*** Server shut down"); + } + }); + } + + public void stop() { + if (server != null) { + server.shutdown(); + } + } + + private void blockUntilShutdown() throws InterruptedException { + if (server != null) { + server.awaitTermination(); + } + } + + /** Main function to launch server from cmd. */ + public static void main(String[] args) throws IOException, InterruptedException { + try{ + Service server = new Service(port); + server.start(); + server.blockUntilShutdown(); + } + catch(Exception ex){ + logger.log(Level.WARNING, ex.getMessage()); + } + } + + /**Here start method of my impementation*/ + private class VerigraphImpl extends VerigraphGrpc.VerigraphImplBase{ + + /** Here start methods of GraphResource*/ + @Override + public void getGraphs(GetRequest request, StreamObserver<GraphGrpc> responseObserver) { + try{ + for(Graph item : graphService.getAllGraphs()) { + GraphGrpc gr = GrpcUtils.obtainGraph(item); + responseObserver.onNext(gr); + } + }catch(Exception ex){ + GraphGrpc nr = GraphGrpc.newBuilder().setErrorMessage(internalError).build(); + responseObserver.onNext(nr); + logger.log(Level.WARNING, ex.getMessage()); + } + responseObserver.onCompleted(); + } + + @Override + public void createGraph(GraphGrpc request, StreamObserver<NewGraph> responseObserver) { + NewGraph.Builder response = NewGraph.newBuilder(); + try{ + Graph graph = GrpcUtils.deriveGraph(request); + Graph newGraph = graphService.addGraph(graph); + response.setSuccess(true).setGraph(GrpcUtils.obtainGraph(newGraph)); + }catch(BadRequestException ex){ + response.setSuccess(false).setErrorMessage(ex.getMessage()); + logger.log(Level.WARNING, ex.getMessage()); + } + catch(Exception ex){ + response.setSuccess(false).setErrorMessage(internalError); + logger.log(Level.WARNING, ex.getMessage()); + } + responseObserver.onNext(response.build()); + responseObserver.onCompleted(); + } + + @Override + public void deleteGraph(RequestID request, StreamObserver<Status> responseObserver) { + + Status.Builder response = Status.newBuilder(); + try{ + graphService.removeGraph(request.getIdGraph()); + response.setSuccess(true); + }catch(ForbiddenException ex){ + response.setSuccess(false).setErrorMessage(ex.getMessage()); + logger.log(Level.WARNING, ex.getMessage()); + } catch(Exception ex){ + response.setSuccess(false).setErrorMessage(internalError); + logger.log(Level.WARNING, ex.getMessage()); + } + responseObserver.onNext(response.build()); + responseObserver.onCompleted(); + } + + @Override + public void getGraph(RequestID request, StreamObserver<GraphGrpc> responseObserver) { + try{ + Graph graph = graphService.getGraph(request.getIdGraph()); + GraphGrpc gr = GrpcUtils.obtainGraph(graph); + responseObserver.onNext(gr); + }catch(ForbiddenException | DataNotFoundException ex){ + GraphGrpc grError = GraphGrpc.newBuilder().setErrorMessage(ex.getMessage()).build(); + responseObserver.onNext(grError); + logger.log(Level.WARNING, ex.getMessage()); + }catch(Exception ex){ + GraphGrpc grError = GraphGrpc.newBuilder().setErrorMessage(internalError).build(); + responseObserver.onNext(grError); + logger.log(Level.WARNING, ex.getMessage()); + } + responseObserver.onCompleted(); + } + + @Override + public void updateGraph(GraphGrpc request, StreamObserver<NewGraph> responseObserver) { + NewGraph.Builder response = NewGraph.newBuilder(); + try{ + Graph graph = GrpcUtils.deriveGraph(request); + graph.setId(request.getId()); + Graph newGraph = graphService.updateGraph(graph); + response.setSuccess(true).setGraph(GrpcUtils.obtainGraph(newGraph)); + }catch(ForbiddenException | DataNotFoundException | BadRequestException ex){ + response.setSuccess(false).setErrorMessage(ex.getMessage()); + logger.log(Level.WARNING, ex.getMessage()); + }catch(Exception ex){ + response.setSuccess(false).setErrorMessage(internalError); + logger.log(Level.WARNING, ex.getMessage()); + } + responseObserver.onNext(response.build()); + responseObserver.onCompleted(); + } + + @Override + public void verifyPolicy(Policy request, StreamObserver<VerificationGrpc> responseObserver) { + + VerificationGrpc.Builder verification; + try{ + //Convert request + VerificationBean verify = new VerificationBean(); + verify.setDestination(request.getDestination()); + verify.setSource(request.getSource()); + verify.setType(request.getType().toString()); + verify.setMiddlebox(request.getMiddlebox()); + + //Convert Response + Verification ver = verificationService.verify(request.getIdGraph(), verify); + verification = VerificationGrpc.newBuilder(GrpcUtils.obtainVerification(ver)) + .setSuccessOfOperation(true); + }catch(ForbiddenException | DataNotFoundException | BadRequestException ex){ + verification = VerificationGrpc.newBuilder().setSuccessOfOperation(false) + .setErrorMessage(ex.getMessage()); + logger.log(Level.WARNING, ex.getMessage()); + } catch(Exception ex){ + verification = VerificationGrpc.newBuilder().setSuccessOfOperation(false) + .setErrorMessage(internalError); + logger.log(Level.WARNING, ex.getMessage()); + } + responseObserver.onNext(verification.build()); + responseObserver.onCompleted(); + } + + /** Here start methods of NodeResource*/ + + @Override + public void getNodes(RequestID request, StreamObserver<NodeGrpc> responseObserver) { + try{ + for (Node item : nodeService.getAllNodes(request.getIdGraph())) { + NodeGrpc nr = GrpcUtils.obtainNode(item); + responseObserver.onNext(nr); + } + }catch(ForbiddenException | DataNotFoundException ex){ + NodeGrpc nr = NodeGrpc.newBuilder().setErrorMessage(ex.getMessage()).build(); + responseObserver.onNext(nr); + logger.log(Level.WARNING, ex.getMessage()); + } catch(Exception ex){ + NodeGrpc nr = NodeGrpc.newBuilder().setErrorMessage(internalError).build(); + responseObserver.onNext(nr); + logger.log(Level.WARNING, ex.getMessage()); + } + responseObserver.onCompleted(); + } + + @Override + public void createNode(NodeGrpc request, StreamObserver<NewNode> responseObserver) { + NewNode.Builder response = NewNode.newBuilder(); + try{ + Node node = GrpcUtils.deriveNode(request); + Node newNode = nodeService.addNode(request.getIdGraph(), node); + response.setSuccess(true).setNode(GrpcUtils.obtainNode(newNode)); + }catch(ForbiddenException | DataNotFoundException | BadRequestException ex){ + response.setSuccess(false).setErrorMessage(ex.getMessage()); + logger.log(Level.WARNING, ex.getMessage()); + }catch(Exception ex){ + response.setSuccess(false).setErrorMessage(internalError); + logger.log(Level.WARNING, ex.getMessage()); + } + responseObserver.onNext(response.build()); + responseObserver.onCompleted(); + } + + @Override + public void deleteNode(RequestID request, StreamObserver<Status> responseObserver) { + Status.Builder response = Status.newBuilder(); + try{ + nodeService.removeNode(request.getIdGraph(), request.getIdNode()); + response.setSuccess(true); + }catch(ForbiddenException | DataNotFoundException ex){ + response.setSuccess(false).setErrorMessage(ex.getMessage()); + logger.log(Level.WARNING, ex.getMessage()); + }catch(Exception ex){ + response.setSuccess(false).setErrorMessage(internalError); + logger.log(Level.WARNING, ex.getMessage()); + } + responseObserver.onNext(response.build()); + responseObserver.onCompleted(); + } + + @Override + public void getNode(RequestID request, StreamObserver<NodeGrpc> responseObserver) { + NodeGrpc nr; + try{ + Node node = nodeService.getNode(request.getIdGraph(), request.getIdNode()); + nr= GrpcUtils.obtainNode(node); + }catch(ForbiddenException | DataNotFoundException ex){ + nr = NodeGrpc.newBuilder().setErrorMessage(ex.getMessage()).build(); + logger.log(Level.WARNING, ex.getMessage()); + }catch(Exception ex){ + nr = NodeGrpc.newBuilder().setErrorMessage(internalError).build(); + logger.log(Level.WARNING, ex.getMessage()); + } + responseObserver.onNext(nr); + responseObserver.onCompleted(); + } + + @Override + public void updateNode(NodeGrpc request, StreamObserver<NewNode> responseObserver) { + NewNode.Builder response = NewNode.newBuilder(); + try{ + Node node = GrpcUtils.deriveNode(request); + node.setId(request.getId()); + Node newNode = nodeService.updateNode(request.getIdGraph(), node); + response.setSuccess(true).setNode(GrpcUtils.obtainNode(newNode)); + }catch(ForbiddenException | DataNotFoundException | BadRequestException ex){ + response.setSuccess(false).setErrorMessage(ex.getMessage()); + logger.log(Level.WARNING, ex.getMessage()); + }catch(Exception ex){ + response.setSuccess(false).setErrorMessage(internalError); + logger.log(Level.WARNING, ex.getMessage()); + } + responseObserver.onNext(response.build()); + responseObserver.onCompleted(); + } + + @Override + public void configureNode(ConfigurationGrpc request, StreamObserver<Status> responseObserver) { + Status.Builder response = Status.newBuilder(); + try{ + if (request.getIdGraph() <= 0) { + throw new ForbiddenException("Illegal graph id: " + request.getIdGraph()); + } + if (request.getIdNode() <= 0) { + throw new ForbiddenException("Illegal node id: " + request.getIdNode()); + } + Graph graph = new GraphService().getGraph(request.getIdGraph()); + if (graph == null){ + throw new BadRequestException("Graph with id " + request.getIdGraph() + " not found"); + } + Node node = nodeService.getNode(request.getIdGraph(), request.getIdNode()); + if (node == null){ + throw new BadRequestException("Node with id " + request.getIdNode() + " not found in graph with id " + request.getIdGraph()); + } + Configuration nodeConfiguration = GrpcUtils.deriveConfiguration(request); + Node nodeCopy = new Node(); + nodeCopy.setId(node.getId()); + nodeCopy.setName(node.getName()); + nodeCopy.setFunctional_type(node.getFunctional_type()); + Map<Long,Neighbour> nodes = new HashMap<Long,Neighbour>(); + nodes.putAll(node.getNeighbours()); + nodeCopy.setNeighbours(nodes); + nodeConfiguration.setId(nodeCopy.getName()); + nodeCopy.setConfiguration(nodeConfiguration); + + Graph graphCopy = new Graph(); + graphCopy.setId(graph.getId()); + graphCopy.setNodes(new HashMap<Long, Node>(graph.getNodes())); + graphCopy.getNodes().remove(node.getId()); + + NodeService.validateNode(graphCopy, nodeCopy); + + graph.getNodes().put(request.getIdNode(), nodeCopy); + response.setSuccess(true); + }catch(ForbiddenException | BadRequestException ex){ + response.setSuccess(false).setErrorMessage(ex.getMessage()); + logger.log(Level.WARNING, ex.getMessage()); + }catch(Exception ex){ + response.setSuccess(false).setErrorMessage(internalError); + logger.log(Level.WARNING, ex.getMessage()); + } + responseObserver.onNext(response.build()); + responseObserver.onCompleted(); + } + + /** Here start methods of NeighbourResource*/ + @Override + public void getNeighbours(RequestID request, StreamObserver<NeighbourGrpc> responseObserver) { + try{ + for(Neighbour item : neighboursService.getAllNeighbours(request.getIdGraph(), request.getIdNode())) { + NeighbourGrpc nr = GrpcUtils.obtainNeighbour(item); + responseObserver.onNext(nr); + } + }catch(ForbiddenException | DataNotFoundException ex){ + NeighbourGrpc nr = NeighbourGrpc.newBuilder().setErrorMessage(ex.getMessage()).build(); + responseObserver.onNext(nr); + logger.log(Level.WARNING, ex.getMessage()); + }catch(Exception ex){ + NeighbourGrpc nr = NeighbourGrpc.newBuilder().setErrorMessage(internalError).build(); + responseObserver.onNext(nr); + logger.log(Level.WARNING, ex.getMessage()); + } + responseObserver.onCompleted(); + } + + @Override + public void createNeighbour(NeighbourGrpc request, StreamObserver<NewNeighbour> responseObserver) { + NewNeighbour.Builder response = NewNeighbour.newBuilder(); + try{ + Neighbour neighbour = GrpcUtils.deriveNeighbour(request); + Neighbour newNeighbour = neighboursService.addNeighbour(request.getIdGraph(), request.getIdNode(), neighbour); + response.setSuccess(true).setNeighbour(GrpcUtils.obtainNeighbour(newNeighbour)); + }catch(ForbiddenException | DataNotFoundException | BadRequestException ex){ + response.setSuccess(false).setErrorMessage(ex.getMessage()); + logger.log(Level.WARNING, ex.getMessage()); + }catch(Exception ex){ + response.setSuccess(false).setErrorMessage(ex.getMessage()); + logger.log(Level.WARNING, ex.getMessage()); + } + responseObserver.onNext(response.build()); + responseObserver.onCompleted(); + } + + @Override + public void deleteNeighbour(RequestID request, StreamObserver<Status> responseObserver) { + Status.Builder response = Status.newBuilder(); + try{ + neighboursService.removeNeighbour(request.getIdGraph(), request.getIdNode(), request.getIdNeighbour()); + response.setSuccess(true); + }catch(ForbiddenException | DataNotFoundException ex){ + response.setSuccess(false).setErrorMessage(ex.getMessage()); + logger.log(Level.WARNING, ex.getMessage()); + }catch(Exception ex){ + response.setSuccess(false).setErrorMessage(ex.getMessage()); + logger.log(Level.WARNING, ex.getMessage()); + } + responseObserver.onNext(response.build()); + responseObserver.onCompleted(); + } + + @Override + public void getNeighbour(RequestID request, StreamObserver<NeighbourGrpc> responseObserver) { + NeighbourGrpc nr; + try{ + Neighbour neighbour = neighboursService.getNeighbour(request.getIdGraph(), + request.getIdNode(), request.getIdNeighbour()); + nr = GrpcUtils.obtainNeighbour(neighbour); + + }catch(ForbiddenException | DataNotFoundException ex){ + nr = NeighbourGrpc.newBuilder().setErrorMessage(ex.getMessage()).build(); + logger.log(Level.WARNING, ex.getMessage()); + }catch(Exception ex){ + nr = NeighbourGrpc.newBuilder().setErrorMessage(internalError).build(); + logger.log(Level.WARNING, ex.getMessage()); + } + responseObserver.onNext(nr); + responseObserver.onCompleted(); + } + + @Override + public void updateNeighbour(NeighbourGrpc request, StreamObserver<NewNeighbour> responseObserver) { + NewNeighbour.Builder response = NewNeighbour.newBuilder(); + try{ + Neighbour neighbour = GrpcUtils.deriveNeighbour(request); + neighbour.setId(request.getId()); + Neighbour newNeighbour = neighboursService.updateNeighbour(request.getIdGraph(), request.getIdNode(), neighbour); + response.setSuccess(true).setNeighbour(GrpcUtils.obtainNeighbour(newNeighbour)); + }catch(ForbiddenException | DataNotFoundException | BadRequestException ex){ + response.setSuccess(false).setErrorMessage(ex.getMessage()); + logger.log(Level.WARNING, ex.getMessage()); + }catch(Exception ex){ + response.setSuccess(false).setErrorMessage(ex.getMessage()); + logger.log(Level.WARNING, ex.getMessage()); + } + responseObserver.onNext(response.build()); + responseObserver.onCompleted(); + } + } +} diff --git a/verigraph/src/main/java/it/polito/grpc/test/GrpcServerTest.java b/verigraph/src/main/java/it/polito/grpc/test/GrpcServerTest.java new file mode 100644 index 0000000..7344447 --- /dev/null +++ b/verigraph/src/main/java/it/polito/grpc/test/GrpcServerTest.java @@ -0,0 +1,292 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.grpc.test; + +import static org.junit.Assert.assertEquals; + +import io.grpc.ManagedChannel; +import io.grpc.inprocess.InProcessChannelBuilder; +import io.grpc.inprocess.InProcessServerBuilder; +import io.grpc.verigraph.ConfigurationGrpc; +import io.grpc.verigraph.GetRequest; +import io.grpc.verigraph.GraphGrpc; +import io.grpc.verigraph.NeighbourGrpc; +import io.grpc.verigraph.NewGraph; +import io.grpc.verigraph.NewNeighbour; +import io.grpc.verigraph.NewNode; +import io.grpc.verigraph.NodeGrpc; +import io.grpc.verigraph.NodeGrpc.FunctionalType; +import io.grpc.verigraph.RequestID; +import io.grpc.verigraph.Status; +import io.grpc.verigraph.VerigraphGrpc; +import it.polito.grpc.Client; +import it.polito.grpc.Service; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * Unit tests for {@link Service}. + * For testing basic gRPC unit test only. + * Not intended to provide a high code coverage or to test every major usecase. + */ +@RunWith(JUnit4.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class GrpcServerTest { + private Service server; + private ManagedChannel inProcessChannel; + + @Before + public void setUp() throws Exception { + String uniqueServerName = "in-process server for " + getClass(); + // use directExecutor for both InProcessServerBuilder and InProcessChannelBuilder can reduce the + // usage timeouts and latches in test. But we still add timeout and latches where they would be + // needed if no directExecutor were used, just for demo purpose. + server = new Service(InProcessServerBuilder.forName(uniqueServerName).directExecutor(),0); + server.start(); + inProcessChannel = InProcessChannelBuilder.forName(uniqueServerName).directExecutor().build(); + } + + @After + public void tearDown() throws Exception { + inProcessChannel.shutdownNow(); + server.stop(); + } + + @Test + public void test1Graph() throws Exception { + RequestID request = RequestID.newBuilder().setIdGraph(1).build() ;//id not present + GraphGrpc ufoundedGraph = GraphGrpc.newBuilder() + .setErrorMessage("Graph with id 1 not found").build(); + VerigraphGrpc.VerigraphBlockingStub stub = VerigraphGrpc.newBlockingStub(inProcessChannel); + + // graph not found in the server + GraphGrpc graph = stub.getGraph(request); + + assertEquals(ufoundedGraph, graph); + + // getGraph in the server, but first add it + GraphGrpc addedGraph = GraphGrpc.newBuilder().build(); + NewGraph response = stub.createGraph(addedGraph); + addedGraph = response.getGraph(); + request = RequestID.newBuilder().setIdGraph(1).build() ; + graph = stub.getGraph(request); + + assertEquals(addedGraph.getId(), graph.getId()); + + //updateGraph + GraphGrpc updatedGraph = GraphGrpc.newBuilder().setId(response.getGraph().getId()).build(); + response = stub.updateGraph(updatedGraph); + + assertEquals(response.getSuccess(),true); + } + + @Test + public void test2Graphs() throws Exception { + // setup + GetRequest request = GetRequest.newBuilder().build(); + GraphGrpc g1 = GraphGrpc.newBuilder().build(); + GraphGrpc g2 = GraphGrpc.newBuilder().build(); + GraphGrpc g3 = GraphGrpc.newBuilder().build(); + GraphGrpc g4 = GraphGrpc.newBuilder().build(); + + VerigraphGrpc.VerigraphBlockingStub stub = VerigraphGrpc.newBlockingStub(inProcessChannel); + + stub.createGraph(g1); + stub.createGraph(g2); + stub.createGraph(g3); + stub.createGraph(g4); + g1 = GraphGrpc.newBuilder(g1).setId(1).build(); + g2 = GraphGrpc.newBuilder(g2).setId(2).build(); + g3 = GraphGrpc.newBuilder(g3).setId(3).build(); + g4 = GraphGrpc.newBuilder(g4).setId(4).build(); + // run + Iterator<GraphGrpc> graphs = stub.getGraphs(request); + + assertEquals(graphs.next(), g1); + assertEquals(graphs.next(), g2); + assertEquals(graphs.next(), g3); + assertEquals(graphs.next(), g4); + + //deleteGraph + RequestID req = RequestID.newBuilder().setIdGraph(g1.getId()).build(); + stub.deleteGraph(req); + // run + graphs = stub.getGraphs(request); + + assertEquals(graphs.next(), g2); + assertEquals(graphs.next(), g3); + assertEquals(graphs.next(), g4); + } + + @Test + public void test3Node() throws Exception { + RequestID request = RequestID.newBuilder().setIdGraph(2).setIdNode(1).build() ;//id not present + NodeGrpc ufoundedGraph = NodeGrpc.newBuilder() + .setErrorMessage("Node with id 1 not found in graph with id 2").build(); + VerigraphGrpc.VerigraphBlockingStub stub = VerigraphGrpc.newBlockingStub(inProcessChannel); + + // graph not found in the server + NodeGrpc node = stub.getNode(request); + + assertEquals(ufoundedGraph, node); + + // graph found in the server, but first add it + NodeGrpc addedNode = NodeGrpc.newBuilder().setName("client").setIdGraph(2) + .setFunctionalType(FunctionalType.endhost).build(); + NewNode response = stub.createNode(addedNode); + addedNode = response.getNode(); + request = RequestID.newBuilder().setIdGraph(2).setIdNode(1).build() ; + node = stub.getNode(request); + + assertEquals(addedNode.getId(), node.getId()); + assertEquals(addedNode.getName(),"client"); + + //updateNode + NodeGrpc updatedNode = NodeGrpc.newBuilder().setName("Nodo2").setIdGraph(2).setId(1) + .setFunctionalType(FunctionalType.endhost).build(); + response = stub.updateNode(updatedNode); + + assertEquals(response.getSuccess(),true); + assertEquals(response.getNode().getName(),"Nodo2"); + + //configureNode + Map<String,String> params = new HashMap<String,String>(); + params.put("url", "www.facebook.com"); + params.put("body", "word"); + params.put("destination","server"); + params.put("protocol", "HTTP_REQUEST"); + ConfigurationGrpc configuration = Client.createConfigurationGrpc(params, null, null, null); + ConfigurationGrpc config = ConfigurationGrpc.newBuilder(configuration).setIdGraph(2) + .setIdNode(1).build(); + + Status status = stub.configureNode(config); + + assertEquals(status.getSuccess(),true); + } + + @Test + public void test4Nodes() throws Exception { + // setup + RequestID request = RequestID.newBuilder().setIdGraph(2).build(); + NodeGrpc n1 = NodeGrpc.newBuilder(Client.createNodeGrpc("Node5", "endhost", null, null)) + .setIdGraph(2).build(); + NodeGrpc n2 = NodeGrpc.newBuilder(Client.createNodeGrpc("Node3", "endhost", null, null)) + .setIdGraph(2).build(); + NodeGrpc n3 = NodeGrpc.newBuilder(Client.createNodeGrpc("Node4", "endhost", null, null)) + .setIdGraph(2).build(); + NodeGrpc n4 = NodeGrpc.newBuilder(Client.createNodeGrpc("client", "endhost", null, null)) + .setIdGraph(2).build(); + + VerigraphGrpc.VerigraphBlockingStub stub = VerigraphGrpc.newBlockingStub(inProcessChannel); + + stub.createNode(n1); + stub.createNode(n2); + stub.createNode(n3); + stub.createNode(n4); + n1 = NodeGrpc.newBuilder(n1).setId(2).setIdGraph(0).build(); + n2 = NodeGrpc.newBuilder(n2).setId(3).setIdGraph(0).build(); + n3 = NodeGrpc.newBuilder(n3).setId(4).setIdGraph(0).build(); + n4 = NodeGrpc.newBuilder(n4).setId(5).setIdGraph(0).build(); + // run + Iterator<NodeGrpc> nodes = stub.getNodes(request); + + nodes.next(); + assertEquals(nodes.next(), n1); + assertEquals(nodes.next(), n2); + assertEquals(nodes.next(), n3); + assertEquals(nodes.next(), n4); + + //deleteNode + RequestID req = RequestID.newBuilder().setIdGraph(2).setIdNode(1).build(); + stub.deleteNode(req); + // run + nodes = stub.getNodes(request); + + assertEquals(nodes.next(), n1); + assertEquals(nodes.next(), n2); + assertEquals(nodes.next(), n3); + assertEquals(nodes.next(), n4); + } + + @Test + public void test5Neighbours() throws Exception { + RequestID request = RequestID.newBuilder().setIdGraph(2).setIdNode(2).setIdNeighbour(1).build() ;//id not present + NeighbourGrpc ufoundedNeighbour = NeighbourGrpc.newBuilder() + .setErrorMessage("Neighbour with id 1 not found for node with id 2 in graph with id 2").build();; + VerigraphGrpc.VerigraphBlockingStub stub = VerigraphGrpc.newBlockingStub(inProcessChannel); + + // Neighbour not found in the server + NeighbourGrpc neighbour = stub.getNeighbour(request); + + assertEquals(ufoundedNeighbour, neighbour); + + // getNeighbour, but first add it + NeighbourGrpc addedNeighbour = NeighbourGrpc.newBuilder().setIdGraph(2).setIdNode(2) + .setName("client").build(); + NewNeighbour response = stub.createNeighbour(addedNeighbour); + addedNeighbour = response.getNeighbour(); + request = RequestID.newBuilder().setIdGraph(2).setIdNode(2) + .setIdNeighbour(addedNeighbour.getId()).build(); + neighbour = stub.getNeighbour(request); + + assertEquals(addedNeighbour.getId(), neighbour.getId()); + + //updateNeighbour + NeighbourGrpc updatedNeighbour = Client.createNeighbourGrpc("Node4"); + NeighbourGrpc nu = NeighbourGrpc.newBuilder(updatedNeighbour) + .setId(response.getNeighbour().getId()).setIdGraph(2).setIdNode(2).build(); + response = stub.updateNeighbour(nu); + + assertEquals(response.getSuccess(),true); + assertEquals(response.getNeighbour().getName(),"Node4"); + } + + @Test + public void test6Neighbours() throws Exception { + // setup + RequestID request = RequestID.newBuilder().setIdGraph(2).setIdNode(2).build(); + NeighbourGrpc n1 = NeighbourGrpc.newBuilder().setIdGraph(2).setIdNode(2) + .setName("Node3").build(); + NeighbourGrpc n2 = NeighbourGrpc.newBuilder().setIdGraph(2).setIdNode(2) + .setName("client").build(); + + VerigraphGrpc.VerigraphBlockingStub stub = VerigraphGrpc.newBlockingStub(inProcessChannel); + + stub.createNeighbour(n1); + stub.createNeighbour(n2); + n1 = NeighbourGrpc.newBuilder(n1).setId(2).setIdGraph(0).setIdNode(0).build(); + n2 = NeighbourGrpc.newBuilder(n2).setId(3).setIdGraph(0).setIdNode(0).build(); + // run + Iterator<NeighbourGrpc> neighbours = stub.getNeighbours(request); + + neighbours.next(); + assertEquals(neighbours.next(), n1); + assertEquals(neighbours.next(), n2); + + //deleteNeighbour + RequestID req = RequestID.newBuilder().setIdGraph(2).setIdNode(2).setIdNeighbour(1).build(); + stub.deleteNeighbour(req); + // run + neighbours = stub.getNeighbours(request); + + assertEquals(neighbours.next(), n1); + assertEquals(neighbours.next(), n2); + } +} diff --git a/verigraph/src/main/java/it/polito/grpc/test/GrpcTest.java b/verigraph/src/main/java/it/polito/grpc/test/GrpcTest.java new file mode 100644 index 0000000..41f9cad --- /dev/null +++ b/verigraph/src/main/java/it/polito/grpc/test/GrpcTest.java @@ -0,0 +1,349 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.grpc.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.fail; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.junit.After; +import org.junit.Before; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.junit.runners.MethodSorters; + +import io.grpc.verigraph.ConfigurationGrpc; +import io.grpc.verigraph.GraphGrpc; +import io.grpc.verigraph.NeighbourGrpc; +import io.grpc.verigraph.NewGraph; +import io.grpc.verigraph.NewNeighbour; +import io.grpc.verigraph.NewNode; +import io.grpc.verigraph.NodeGrpc; +import it.polito.grpc.Client; +import it.polito.grpc.Service; + +@RunWith(JUnit4.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class GrpcTest { + private Service server; + private Client client; + + @Before + public void setUpBeforeClass() throws Exception { + client = new Client("localhost" , 50051); + server = new Service(50051); + server.start(); + } + + @After + public void tearDown() throws Exception { + server.stop(); + client.shutdown(); + } + + // method for comparing two non-null strings + private void compareString(String rs, String ts, String meaning) { + assertNotNull("NULL "+meaning, ts); + assertEquals("Wrong "+meaning, rs, ts); + } + + @Test + public final void test1Load() throws Exception{ + String funcType1 = "vpnaccess"; + String funcType2 = "vpnexit"; + + // load an existing graph with 2 nodes + Map<String,String> map = new HashMap<String,String>(); + map.put("vpnexit", "Node2"); + ConfigurationGrpc conf = Client.createConfigurationGrpc(map, null, null, null); + NodeGrpc node1 = Client.createNodeGrpc("Node1", funcType1, null, conf); + List<NeighbourGrpc> neighbours = new ArrayList<NeighbourGrpc>(); + NeighbourGrpc nb = Client.createNeighbourGrpc("Node1"); + neighbours.add(nb); + map.clear(); + map.put("vpnaccess", "Node1"); + conf = Client.createConfigurationGrpc(map, null, null, null); + NodeGrpc node2 = Client.createNodeGrpc("Node2", funcType2, neighbours, conf); + List<NodeGrpc> nodes = new ArrayList<NodeGrpc>(); + nodes.add(node1); + nodes.add(node2); + GraphGrpc graph = Client.createGraphGrpc(nodes); + //createGraph + graph = client.createGraph(graph).getGraph(); + + //getGraph + GraphGrpc retreivedGraph = client.getGraph(graph.getId()); + + assertNotNull("NULL Graph ",retreivedGraph); + assertEquals(graph.getId(), retreivedGraph.getId()); + + // check the name of first node and the id + compareString(retreivedGraph.getNodeList().get(0).getName(), graph.getNodeList().get(0).getName(), "node name"); + assertEquals(retreivedGraph.getNodeList().get(0).getId(), graph.getNodeList().get(0).getId()); + + // check the name of second node and the id + compareString(retreivedGraph.getNodeList().get(1).getName(), graph.getNodeList().get(1).getName(), "node name"); + assertEquals(retreivedGraph.getNodeList().get(1).getId(), graph.getNodeList().get(1).getId()); + + //updateGraph + GraphGrpc updatedGraph = GraphGrpc.newBuilder().build(); + NewGraph response = client.updateGraph(graph.getId(),updatedGraph); + + assertEquals(response.getSuccess(),true); + } + + @Test + public final void test2LoadWithError() throws Exception{ + // try to load a graph with node without functionalType + NodeGrpc node = null; + try{ + node = Client.createNodeGrpc("Node1", null, null, null); + fail( "createNodeGrpc didn't throw when I expected it to" ); + } + catch(Exception ex){ + } + List<NodeGrpc> nodes = new ArrayList<NodeGrpc>(); + if(node != null) + nodes.add(node); + + GraphGrpc graph = Client.createGraphGrpc(nodes); + graph = client.createGraph(graph).getGraph(); + + assertEquals(graph.getId(), 2); + + //getGraphs + Iterator<GraphGrpc> graphs = client.getGraphs().iterator(); + + assertEquals(graphs.next().getId(), 1); + assertEquals(graphs.next(), graph); + + //deleteGraph + boolean resp= client.deleteGraph(graph.getId()); + assertEquals(resp, true); + + List<GraphGrpc> listGraphs = client.getGraphs(); + + assertEquals(listGraphs.size(), 1); + assertEquals(listGraphs.get(0).getId(), 1); + } + + @Test + public void test3Node() throws Exception { + NodeGrpc ufoundedGraph = NodeGrpc.newBuilder() + .setErrorMessage("Node with id 1 not found in graph with id 1").build(); + + // graph not found in the server + NodeGrpc node = client.getNode(1, 1);//id not present + + assertEquals(ufoundedGraph, node); + + // graph found in the server, but first add it + NodeGrpc addedNode = Client.createNodeGrpc("Node4", "firewall", null, null); + NewNode response = client.createNode(addedNode, 1); + addedNode = response.getNode(); + node = client.getNode(1, 1); + + assertEquals(addedNode.getId(), node.getId()); + + //updateNode + NodeGrpc updatedNode = Client.createNodeGrpc("Node9", "endhost", null, null); + response = client.updateNode(1, addedNode.getId(), updatedNode); + + assertEquals(response.getSuccess(),true); + + //configureNode + //this configuration is valid only on endhost! + Map<String,String> params = new HashMap<String,String>(); + params.put("url", "www.facebook.com"); + params.put("body", "word"); + params.put("destination","server"); + params.put("protocol", "HTTP_REQUEST"); + ConfigurationGrpc configuration = Client.createConfigurationGrpc(params, null, null, null); + + boolean status = client.configureNode(1, 1, configuration); + + assertEquals(status,true); + } + + @Test + public void test4Nodes() throws Exception { + // setup + GraphGrpc graph = Client.createGraphGrpc(null); + //createGraph + graph = client.createGraph(graph).getGraph(); + + List<NeighbourGrpc> neighbours = new ArrayList<NeighbourGrpc>(); + NeighbourGrpc nb = Client.createNeighbourGrpc("Node6"); + neighbours.add(nb); + NodeGrpc n1 = Client.createNodeGrpc("Node6", "mailserver", null, null); + NodeGrpc n2 = Client.createNodeGrpc("Node9", "endhost", neighbours, null); + Map<String,String> map = new HashMap<String,String>(); + map.put("mailserver", "Node6"); + ConfigurationGrpc conf = Client.createConfigurationGrpc(map, null, null, null); + NodeGrpc n3 = Client.createNodeGrpc("Node10", "mailclient", null, conf); + NodeGrpc n4 = Client.createNodeGrpc("Node11", "nat", null, null); + + NewNode nw1 = client.createNode(n1, graph.getId()); + NewNode nw2 = client.createNode(n2, graph.getId()); + NewNode nw3 = client.createNode(n3, graph.getId()); + NewNode nw4 = client.createNode(n4, graph.getId()); + assertEquals(nw1.getSuccess(),true); + assertEquals(nw2.getSuccess(),true); + assertEquals(nw3.getSuccess(),true); + assertEquals(nw4.getSuccess(),true); + n1 = NodeGrpc.newBuilder(n1).setId(nw1.getNode().getId()).build(); + n2 = NodeGrpc.newBuilder(n2).setId(nw2.getNode().getId()).build(); + n3 = NodeGrpc.newBuilder(n3).setId(nw3.getNode().getId()).build(); + n4 = NodeGrpc.newBuilder(n4).setId(nw4.getNode().getId()).build(); + + // getNodes + Iterator<NodeGrpc> nodes = client.getNodes(graph.getId()).iterator(); + + assertEquals(nodes.next().getName(), n1.getName()); + assertEquals(nodes.next().getName(), n2.getName()); + assertEquals(nodes.next().getName(), n3.getName()); + assertEquals(nodes.next().getName(), n4.getName()); + + //deleteNode + client.deleteNode(graph.getId(), 1); + // run + nodes = client.getNodes(graph.getId()).iterator(); + + assertEquals(nodes.next().getName(), n2.getName()); + assertEquals(nodes.next().getName(), n3.getName()); + assertEquals(nodes.next().getName(), n4.getName()); + } + + @Test + public void test5Neighbours() throws Exception { + NeighbourGrpc ufoundedNeighbour = NeighbourGrpc.newBuilder() + .setErrorMessage("Neighbour with id 1 not found for node with id 1 in graph with id 1").build();; + + // Neighbour not found in the server + NeighbourGrpc neighbour = client.getNeighbour(1, 1, 1);//id not present + + assertEquals(ufoundedNeighbour, neighbour); + + GraphGrpc graph = Client.createGraphGrpc(null); + graph = client.createGraph(graph).getGraph(); + + List<NeighbourGrpc> neighbours = new ArrayList<NeighbourGrpc>(); + NeighbourGrpc nb = Client.createNeighbourGrpc("Node1"); + neighbours.add(nb); + NodeGrpc n1 = Client.createNodeGrpc("Node1", "antispam", null, null); + NodeGrpc n2 = Client.createNodeGrpc("Node2", "endhost", neighbours, null); + NodeGrpc n3 = Client.createNodeGrpc("Node3", "endhost", null, null); + NodeGrpc n4 = Client.createNodeGrpc("Node4", "endpoint", null, null); + NodeGrpc n5 = Client.createNodeGrpc("Node5", "webserver", null, null); + Map<String,String> map = new HashMap<String,String>(); + map.put("webserver", "Node5"); + ConfigurationGrpc conf = Client.createConfigurationGrpc(map, null, null, null); + NodeGrpc n6 = Client.createNodeGrpc("Node6", "webclient", null, conf); + NodeGrpc n7 = Client.createNodeGrpc("Node7", "cache", null, null); + NodeGrpc n8 = Client.createNodeGrpc("Node8", "firewall", null, null); + NodeGrpc n9 = Client.createNodeGrpc("Node9", "fieldmodifier", null, null); + NodeGrpc n10 = Client.createNodeGrpc("Node10", "dpi", null, null); + NewNode nw1 = client.createNode(n1, graph.getId()); + NewNode nw2 = client.createNode(n2, graph.getId()); + NewNode nw3 = client.createNode(n3, graph.getId()); + NewNode nw4 = client.createNode(n4, graph.getId()); + NewNode nw5 = client.createNode(n5, graph.getId()); + NewNode nw6 = client.createNode(n6, graph.getId()); + NewNode nw7 = client.createNode(n7, graph.getId()); + NewNode nw8 = client.createNode(n8, graph.getId()); + NewNode nw9 = client.createNode(n9, graph.getId()); + NewNode nw10 = client.createNode(n10, graph.getId()); + assertEquals(nw1.getSuccess(),true); + assertEquals(nw2.getSuccess(),true); + assertEquals(nw3.getSuccess(),true); + assertEquals(nw4.getSuccess(),true); + assertEquals(nw5.getSuccess(),true); + assertEquals(nw6.getSuccess(),true); + assertEquals(nw7.getSuccess(),true); + assertEquals(nw8.getSuccess(),true); + assertEquals(nw9.getSuccess(),true); + assertEquals(nw10.getSuccess(),true); + + // getNeighbour, but first add it + NeighbourGrpc addedNeighbour = Client.createNeighbourGrpc("Node9"); + NewNeighbour response = client.createNeighbour(addedNeighbour, graph.getId(), nw1.getNode().getId()); + addedNeighbour = response.getNeighbour(); + neighbour = client.getNeighbour(graph.getId(), nw1.getNode().getId(), addedNeighbour.getId()); + + assertEquals(addedNeighbour.getId(), neighbour.getId()); + + //updateNeighbour + NeighbourGrpc updatedNeighbour = Client.createNeighbourGrpc("Node10"); + + response = client.updateNeighbour(graph.getId(), 1, addedNeighbour.getId(),updatedNeighbour); + + assertEquals(response.getSuccess(),true); + assertEquals(response.getNeighbour().getName(),"Node10"); + } + + @Test + public void test6Neighbours() throws Exception { + // setup + GraphGrpc graph = Client.createGraphGrpc(null); + //createGraph + graph = client.createGraph(graph).getGraph(); + + NodeGrpc n1 = Client.createNodeGrpc("Node1", "antispam", null, null); + NodeGrpc n2 = Client.createNodeGrpc("Node2", "endhost", null, null); + NodeGrpc n3 = Client.createNodeGrpc("Node3", "endhost", null, null); + NodeGrpc n4 = Client.createNodeGrpc("Node4", "endpoint", null, null); + NewNode nw1 = client.createNode(n1, graph.getId()); + NewNode nw2 = client.createNode(n2, graph.getId()); + NewNode nw3 = client.createNode(n3, graph.getId()); + NewNode nw4 = client.createNode(n4, graph.getId()); + assertEquals(nw1.getSuccess(),true); + assertEquals(nw2.getSuccess(),true); + assertEquals(nw3.getSuccess(),true); + assertEquals(nw4.getSuccess(),true); + + //createNeighbour + NeighbourGrpc nn1 = Client.createNeighbourGrpc("Node2"); + NewNeighbour addedNeighbour1 = client.createNeighbour(nn1, graph.getId(), nw1.getNode().getId()); + assertEquals(addedNeighbour1.getSuccess(),true); + NeighbourGrpc nn2 = Client.createNeighbourGrpc("Node3"); + NewNeighbour addedNeighbour2 = client.createNeighbour(nn2, graph.getId(), nw1.getNode().getId()); + assertEquals(addedNeighbour2.getSuccess(),true); + NeighbourGrpc nn3 = Client.createNeighbourGrpc("Node4"); + NewNeighbour addedNeighbour3 = client.createNeighbour(nn3, graph.getId(), nw1.getNode().getId()); + assertEquals(addedNeighbour3.getSuccess(),true); + + nn1 = NeighbourGrpc.newBuilder(nn1).setId(1).build(); + nn2 = NeighbourGrpc.newBuilder(nn2).setId(2).build(); + nn3 = NeighbourGrpc.newBuilder(nn3).setId(3).build(); + // run + Iterator<NeighbourGrpc> neighbours = client.getNeighbours(graph.getId(), nw1.getNode().getId()).iterator(); + + assertEquals(neighbours.next(), nn1); + assertEquals(neighbours.next(), nn2); + assertEquals(neighbours.next(), nn3); + + //deleteNeighbour + boolean succ = client.deleteNeighbour(graph.getId(), nw1.getNode().getId(), 1); + assertEquals(succ, true); + // run + neighbours = client.getNeighbours(graph.getId(), nw1.getNode().getId()).iterator(); + + assertEquals(neighbours.next(), nn2); + assertEquals(neighbours.next(), nn3); + } +} diff --git a/verigraph/src/main/java/it/polito/grpc/test/MultiThreadTest.java b/verigraph/src/main/java/it/polito/grpc/test/MultiThreadTest.java new file mode 100644 index 0000000..5b76bea --- /dev/null +++ b/verigraph/src/main/java/it/polito/grpc/test/MultiThreadTest.java @@ -0,0 +1,220 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.grpc.test; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Random; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.junit.runners.MethodSorters; + +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; + +import io.grpc.verigraph.GraphGrpc; +import io.grpc.verigraph.NewGraph; +import io.grpc.verigraph.NodeGrpc; +import it.polito.escape.verify.client.VerifyClientException; +import it.polito.grpc.Client; +import it.polito.grpc.Service; + +/** + * Unit tests for gRPC project. + * For testing concurrency on server side. + */ +@RunWith(JUnit4.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class MultiThreadTest { + private Service server; + private Client client; + + @Before + public void setUp() throws Exception { + client = new Client("localhost" , 50051); + server = new Service(50051); + + server.start(); + } + + @After + public void tearDown() throws Exception { + server.stop(); + client.shutdown(); + } + + private void testUpdateGraphStatus(final int threadCount) throws InterruptedException, ExecutionException, JsonParseException, JsonMappingException, IOException, VerifyClientException { + GraphGrpc retrieveGraphResponse =client.getGraph(1); + + UpdateGraph task = new UpdateGraph(client, 1, retrieveGraphResponse); + + List<MultiThreadTest.UpdateGraph> tasks = Collections.nCopies(threadCount, task); + ExecutorService executorService = Executors.newFixedThreadPool(threadCount); + + List<Future<NewGraph>> futures = executorService.invokeAll(tasks); + List<Boolean> resultList = new ArrayList<Boolean>(futures.size()); + + // Check for exceptions + for (Future<NewGraph> future : futures) { + // Throws an exception if an exception was thrown by the task. + resultList.add(future.get().getSuccess()); + } + // Validate the dimensions + Assert.assertEquals(threadCount, futures.size()); + + List<Boolean> expectedList = new ArrayList<Boolean>(threadCount); + for (int i = 1; i <= threadCount; i++) { + expectedList.add(true); + } + // Validate expected results + Assert.assertEquals(expectedList, resultList); + } + + private void testUpdateGraph(final int threadCount) throws Exception { + GraphGrpc retrieveGraph = client.getGraph(2L); + NodeGrpc nodeToEdit = Client.createNodeGrpc("client", + "endpoint", + null, + Client.createConfigurationGrpc(null, null, "client", "")); + + GraphGrpc graphToUpdate = GraphGrpc.newBuilder(retrieveGraph).addNode(nodeToEdit).build(); + + String graphAsString = graphToUpdate.toString(); + + UpdateGraph task = new UpdateGraph(client, 2, graphToUpdate); + + List<MultiThreadTest.UpdateGraph> tasks = Collections.nCopies(threadCount, task); + ExecutorService executorService = Executors.newFixedThreadPool(threadCount); + + List<Future<NewGraph>> futures = executorService.invokeAll(tasks); + List<String> resultList = new ArrayList<String>(futures.size()); + + // Check for exceptions + for (Future<NewGraph> future : futures) { + // Throws an exception if an exception was thrown by the task. + GraphGrpc graphReceived = future.get().getGraph(); + NodeGrpc node = NodeGrpc.newBuilder(graphReceived.getNode(0)).setId(0).build(); + GraphGrpc graph = GraphGrpc.newBuilder(graphReceived).setNode(0, node).build(); + resultList.add(graph.toString()); + } + // Validate dimensions + Assert.assertEquals(threadCount, futures.size()); + + List<String> expectedList = new ArrayList<String>(threadCount); + for (int i = 1; i <= threadCount; i++) { + expectedList.add(graphAsString); + } + // Validate expected results + Assert.assertEquals(expectedList, resultList); + } + + private void testCreateGraphStatus(final int threadCount) throws InterruptedException, ExecutionException, JsonParseException, JsonMappingException, IOException { + + GraphGrpc graph = GraphGrpc.newBuilder().build(); + + CreateGraph task = new CreateGraph(client, graph); + + List<MultiThreadTest.CreateGraph> tasks = Collections.nCopies(threadCount, task); + ExecutorService executorService = Executors.newFixedThreadPool(threadCount); + + List<Future<Boolean>> futures = executorService.invokeAll(tasks); + List<Boolean> resultList = new ArrayList<Boolean>(futures.size()); + + // Check for exceptions + for (Future<Boolean> future : futures) { + // Throws an exception if an exception was thrown by the task. + resultList.add(future.get()); + } + // Validate the IDs + Assert.assertEquals(threadCount, futures.size()); + + List<Boolean> expectedList = new ArrayList<Boolean>(threadCount); + for (int i = 1; i <= threadCount; i++) { + expectedList.add(true); + } + // Validate expected results + Assert.assertEquals(expectedList, resultList); + } + + private int randInt(int min, int max){ + Random rand = new Random(); + int randomNum = rand.nextInt((max - min) + 1) + min; + return randomNum; + } + + @Test + public void updateGraphStatusCheck() throws InterruptedException, ExecutionException, JsonParseException, JsonMappingException, IOException, VerifyClientException { + testUpdateGraphStatus(64); + } + + @Test + public void updateGraphResponseCheck() throws Exception { + testUpdateGraph(16); + } + + @Test + public void createGraphStatusCheck() throws JsonParseException, JsonMappingException, InterruptedException, ExecutionException, IOException { + testCreateGraphStatus(8); + } + + class UpdateGraph implements Callable<NewGraph> { + + private Client verifyClient; + + private int graphId; + + private GraphGrpc graph; + + public UpdateGraph(Client verifyClient, int graphId, GraphGrpc graph) { + this.graphId = graphId; + this.graph = graph; + this.verifyClient = verifyClient; + } + + @Override + public NewGraph call() throws Exception { + Thread.sleep(randInt(0,2000)); + return this.verifyClient.updateGraph(this.graphId, this.graph); + } + } + + class CreateGraph implements Callable<Boolean> { + + private Client verifyClient; + + private GraphGrpc graph; + + public CreateGraph(Client verifyClient, GraphGrpc graph) { + this.graph = graph; + this.verifyClient = verifyClient; + } + + @Override + public Boolean call() throws Exception { + Thread.sleep(randInt(0,2000)); + return this.verifyClient.createGraph(this.graph).getSuccess(); + } + + } + +} diff --git a/verigraph/src/main/java/it/polito/grpc/test/ReachabilityTest.java b/verigraph/src/main/java/it/polito/grpc/test/ReachabilityTest.java new file mode 100644 index 0000000..a120aff --- /dev/null +++ b/verigraph/src/main/java/it/polito/grpc/test/ReachabilityTest.java @@ -0,0 +1,252 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.grpc.test; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.junit.After; +import org.junit.Before; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.junit.runners.MethodSorters; + +import static org.junit.Assert.assertEquals; + +import java.io.BufferedReader; +import java.io.FilenameFilter; +import java.io.InputStreamReader; + +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.github.fge.jsonschema.core.exceptions.ProcessingException; +import com.github.fge.jsonschema.main.JsonSchema; + +import io.grpc.verigraph.GraphGrpc; +import io.grpc.verigraph.NewGraph; +import io.grpc.verigraph.Policy; +import io.grpc.verigraph.VerificationGrpc; +import it.polito.escape.verify.client.VerifyClientException; +import it.polito.escape.verify.service.ValidationUtils; +import it.polito.escape.verify.test.TestCase; +import it.polito.escape.verify.test.TestExecutionException; +import it.polito.grpc.Client; +import it.polito.grpc.GrpcUtils; +import it.polito.grpc.Service; + +@RunWith(JUnit4.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class ReachabilityTest { + private File schema; + private List<File> testFiles = new ArrayList<File>(); + private List<TestCase> testCases = new ArrayList<TestCase>(); + private Client client; + private Service server; + + @Before + public void setUpBeforeClass() throws Exception { + client = new Client("localhost" , 50051); + server = new Service(50051); + server.start(); + + String folderName = System.getProperty("user.dir") + "/tester/testcases"; + File folder = new File(folderName); + if (!folder.exists()) { + BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); + String s; + do{ + System.out.println("Please enter the testcases folder path: "); + s = in.readLine(); + if (isValidpath(s)){ + folder = new File(s); + break; + } + }while (s != null && s.length() != 0); + if(s == null) + System.exit(0); + } + String schemaName = System.getProperty("user.dir") + "/tester/testcase_schema.json"; + File schema = new File(schemaName); + if (!schema.exists()) { + BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); + String s; + do{ + System.out.println("Please enter the full path of 'testcase_schema.json': "); + s = in.readLine(); + if (isValidpath(s)){ + folder = new File(s); + break; + } + }while (s != null && s.length() != 0); + if(s == null) + System.exit(0); + } + + this.schema = schema; + this.testFiles = getTests(folder); + this.testCases = getTestCases(this.testFiles); + } + + @After + public void tearDown() throws Exception { + server.stop(); + client.shutdown(); + } + + @Test + public final void wrongReachability() { + System.out.println("DEBUG: starting testWrongReachability"); + + VerificationGrpc nullVer = VerificationGrpc.newBuilder() + .setErrorMessage("Graph with id 52 not found").build(); + //verification on uncreated graph + Policy policyToVerify = Client.createPolicy("Node1", "Node4", "reachability", null, 52); + VerificationGrpc ver = client.verify(policyToVerify); + assertEquals(ver, nullVer); + + //verification on uncreated nodes + nullVer = VerificationGrpc.newBuilder() + .setErrorMessage("The \'source\' parameter \'Node5\' is not valid, please insert the name of an existing node").build(); + policyToVerify = Client.createPolicy("Node5", "Node4", "reachability", null, 1); + ver = client.verify(policyToVerify); + assertEquals(ver, nullVer); + + //verification on uncreated nodes + nullVer = VerificationGrpc.newBuilder() + .setErrorMessage("The \'source\' parameter \'Node1\' is not valid, please insert the name of an existing node").build(); + + policyToVerify = Client.createPolicy("Node1", "Node10", "reachability", null, 1); + ver = client.verify(policyToVerify); + assertEquals(ver, nullVer); + + } + + public List<File> getTests(File folder) { + List<File> filesList = new ArrayList<File>(); + + System.out.println("Test folder set to '" + folder.getAbsolutePath() + "'"); + + File[] files = folder.listFiles(new FilenameFilter() { + + @Override + public boolean accept(File dir, String name) { + return name.endsWith(".json"); + } + }); + + for (File f : files) { + filesList.add(f); + System.out.println("File '" + f.getName() + "' added to test files"); + } + + return filesList; + } + + public List<TestCase> getTestCases(List<File> files) throws JsonParseException, JsonMappingException, IOException, + Exception { + List<TestCase> testCases = new ArrayList<TestCase>(); + + for (File file : files) { + validateTestFile(file); + try { + TestCase tc = new ObjectMapper().readValue(file, TestCase.class); + testCases.add(tc); + } + catch (Exception e) { + throw e; + } + } + + return testCases; + } + + @Test + public void runTestCases() throws VerifyClientException, TestExecutionException { + int counter = 0; + for (TestCase tc : this.testCases) { + String result = runTestCase(tc); + if (!result.equals(tc.getResult())) + throw new TestExecutionException("Error running test given in file '" + this.testFiles.get(counter).getName() + + "'. Test returned '" + result + "' instead of '" + tc.getResult() + "'."); + else + System.out.println("Test given in file '" + this.testFiles.get(counter).getName() + "' returned '" + + result + "' as expected"); + counter++; + + } + System.out.println("All tests PASSED"); + } + + private String runTestCase(TestCase tc) throws VerifyClientException, TestExecutionException{ + GraphGrpc graph = GrpcUtils.obtainGraph(tc.getGraph()); + + NewGraph newGraph = this.client.createGraph(graph); + if(newGraph.getSuccess() == false) + throw new VerifyClientException("gRPC request failed"); + GraphGrpc createdGraph = newGraph.getGraph(); + + GraphGrpc addedgraph = client.getGraph(createdGraph.getId()); + System.out.println(addedgraph); + + final Map<String, String> map = GrpcUtils.getParamGivenString(tc.getPolicyUrlParameters()); + + Policy policy = Client.createPolicy(map.get("source"), + map.get("destination"), + map.get("type"), + map.get("middlebox"), + createdGraph.getId()); + VerificationGrpc verification = this.client.verify(policy); + return verification.getResult(); + } + + public void validateTestFile(File testFile) throws Exception { + JsonSchema schemaNode = null; + try { + schemaNode = ValidationUtils.getSchemaNode(schema); + } + catch (IOException e) { + throw new Exception("Unable to load '" + schema.getAbsolutePath() + "' schema file"); + } + catch (ProcessingException e) { + throw new Exception("Unable to resolve '" + schema.getAbsolutePath() + "' schema file as a schema node"); + } + + JsonNode jsonNode; + try { + jsonNode = ValidationUtils.getJsonNode(testFile); + } + catch (IOException e) { + throw new Exception("Unable to load '" + testFile.getAbsolutePath() + "' as a json node"); + } + + try { + ValidationUtils.validateJson(schemaNode, jsonNode); + } + catch (ProcessingException e) { + throw new Exception("There were errors in the validation of file '" + testFile.getAbsolutePath() + + "' against the json schema '" + schema.getAbsolutePath() + "': " + e.getMessage()); + + } + } + + private static boolean isValidpath(String s) { + if (s==null) + return false; + File file = new File(s); + return file.exists(); + } +} diff --git a/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/ActionEnumType.java b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/ActionEnumType.java new file mode 100644 index 0000000..e7504b5 --- /dev/null +++ b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/ActionEnumType.java @@ -0,0 +1,59 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.nffg.neo4j.jaxb; + +import javax.xml.bind.annotation.XmlEnum; +import javax.xml.bind.annotation.XmlEnumValue; +import javax.xml.bind.annotation.XmlType; + + +/** + * <p>Java class for actionEnumType. + * + * <p>The following schema fragment specifies the expected content contained within this class. + * <p> + * <pre> + * <simpleType name="actionEnumType"> + * <restriction base="{http://www.w3.org/2001/XMLSchema}string"> + * <enumeration value="discard"/> + * <enumeration value="output"/> + * </restriction> + * </simpleType> + * </pre> + * + */ +@XmlType(name = "actionEnumType") +@XmlEnum +public enum ActionEnumType { + + @XmlEnumValue("discard") + DISCARD("discard"), + @XmlEnumValue("output") + OUTPUT("output"); + private final String value; + + ActionEnumType(String v) { + value = v; + } + + public String value() { + return value; + } + + public static ActionEnumType fromValue(String v) { + for (ActionEnumType c: ActionEnumType.values()) { + if (c.value.equals(v)) { + return c; + } + } + throw new IllegalArgumentException(v); + } + +} diff --git a/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/ActionType.java b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/ActionType.java new file mode 100644 index 0000000..db86975 --- /dev/null +++ b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/ActionType.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.nffg.neo4j.jaxb; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlType; + + +/** + * <p>Java class for actionType complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType name="actionType"> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <attribute name="type" use="required" type="{http://www.example.org/nffg/}actionEnumType" /> + * <attribute name="port" type="{http://www.w3.org/2001/XMLSchema}string" /> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "actionType") +public class ActionType { + + @XmlAttribute(name = "type", required = true) + protected ActionEnumType type; + @XmlAttribute(name = "port") + protected String port; + + /** + * Gets the value of the type property. + * @return + * possible object is + * {@link ActionEnumType } + */ + public ActionEnumType getType() { + return type; + } + + /** + * Sets the value of the type property. + * @param value + * allowed object is + * {@link ActionEnumType } + */ + public void setType(ActionEnumType value) { + this.type = value; + } + + /** + * Gets the value of the port property. + * @return + * possible object is + * {@link String } + */ + public String getPort() { + return port; + } + + /** + * Sets the value of the port property. + * @param value + * allowed object is + * {@link String } + */ + public void setPort(String value) { + this.port = value; + } + +} diff --git a/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/ActionsType.java b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/ActionsType.java new file mode 100644 index 0000000..5b81ae7 --- /dev/null +++ b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/ActionsType.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.nffg.neo4j.jaxb; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + * <p>Java class for actionsType complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType name="actionsType"> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <sequence> + * <element name="action" type="{http://www.example.org/nffg/}actionType" maxOccurs="unbounded"/> + * </sequence> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "actionsType", propOrder = { + "action" +}) +public class ActionsType { + + @XmlElement(required = true) + protected List<ActionType> action; + + /** + * Gets the value of the action property. + * <p> + * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a <CODE>set</CODE> method for the action property. + * <p> + * For example, to add a new item, do as follows: + * <pre> + * getAction().add(newItem); + * </pre> + * <p> + * Objects of the following type(s) are allowed in the list + * {@link ActionType } + */ + public List<ActionType> getAction() { + if (action == null) { + action = new ArrayList<ActionType>(); + } + return this.action; + } + +} diff --git a/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/CiType.java b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/CiType.java new file mode 100644 index 0000000..9a82728 --- /dev/null +++ b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/CiType.java @@ -0,0 +1,206 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.nffg.neo4j.jaxb; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + * <p>Java class for ciType complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType name="ciType"> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <sequence> + * <element name="attributes"> + * <complexType> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <sequence> + * <element name="attribute" maxOccurs="unbounded" minOccurs="0"> + * <complexType> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <attribute name="value" use="required" type="{http://www.w3.org/2001/XMLSchema}string" /> + * </restriction> + * </complexContent> + * </complexType> + * </element> + * </sequence> + * </restriction> + * </complexContent> + * </complexType> + * </element> + * </sequence> + * <attribute name="id" use="required" type="{http://www.example.org/nffg/}ciIdType" /> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "ciType", propOrder = { + "attributes" +}) +public class CiType { + + @XmlElement(required = true) + protected CiType.Attributes attributes; + @XmlAttribute(name = "id", required = true) + protected String id; + + /** + * Gets the value of the attributes property. + * @return + * possible object is + * {@link CiType.Attributes } + */ + public CiType.Attributes getAttributes() { + return attributes; + } + + /** + * Sets the value of the attributes property. + * @param value + * allowed object is + * {@link CiType.Attributes } + */ + public void setAttributes(CiType.Attributes value) { + this.attributes = value; + } + + /** + * Gets the value of the id property. + * @return + * possible object is + * {@link String } + */ + public String getId() { + return id; + } + + /** + * Sets the value of the id property. + * @param value + * allowed object is + * {@link String } + */ + public void setId(String value) { + this.id = value; + } + + + /** + * <p>Java class for anonymous complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <sequence> + * <element name="attribute" maxOccurs="unbounded" minOccurs="0"> + * <complexType> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <attribute name="value" use="required" type="{http://www.w3.org/2001/XMLSchema}string" /> + * </restriction> + * </complexContent> + * </complexType> + * </element> + * </sequence> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "", propOrder = { + "attribute" + }) + public static class Attributes { + + protected List<CiType.Attributes.Attribute> attribute; + + /** + * Gets the value of the attribute property. + * <p> + * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a <CODE>set</CODE> method for the attribute property. + * <p> + * For example, to add a new item, do as follows: + * <pre> + * getAttribute().add(newItem); + * </pre> + * <p> + * Objects of the following type(s) are allowed in the list + * {@link CiType.Attributes.Attribute } + */ + public List<CiType.Attributes.Attribute> getAttribute() { + if (attribute == null) { + attribute = new ArrayList<CiType.Attributes.Attribute>(); + } + return this.attribute; + } + + + /** + * <p>Java class for anonymous complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <attribute name="value" use="required" type="{http://www.w3.org/2001/XMLSchema}string" /> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "") + public static class Attribute { + + @XmlAttribute(name = "value", required = true) + protected String value; + + /** + * Gets the value of the value property. + * @return + * possible object is + * {@link String } + */ + public String getValue() { + return value; + } + + /** + * Sets the value of the value property. + * @param value + * allowed object is + * {@link String } + */ + public void setValue(String value) { + this.value = value; + } + + } + + } + +} diff --git a/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/CpType.java b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/CpType.java new file mode 100644 index 0000000..4a67b79 --- /dev/null +++ b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/CpType.java @@ -0,0 +1,86 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.nffg.neo4j.jaxb; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + * <p>Java class for cpType complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType name="cpType"> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <sequence> + * <element name="port" type="{http://www.example.org/nffg/}portType"/> + * </sequence> + * <attribute name="id" use="required" type="{http://www.example.org/nffg/}cpIdType" /> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "cpType", propOrder = { + "port" +}) +public class CpType { + + @XmlElement(required = true) + protected PortType port; + @XmlAttribute(name = "id", required = true) + protected String id; + + /** + * Gets the value of the port property. + * @return + * possible object is + * {@link PortType } + */ + public PortType getPort() { + return port; + } + + /** + * Sets the value of the port property. + * @param value + * allowed object is + * {@link PortType } + */ + public void setPort(PortType value) { + this.port = value; + } + + /** + * Gets the value of the id property. + * @return + * possible object is + * {@link String } + */ + public String getId() { + return id; + } + + /** + * Sets the value of the id property. + * @param value + * allowed object is + * {@link String } + */ + public void setId(String value) { + this.id = value; + } + +} diff --git a/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/CpointsType.java b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/CpointsType.java new file mode 100644 index 0000000..4c820ed --- /dev/null +++ b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/CpointsType.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.nffg.neo4j.jaxb; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + * <p>Java class for cpointsType complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType name="cpointsType"> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <sequence> + * <element name="connection_point" type="{http://www.example.org/nffg/}cpType" maxOccurs="unbounded"/> + * </sequence> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "cpointsType", propOrder = { + "connectionPoint" +}) +public class CpointsType { + + @XmlElement(name = "connection_point", required = true) + protected List<CpType> connectionPoint; + + /** + * Gets the value of the connectionPoint property. + * <p> + * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a <CODE>set</CODE> method for the connectionPoint property. + * <p> + * For example, to add a new item, do as follows: + * <pre> + * getConnectionPoint().add(newItem); + * </pre> + * <p> + * Objects of the following type(s) are allowed in the list + * {@link CpType } + */ + public List<CpType> getConnectionPoint() { + if (connectionPoint == null) { + connectionPoint = new ArrayList<CpType>(); + } + return this.connectionPoint; + } + +} diff --git a/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/CtrlInterfacesType.java b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/CtrlInterfacesType.java new file mode 100644 index 0000000..02ad675 --- /dev/null +++ b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/CtrlInterfacesType.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.nffg.neo4j.jaxb; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + * <p>Java class for ctrlInterfacesType complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType name="ctrlInterfacesType"> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <sequence> + * <element name="control_interface" type="{http://www.example.org/nffg/}ciType" maxOccurs="unbounded" minOccurs="0"/> + * </sequence> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "ctrlInterfacesType", propOrder = { + "controlInterface" +}) +public class CtrlInterfacesType { + + @XmlElement(name = "control_interface") + protected List<CiType> controlInterface; + + /** + * Gets the value of the controlInterface property. + * <p> + * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a <CODE>set</CODE> method for the controlInterface property. + * <p> + * For example, to add a new item, do as follows: + * <pre> + * getControlInterface().add(newItem); + * </pre> + * <p> + * Objects of the following type(s) are allowed in the list + * {@link CiType } + */ + public List<CiType> getControlInterface() { + if (controlInterface == null) { + controlInterface = new ArrayList<CiType>(); + } + return this.controlInterface; + } + +} diff --git a/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/EpCpType.java b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/EpCpType.java new file mode 100644 index 0000000..a9448c1 --- /dev/null +++ b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/EpCpType.java @@ -0,0 +1,89 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.nffg.neo4j.jaxb; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlType; + + +/** + * <p>Java class for ep-cpType complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType name="ep-cpType"> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <sequence> + * <element name="flowrules" type="{http://www.example.org/nffg/}flowrulesType" maxOccurs="unbounded" minOccurs="0"/> + * </sequence> + * <attribute name="id_ref" use="required" type="{http://www.w3.org/2001/XMLSchema}string" /> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "ep-cpType", propOrder = { + "flowrules" +}) +public class EpCpType { + + protected List<FlowrulesType> flowrules; + @XmlAttribute(name = "id_ref", required = true) + protected String idRef; + + /** + * Gets the value of the flowrules property. + * <p> + * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a <CODE>set</CODE> method for the flowrules property. + * <p> + * For example, to add a new item, do as follows: + * <pre> + * getFlowrules().add(newItem); + * </pre> + * <p> + * Objects of the following type(s) are allowed in the list + * {@link FlowrulesType } + */ + public List<FlowrulesType> getFlowrules() { + if (flowrules == null) { + flowrules = new ArrayList<FlowrulesType>(); + } + return this.flowrules; + } + + /** + * Gets the value of the idRef property. + * @return + * possible object is + * {@link String } + */ + public String getIdRef() { + return idRef; + } + + /** + * Sets the value of the idRef property. + * @param value + * allowed object is + * {@link String } + */ + public void setIdRef(String value) { + this.idRef = value; + } + +} diff --git a/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/EpType.java b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/EpType.java new file mode 100644 index 0000000..2ae875d --- /dev/null +++ b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/EpType.java @@ -0,0 +1,260 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.nffg.neo4j.jaxb; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + * <p>Java class for epType complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType name="epType"> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <sequence> + * <element name="flowspace"> + * <complexType> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <sequence> + * <group ref="{http://www.example.org/nffg/}L2HeaderParameters"/> + * <group ref="{http://www.example.org/nffg/}L3HeaderParameters"/> + * <group ref="{http://www.example.org/nffg/}L4HeaderParameters"/> + * </sequence> + * <attribute name="nodeId" type="{http://www.w3.org/2001/XMLSchema}string" /> + * <attribute name="ingPhysPort" type="{http://www.w3.org/2001/XMLSchema}string" /> + * </restriction> + * </complexContent> + * </complexType> + * </element> + * </sequence> + * <attribute name="id" use="required" type="{http://www.example.org/nffg/}epIdType" /> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "epType", propOrder = { + "flowspace" +}) +public class EpType { + + @XmlElement(required = true) + protected EpType.Flowspace flowspace; + @XmlAttribute(name = "id", required = true) + protected String id; + + /** + * Gets the value of the flowspace property. + * @return + * possible object is + * {@link EpType.Flowspace } + */ + public EpType.Flowspace getFlowspace() { + return flowspace; + } + + /** + * Sets the value of the flowspace property. + * @param value + * allowed object is + * {@link EpType.Flowspace } + */ + public void setFlowspace(EpType.Flowspace value) { + this.flowspace = value; + } + + /** + * Gets the value of the id property. + * @return + * possible object is + * {@link String } + */ + public String getId() { + return id; + } + + /** + * Sets the value of the id property. + * @param value + * allowed object is + * {@link String } + */ + public void setId(String value) { + this.id = value; + } + + + /** + * <p>Java class for anonymous complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <sequence> + * <group ref="{http://www.example.org/nffg/}L2HeaderParameters"/> + * <group ref="{http://www.example.org/nffg/}L3HeaderParameters"/> + * <group ref="{http://www.example.org/nffg/}L4HeaderParameters"/> + * </sequence> + * <attribute name="nodeId" type="{http://www.w3.org/2001/XMLSchema}string" /> + * <attribute name="ingPhysPort" type="{http://www.w3.org/2001/XMLSchema}string" /> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "", propOrder = { + "mac", + "ip", + "tcp", + "udp" + }) + public static class Flowspace { + + protected it.polito.nffg.neo4j.jaxb.FlowrulesType.Flowspace.Mac mac; + protected it.polito.nffg.neo4j.jaxb.FlowrulesType.Flowspace.Ip ip; + protected it.polito.nffg.neo4j.jaxb.FlowrulesType.Flowspace.Tcp tcp; + protected it.polito.nffg.neo4j.jaxb.FlowrulesType.Flowspace.Udp udp; + @XmlAttribute(name = "nodeId") + protected String nodeId; + @XmlAttribute(name = "ingPhysPort") + protected String ingPhysPort; + + /** + * Gets the value of the mac property. + * @return + * possible object is + * {@link it.polito.nffg.neo4j.jaxb.FlowrulesType.Flowspace.Mac } + */ + public it.polito.nffg.neo4j.jaxb.FlowrulesType.Flowspace.Mac getMac() { + return mac; + } + + /** + * Sets the value of the mac property. + * @param value + * allowed object is + * {@link it.polito.nffg.neo4j.jaxb.FlowrulesType.Flowspace.Mac } + */ + public void setMac(it.polito.nffg.neo4j.jaxb.FlowrulesType.Flowspace.Mac value) { + this.mac = value; + } + + /** + * Gets the value of the ip property. + * @return + * possible object is + * {@link it.polito.nffg.neo4j.jaxb.FlowrulesType.Flowspace.Ip } + */ + public it.polito.nffg.neo4j.jaxb.FlowrulesType.Flowspace.Ip getIp() { + return ip; + } + + /** + * Sets the value of the ip property. + * @param value + * allowed object is + * {@link it.polito.nffg.neo4j.jaxb.FlowrulesType.Flowspace.Ip } + */ + public void setIp(it.polito.nffg.neo4j.jaxb.FlowrulesType.Flowspace.Ip value) { + this.ip = value; + } + + /** + * Gets the value of the tcp property. + * @return + * possible object is + * {@link it.polito.nffg.neo4j.jaxb.FlowrulesType.Flowspace.Tcp } + */ + public it.polito.nffg.neo4j.jaxb.FlowrulesType.Flowspace.Tcp getTcp() { + return tcp; + } + + /** + * Sets the value of the tcp property. + * @param value + * allowed object is + * {@link it.polito.nffg.neo4j.jaxb.FlowrulesType.Flowspace.Tcp } + */ + public void setTcp(it.polito.nffg.neo4j.jaxb.FlowrulesType.Flowspace.Tcp value) { + this.tcp = value; + } + + /** + * Gets the value of the udp property. + * @return + * possible object is + * {@link it.polito.nffg.neo4j.jaxb.FlowrulesType.Flowspace.Udp } + */ + public it.polito.nffg.neo4j.jaxb.FlowrulesType.Flowspace.Udp getUdp() { + return udp; + } + + /** + * Sets the value of the udp property. + * @param value + * allowed object is + * {@link it.polito.nffg.neo4j.jaxb.FlowrulesType.Flowspace.Udp } + */ + public void setUdp(it.polito.nffg.neo4j.jaxb.FlowrulesType.Flowspace.Udp value) { + this.udp = value; + } + + /** + * Gets the value of the nodeId property. + * @return + * possible object is + * {@link String } + */ + public String getNodeId() { + return nodeId; + } + + /** + * Sets the value of the nodeId property. + * @param value + * allowed object is + * {@link String } + */ + public void setNodeId(String value) { + this.nodeId = value; + } + + /** + * Gets the value of the ingPhysPort property. + * @return + * possible object is + * {@link String } + */ + public String getIngPhysPort() { + return ingPhysPort; + } + + /** + * Sets the value of the ingPhysPort property. + * @param value + * allowed object is + * {@link String } + */ + public void setIngPhysPort(String value) { + this.ingPhysPort = value; + } + + } + +} diff --git a/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/EpointsType.java b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/EpointsType.java new file mode 100644 index 0000000..850d8b6 --- /dev/null +++ b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/EpointsType.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.nffg.neo4j.jaxb; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlType; + + +/** + * <p>Java class for epointsType complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType name="epointsType"> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <sequence> + * <element name="endpoint" type="{http://www.example.org/nffg/}epType" maxOccurs="unbounded" minOccurs="0"/> + * </sequence> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "epointsType", propOrder = { + "endpoint" +}) +public class EpointsType { + + protected List<EpType> endpoint; + + /** + * Gets the value of the endpoint property. + * <p> + * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a <CODE>set</CODE> method for the endpoint property. + * <p> + * For example, to add a new item, do as follows: + * <pre> + * getEndpoint().add(newItem); + * </pre> + * <p> + * Objects of the following type(s) are allowed in the list + * {@link EpType } + */ + public List<EpType> getEndpoint() { + if (endpoint == null) { + endpoint = new ArrayList<EpType>(); + } + return this.endpoint; + } + +} diff --git a/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/EpsCpsType.java b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/EpsCpsType.java new file mode 100644 index 0000000..181085e --- /dev/null +++ b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/EpsCpsType.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.nffg.neo4j.jaxb; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + * <p>Java class for eps-cpsType complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType name="eps-cpsType"> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <sequence> + * <element name="ep-cp" type="{http://www.example.org/nffg/}ep-cpType" maxOccurs="unbounded" minOccurs="0"/> + * </sequence> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "eps-cpsType", propOrder = { + "epCp" +}) +public class EpsCpsType { + + @XmlElement(name = "ep-cp") + protected List<EpCpType> epCp; + + /** + * Gets the value of the epCp property. + * <p> + * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a <CODE>set</CODE> method for the epCp property. + * <p> + * For example, to add a new item, do as follows: + * <pre> + * getEpCp().add(newItem); + * </pre> + * <p> + * Objects of the following type(s) are allowed in the list + * {@link EpCpType } + */ + public List<EpCpType> getEpCp() { + if (epCp == null) { + epCp = new ArrayList<EpCpType>(); + } + return this.epCp; + } + +} diff --git a/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/FlowrulesType.java b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/FlowrulesType.java new file mode 100644 index 0000000..53c8f79 --- /dev/null +++ b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/FlowrulesType.java @@ -0,0 +1,619 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.nffg.neo4j.jaxb; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + + +/** + * <p>Java class for flowrulesType complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType name="flowrulesType"> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <sequence> + * <element name="flowspace"> + * <complexType> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <sequence> + * <group ref="{http://www.example.org/nffg/}L2HeaderParameters"/> + * <group ref="{http://www.example.org/nffg/}L3HeaderParameters"/> + * <group ref="{http://www.example.org/nffg/}L4HeaderParameters"/> + * </sequence> + * <attribute name="ingPort" type="{http://www.w3.org/2001/XMLSchema}string" /> + * </restriction> + * </complexContent> + * </complexType> + * </element> + * <element name="actions" type="{http://www.example.org/nffg/}actionsType"/> + * </sequence> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "flowrulesType", propOrder = { + "flowspace", + "actions" +}) +public class FlowrulesType { + + @XmlElement(required = true) + protected FlowrulesType.Flowspace flowspace; + @XmlElement(required = true) + protected ActionsType actions; + + /** + * Gets the value of the flowspace property. + * @return + * possible object is + * {@link FlowrulesType.Flowspace } + */ + public FlowrulesType.Flowspace getFlowspace() { + return flowspace; + } + + /** + * Sets the value of the flowspace property. + * @param value + * allowed object is + * {@link FlowrulesType.Flowspace } + */ + public void setFlowspace(FlowrulesType.Flowspace value) { + this.flowspace = value; + } + + /** + * Gets the value of the actions property. + * @return + * possible object is + * {@link ActionsType } + */ + public ActionsType getActions() { + return actions; + } + + /** + * Sets the value of the actions property. + * @param value + * allowed object is + * {@link ActionsType } + */ + public void setActions(ActionsType value) { + this.actions = value; + } + + + /** + * <p>Java class for anonymous complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <sequence> + * <group ref="{http://www.example.org/nffg/}L2HeaderParameters"/> + * <group ref="{http://www.example.org/nffg/}L3HeaderParameters"/> + * <group ref="{http://www.example.org/nffg/}L4HeaderParameters"/> + * </sequence> + * <attribute name="ingPort" type="{http://www.w3.org/2001/XMLSchema}string" /> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "", propOrder = { + "mac", + "ip", + "tcp", + "udp" + }) + public static class Flowspace { + + protected FlowrulesType.Flowspace.Mac mac; + protected FlowrulesType.Flowspace.Ip ip; + protected FlowrulesType.Flowspace.Tcp tcp; + protected FlowrulesType.Flowspace.Udp udp; + @XmlAttribute(name = "ingPort") + protected String ingPort; + + /** + * Gets the value of the mac property. + * @return + * possible object is + * {@link FlowrulesType.Flowspace.Mac } + */ + public FlowrulesType.Flowspace.Mac getMac() { + return mac; + } + + /** + * Sets the value of the mac property. + * @param value + * allowed object is + * {@link FlowrulesType.Flowspace.Mac } + */ + public void setMac(FlowrulesType.Flowspace.Mac value) { + this.mac = value; + } + + /** + * Gets the value of the ip property. + * @return + * possible object is + * {@link FlowrulesType.Flowspace.Ip } + */ + public FlowrulesType.Flowspace.Ip getIp() { + return ip; + } + + /** + * Sets the value of the ip property. + * @param value + * allowed object is + * {@link FlowrulesType.Flowspace.Ip } + */ + public void setIp(FlowrulesType.Flowspace.Ip value) { + this.ip = value; + } + + /** + * Gets the value of the tcp property. + * @return + * possible object is + * {@link FlowrulesType.Flowspace.Tcp } + */ + public FlowrulesType.Flowspace.Tcp getTcp() { + return tcp; + } + + /** + * Sets the value of the tcp property. + * @param value + * allowed object is + * {@link FlowrulesType.Flowspace.Tcp } + */ + public void setTcp(FlowrulesType.Flowspace.Tcp value) { + this.tcp = value; + } + + /** + * Gets the value of the udp property. + * @return + * possible object is + * {@link FlowrulesType.Flowspace.Udp } + */ + public FlowrulesType.Flowspace.Udp getUdp() { + return udp; + } + + /** + * Sets the value of the udp property. + * @param value + * allowed object is + * {@link FlowrulesType.Flowspace.Udp } + */ + public void setUdp(FlowrulesType.Flowspace.Udp value) { + this.udp = value; + } + + /** + * Gets the value of the ingPort property. + * @return + * possible object is + * {@link String } + */ + public String getIngPort() { + return ingPort; + } + + /** + * Sets the value of the ingPort property. + * @param value + * allowed object is + * {@link String } + */ + public void setIngPort(String value) { + this.ingPort = value; + } + + + /** + * <p>Java class for anonymous complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <attribute name="src" type="{http://www.example.org/net/}ipAddressType" /> + * <attribute name="dst" type="{http://www.example.org/net/}ipAddressType" /> + * <attribute name="ipProtocol" type="{http://www.w3.org/2001/XMLSchema}unsignedByte" /> + * <attribute name="tos" type="{http://www.w3.org/2001/XMLSchema}unsignedByte" /> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "") + public static class Ip { + + @XmlAttribute(name = "src") + protected String src; + @XmlAttribute(name = "dst") + protected String dst; + @XmlAttribute(name = "ipProtocol") + @XmlSchemaType(name = "unsignedByte") + protected Short ipProtocol; + @XmlAttribute(name = "tos") + @XmlSchemaType(name = "unsignedByte") + protected Short tos; + + /** + * Gets the value of the src property. + * @return + * possible object is + * {@link String } + */ + public String getSrc() { + return src; + } + + /** + * Sets the value of the src property. + * @param value + * allowed object is + * {@link String } + */ + public void setSrc(String value) { + this.src = value; + } + + /** + * Gets the value of the dst property. + * @return + * possible object is + * {@link String } + */ + public String getDst() { + return dst; + } + + /** + * Sets the value of the dst property. + * @param value + * allowed object is + * {@link String } + */ + public void setDst(String value) { + this.dst = value; + } + + /** + * Gets the value of the ipProtocol property. + * @return + * possible object is + * {@link Short } + */ + public Short getIpProtocol() { + return ipProtocol; + } + + /** + * Sets the value of the ipProtocol property. + * @param value + * allowed object is + * {@link Short } + */ + public void setIpProtocol(Short value) { + this.ipProtocol = value; + } + + /** + * Gets the value of the tos property. + * @return + * possible object is + * {@link Short } + */ + public Short getTos() { + return tos; + } + + /** + * Sets the value of the tos property. + * @param value + * allowed object is + * {@link Short } + */ + public void setTos(Short value) { + this.tos = value; + } + + } + + + /** + * <p>Java class for anonymous complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <attribute name="src" type="{http://www.example.org/net/}macAddressType" /> + * <attribute name="dst" type="{http://www.example.org/net/}macAddressType" /> + * <attribute name="ethertype" type="{http://www.example.org/net/}ethertypeType" /> + * <attribute name="vlanId" type="{http://www.example.org/net/}vlanIdType" /> + * <attribute name="vlanPcp" type="{http://www.example.org/net/}vlanPcpType" /> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "") + public static class Mac { + + @XmlAttribute(name = "src") + protected String src; + @XmlAttribute(name = "dst") + protected String dst; + @XmlAttribute(name = "ethertype") + protected Integer ethertype; + @XmlAttribute(name = "vlanId") + protected Integer vlanId; + @XmlAttribute(name = "vlanPcp") + protected Integer vlanPcp; + + /** + * Gets the value of the src property. + * @return + * possible object is + * {@link String } + */ + public String getSrc() { + return src; + } + + /** + * Sets the value of the src property. + * @param value + * allowed object is + * {@link String } + */ + public void setSrc(String value) { + this.src = value; + } + + /** + * Gets the value of the dst property. + * @return + * possible object is + * {@link String } + */ + public String getDst() { + return dst; + } + + /** + * Sets the value of the dst property. + * @param value + * allowed object is + * {@link String } + */ + public void setDst(String value) { + this.dst = value; + } + + /** + * Gets the value of the ethertype property. + * @return + * possible object is + * {@link Integer } + */ + public Integer getEthertype() { + return ethertype; + } + + /** + * Sets the value of the ethertype property. + * @param value + * allowed object is + * {@link Integer } + */ + public void setEthertype(Integer value) { + this.ethertype = value; + } + + /** + * Gets the value of the vlanId property. + * @return + * possible object is + * {@link Integer } + */ + public Integer getVlanId() { + return vlanId; + } + + /** + * Sets the value of the vlanId property. + * @param value + * allowed object is + * {@link Integer } + */ + public void setVlanId(Integer value) { + this.vlanId = value; + } + + /** + * Gets the value of the vlanPcp property. + * @return + * possible object is + * {@link Integer } + */ + public Integer getVlanPcp() { + return vlanPcp; + } + + /** + * Sets the value of the vlanPcp property. + * @param value + * allowed object is + * {@link Integer } + */ + public void setVlanPcp(Integer value) { + this.vlanPcp = value; + } + + } + + + /** + * <p>Java class for anonymous complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <attribute name="src" type="{http://www.example.org/net/}portNumberType" /> + * <attribute name="dst" type="{http://www.example.org/net/}portNumberType" /> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "") + public static class Tcp { + + @XmlAttribute(name = "src") + protected Integer src; + @XmlAttribute(name = "dst") + protected Integer dst; + + /** + * Gets the value of the src property. + * @return + * possible object is + * {@link Integer } + */ + public Integer getSrc() { + return src; + } + + /** + * Sets the value of the src property. + * @param value + * allowed object is + * {@link Integer } + */ + public void setSrc(Integer value) { + this.src = value; + } + + /** + * Gets the value of the dst property. + * @return + * possible object is + * {@link Integer } + */ + public Integer getDst() { + return dst; + } + + /** + * Sets the value of the dst property. + * @param value + * allowed object is + * {@link Integer } + */ + public void setDst(Integer value) { + this.dst = value; + } + + } + + + /** + * <p>Java class for anonymous complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <attribute name="src" type="{http://www.example.org/net/}portNumberType" /> + * <attribute name="dst" type="{http://www.example.org/net/}portNumberType" /> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "") + public static class Udp { + + @XmlAttribute(name = "src") + protected Integer src; + @XmlAttribute(name = "dst") + protected Integer dst; + + /** + * Gets the value of the src property. + * @return + * possible object is + * {@link Integer } + */ + public Integer getSrc() { + return src; + } + + /** + * Sets the value of the src property. + * @param value + * allowed object is + * {@link Integer } + */ + public void setSrc(Integer value) { + this.src = value; + } + + /** + * Gets the value of the dst property. + * @return + * possible object is + * {@link Integer } + */ + public Integer getDst() { + return dst; + } + + /** + * Sets the value of the dst property. + * @param value + * allowed object is + * {@link Integer } + */ + public void setDst(Integer value) { + this.dst = value; + } + + } + + } + +} diff --git a/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/HttpMessage.java b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/HttpMessage.java new file mode 100644 index 0000000..5dc7c29 --- /dev/null +++ b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/HttpMessage.java @@ -0,0 +1,108 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.nffg.neo4j.jaxb; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + + +/** + * <p>Java class for anonymous complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <sequence> + * <element name="statusCode" type="{http://www.w3.org/2001/XMLSchema}unsignedShort"/> + * <element name="reasonPhrase" type="{http://www.w3.org/2001/XMLSchema}string"/> + * <element name="message" type="{http://www.w3.org/2001/XMLSchema}string" minOccurs="0"/> + * </sequence> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "", propOrder = { + "statusCode", + "reasonPhrase", + "message" +}) +@XmlRootElement(name = "httpMessage", namespace = "http://www.example.org/response/") +public class HttpMessage { + + @XmlElement(namespace = "http://www.example.org/response/", defaultValue = "500") + @XmlSchemaType(name = "unsignedShort") + protected int statusCode; + @XmlElement(namespace = "http://www.example.org/response/", required = true, defaultValue = "Internal Server Error") + protected String reasonPhrase; + @XmlElement(namespace = "http://www.example.org/response/") + protected String message; + + /** + * Gets the value of the statusCode property. + */ + public int getStatusCode() { + return statusCode; + } + + /** + * Sets the value of the statusCode property. + */ + public void setStatusCode(int value) { + this.statusCode = value; + } + + /** + * Gets the value of the reasonPhrase property. + * @return + * possible object is + * {@link String } + */ + public String getReasonPhrase() { + return reasonPhrase; + } + + /** + * Sets the value of the reasonPhrase property. + * @param value + * allowed object is + * {@link String } + */ + public void setReasonPhrase(String value) { + this.reasonPhrase = value; + } + + /** + * Gets the value of the message property. + * @return + * possible object is + * {@link String } + */ + public String getMessage() { + return message; + } + + /** + * Sets the value of the message property. + * @param value + * allowed object is + * {@link String } + */ + public void setMessage(String value) { + this.message = value; + } + +} diff --git a/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/MonParamsType.java b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/MonParamsType.java new file mode 100644 index 0000000..8651966 --- /dev/null +++ b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/MonParamsType.java @@ -0,0 +1,122 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.nffg.neo4j.jaxb; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + + +/** + * <p>Java class for monParamsType complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType name="monParamsType"> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <sequence> + * <element name="parameter" maxOccurs="unbounded" minOccurs="0"> + * <complexType> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <attribute name="value" use="required" type="{http://www.w3.org/2001/XMLSchema}NMTOKENS" /> + * </restriction> + * </complexContent> + * </complexType> + * </element> + * </sequence> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "monParamsType", propOrder = { + "parameter" +}) +public class MonParamsType { + + protected List<MonParamsType.Parameter> parameter; + + /** + * Gets the value of the parameter property. + * <p> + * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a <CODE>set</CODE> method for the parameter property. + * <p> + * For example, to add a new item, do as follows: + * <pre> + * getParameter().add(newItem); + * </pre> + * <p> + * Objects of the following type(s) are allowed in the list + * {@link MonParamsType.Parameter } + */ + public List<MonParamsType.Parameter> getParameter() { + if (parameter == null) { + parameter = new ArrayList<MonParamsType.Parameter>(); + } + return this.parameter; + } + + + /** + * <p>Java class for anonymous complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <attribute name="value" use="required" type="{http://www.w3.org/2001/XMLSchema}NMTOKENS" /> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "") + public static class Parameter { + + @XmlAttribute(name = "value", required = true) + @XmlSchemaType(name = "NMTOKENS") + protected List<String> value; + + /** + * Gets the value of the value property. + * <p> + * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a <CODE>set</CODE> method for the value property. + * <p> + * For example, to add a new item, do as follows: + * <pre> + * getValue().add(newItem); + * </pre> + * <p> + * Objects of the following type(s) are allowed in the list + * {@link String } + */ + public List<String> getValue() { + if (value == null) { + value = new ArrayList<String>(); + } + return this.value; + } + + } + +} diff --git a/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/NeType.java b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/NeType.java new file mode 100644 index 0000000..9cdecdd --- /dev/null +++ b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/NeType.java @@ -0,0 +1,133 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.nffg.neo4j.jaxb; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + * <p>Java class for neType complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType name="neType"> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <sequence> + * <element name="eps-cps" type="{http://www.example.org/nffg/}eps-cpsType"/> + * <element name="monitoring_parameters" type="{http://www.example.org/nffg/}monParamsType"/> + * </sequence> + * <attribute name="id" use="required" type="{http://www.example.org/nffg/}neIdType" /> + * <attribute name="type" use="required" type="{http://www.w3.org/2001/XMLSchema}string" /> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "neType", propOrder = { + "epsCps", + "monitoringParameters" +}) +public class NeType { + + @XmlElement(name = "eps-cps", required = true) + protected EpsCpsType epsCps; + @XmlElement(name = "monitoring_parameters", required = true) + protected MonParamsType monitoringParameters; + @XmlAttribute(name = "id", required = true) + protected String id; + @XmlAttribute(name = "type", required = true) + protected String type; + + /** + * Gets the value of the epsCps property. + * @return + * possible object is + * {@link EpsCpsType } + */ + public EpsCpsType getEpsCps() { + return epsCps; + } + + /** + * Sets the value of the epsCps property. + * @param value + * allowed object is + * {@link EpsCpsType } + */ + public void setEpsCps(EpsCpsType value) { + this.epsCps = value; + } + + /** + * Gets the value of the monitoringParameters property. + * @return + * possible object is + * {@link MonParamsType } + */ + public MonParamsType getMonitoringParameters() { + return monitoringParameters; + } + + /** + * Sets the value of the monitoringParameters property. + * @param value + * allowed object is + * {@link MonParamsType } + */ + public void setMonitoringParameters(MonParamsType value) { + this.monitoringParameters = value; + } + + /** + * Gets the value of the id property. + * @return + * possible object is + * {@link String } + */ + public String getId() { + return id; + } + + /** + * Sets the value of the id property. + * @param value + * allowed object is + * {@link String } + */ + public void setId(String value) { + this.id = value; + } + + /** + * Gets the value of the type property. + * @return + * possible object is + * {@link String } + */ + public String getType() { + return type; + } + + /** + * Sets the value of the type property. + * @param value + * allowed object is + * {@link String } + */ + public void setType(String value) { + this.type = value; + } + +} diff --git a/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/NelementsType.java b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/NelementsType.java new file mode 100644 index 0000000..0ccef60 --- /dev/null +++ b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/NelementsType.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.nffg.neo4j.jaxb; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + * <p>Java class for nelementsType complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType name="nelementsType"> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <sequence> + * <element name="network_element" type="{http://www.example.org/nffg/}neType" maxOccurs="unbounded" minOccurs="0"/> + * </sequence> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "nelementsType", propOrder = { + "networkElement" +}) +public class NelementsType { + + @XmlElement(name = "network_element") + protected List<NeType> networkElement; + + /** + * Gets the value of the networkElement property. + * <p> + * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a <CODE>set</CODE> method for the networkElement property. + * <p> + * For example, to add a new item, do as follows: + * <pre> + * getNetworkElement().add(newItem); + * </pre> + * <p> + * Objects of the following type(s) are allowed in the list + * {@link NeType } + */ + public List<NeType> getNetworkElement() { + if (networkElement == null) { + networkElement = new ArrayList<NeType>(); + } + return this.networkElement; + } + +} diff --git a/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/NfType.java b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/NfType.java new file mode 100644 index 0000000..f2b50ea --- /dev/null +++ b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/NfType.java @@ -0,0 +1,181 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.nffg.neo4j.jaxb; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + * <p>Java class for nfType complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType name="nfType"> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <sequence> + * <element name="specification" type="{http://www.example.org/nffg/}specType"/> + * <element name="connection_points" type="{http://www.example.org/nffg/}cpointsType"/> + * <element name="control_interfaces" type="{http://www.example.org/nffg/}ctrlInterfacesType"/> + * <element name="monitoring_parameters" type="{http://www.example.org/nffg/}monParamsType"/> + * </sequence> + * <attribute name="id" use="required" type="{http://www.example.org/nffg/}nfIdType" /> + * <attribute name="functionalType" use="required" type="{http://www.w3.org/2001/XMLSchema}string" /> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "nfType", propOrder = { + "specification", + "connectionPoints", + "controlInterfaces", + "monitoringParameters" +}) +public class NfType { + + @XmlElement(required = true) + protected SpecType specification; + @XmlElement(name = "connection_points", required = true) + protected CpointsType connectionPoints; + @XmlElement(name = "control_interfaces", required = true) + protected CtrlInterfacesType controlInterfaces; + @XmlElement(name = "monitoring_parameters", required = true) + protected MonParamsType monitoringParameters; + @XmlAttribute(name = "id", required = true) + protected String id; + @XmlAttribute(name = "functionalType", required = true) + protected String functionalType; + + /** + * Gets the value of the specification property. + * @return + * possible object is + * {@link SpecType } + */ + public SpecType getSpecification() { + return specification; + } + + /** + * Sets the value of the specification property. + * @param value + * allowed object is + * {@link SpecType } + */ + public void setSpecification(SpecType value) { + this.specification = value; + } + + /** + * Gets the value of the connectionPoints property. + * @return + * possible object is + * {@link CpointsType } + */ + public CpointsType getConnectionPoints() { + return connectionPoints; + } + + /** + * Sets the value of the connectionPoints property. + * @param value + * allowed object is + * {@link CpointsType } + */ + public void setConnectionPoints(CpointsType value) { + this.connectionPoints = value; + } + + /** + * Gets the value of the controlInterfaces property. + * @return + * possible object is + * {@link CtrlInterfacesType } + */ + public CtrlInterfacesType getControlInterfaces() { + return controlInterfaces; + } + + /** + * Sets the value of the controlInterfaces property. + * @param value + * allowed object is + * {@link CtrlInterfacesType } + */ + public void setControlInterfaces(CtrlInterfacesType value) { + this.controlInterfaces = value; + } + + /** + * Gets the value of the monitoringParameters property. + * @return + * possible object is + * {@link MonParamsType } + */ + public MonParamsType getMonitoringParameters() { + return monitoringParameters; + } + + /** + * Sets the value of the monitoringParameters property. + * @param value + * allowed object is + * {@link MonParamsType } + */ + public void setMonitoringParameters(MonParamsType value) { + this.monitoringParameters = value; + } + + /** + * Gets the value of the id property. + * @return + * possible object is + * {@link String } + */ + public String getId() { + return id; + } + + /** + * Sets the value of the id property. + * @param value + * allowed object is + * {@link String } + */ + public void setId(String value) { + this.id = value; + } + + /** + * Gets the value of the functionalType property. + * @return + * possible object is + * {@link String } + */ + public String getFunctionalType() { + return functionalType; + } + + /** + * Sets the value of the functionalType property. + * @param value + * allowed object is + * {@link String } + */ + public void setFunctionalType(String value) { + this.functionalType = value; + } + +} diff --git a/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/Nffg.java b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/Nffg.java new file mode 100644 index 0000000..54e6daf --- /dev/null +++ b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/Nffg.java @@ -0,0 +1,183 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.nffg.neo4j.jaxb; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + + +/** + * <p>Java class for anonymous complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <sequence> + * <element name="endpoints" type="{http://www.example.org/nffg/}epointsType"/> + * <element name="network_functions" type="{http://www.example.org/nffg/}nfunctionsType"/> + * <element name="network_elements" type="{http://www.example.org/nffg/}nelementsType"/> + * <element name="monitoring_parameters" type="{http://www.example.org/nffg/}monParamsType"/> + * </sequence> + * <attribute name="id" type="{http://www.example.org/nffg/}nffgIdType" /> + * <attribute name="version" type="{http://www.w3.org/2001/XMLSchema}string" /> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "", propOrder = { + "endpoints", + "networkFunctions", + "networkElements", + "monitoringParameters" +}) +@XmlRootElement(name = "nffg") +public class Nffg { + + @XmlElement(required = true) + protected EpointsType endpoints; + @XmlElement(name = "network_functions", required = true) + protected NfunctionsType networkFunctions; + @XmlElement(name = "network_elements", required = true) + protected NelementsType networkElements; + @XmlElement(name = "monitoring_parameters", required = true) + protected MonParamsType monitoringParameters; + @XmlAttribute(name = "id") + protected String id; + @XmlAttribute(name = "version") + protected String version; + + /** + * Gets the value of the endpoints property. + * @return + * possible object is + * {@link EpointsType } + */ + public EpointsType getEndpoints() { + return endpoints; + } + + /** + * Sets the value of the endpoints property. + * @param value + * allowed object is + * {@link EpointsType } + */ + public void setEndpoints(EpointsType value) { + this.endpoints = value; + } + + /** + * Gets the value of the networkFunctions property. + * @return + * possible object is + * {@link NfunctionsType } + */ + public NfunctionsType getNetworkFunctions() { + return networkFunctions; + } + + /** + * Sets the value of the networkFunctions property. + * @param value + * allowed object is + * {@link NfunctionsType } + */ + public void setNetworkFunctions(NfunctionsType value) { + this.networkFunctions = value; + } + + /** + * Gets the value of the networkElements property. + * @return + * possible object is + * {@link NelementsType } + */ + public NelementsType getNetworkElements() { + return networkElements; + } + + /** + * Sets the value of the networkElements property. + * @param value + * allowed object is + * {@link NelementsType } + */ + public void setNetworkElements(NelementsType value) { + this.networkElements = value; + } + + /** + * Gets the value of the monitoringParameters property. + * @return + * possible object is + * {@link MonParamsType } + */ + public MonParamsType getMonitoringParameters() { + return monitoringParameters; + } + + /** + * Sets the value of the monitoringParameters property. + * @param value + * allowed object is + * {@link MonParamsType } + */ + public void setMonitoringParameters(MonParamsType value) { + this.monitoringParameters = value; + } + + /** + * Gets the value of the id property. + * @return + * possible object is + * {@link String } + */ + public String getId() { + return id; + } + + /** + * Sets the value of the id property. + * @param value + * allowed object is + * {@link String } + */ + public void setId(String value) { + this.id = value; + } + + /** + * Gets the value of the version property. + * @return + * possible object is + * {@link String } + */ + public String getVersion() { + return version; + } + + /** + * Sets the value of the version property. + * @param value + * allowed object is + * {@link String } + */ + public void setVersion(String value) { + this.version = value; + } + +} diff --git a/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/NffgSet.java b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/NffgSet.java new file mode 100644 index 0000000..8fdc137 --- /dev/null +++ b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/NffgSet.java @@ -0,0 +1,69 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.nffg.neo4j.jaxb; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + + +/** + * <p>Java class for anonymous complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <sequence> + * <element ref="{http://www.example.org/nffg/}nffg" maxOccurs="unbounded"/> + * </sequence> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "", propOrder = { + "nffg" +}) +@XmlRootElement(name = "nffg-set") +public class NffgSet { + + @XmlElement(required = true) + protected List<Nffg> nffg; + + /** + * Gets the value of the nffg property. + * <p> + * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a <CODE>set</CODE> method for the nffg property. + * <p> + * For example, to add a new item, do as follows: + * <pre> + * getNffg().add(newItem); + * </pre> + * <p> + * Objects of the following type(s) are allowed in the list + * {@link Nffg } + */ + public List<Nffg> getNffg() { + if (nffg == null) { + nffg = new ArrayList<Nffg>(); + } + return this.nffg; + } + +} diff --git a/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/NfunctionsType.java b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/NfunctionsType.java new file mode 100644 index 0000000..7b26ac3 --- /dev/null +++ b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/NfunctionsType.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.nffg.neo4j.jaxb; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + * <p>Java class for nfunctionsType complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType name="nfunctionsType"> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <sequence> + * <element name="network_function" type="{http://www.example.org/nffg/}nfType" maxOccurs="unbounded" minOccurs="0"/> + * </sequence> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "nfunctionsType", propOrder = { + "networkFunction" +}) +public class NfunctionsType { + + @XmlElement(name = "network_function") + protected List<NfType> networkFunction; + + /** + * Gets the value of the networkFunction property. + * <p> + * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a <CODE>set</CODE> method for the networkFunction property. + * <p> + * For example, to add a new item, do as follows: + * <pre> + * getNetworkFunction().add(newItem); + * </pre> + * <p> + * Objects of the following type(s) are allowed in the list + * {@link NfType } + */ + public List<NfType> getNetworkFunction() { + if (networkFunction == null) { + networkFunction = new ArrayList<NfType>(); + } + return this.networkFunction; + } + +} diff --git a/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/ObjectFactory.java b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/ObjectFactory.java new file mode 100644 index 0000000..1c7c7f5 --- /dev/null +++ b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/ObjectFactory.java @@ -0,0 +1,319 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.nffg.neo4j.jaxb; + +import javax.xml.bind.JAXBElement; +import javax.xml.bind.annotation.XmlElementDecl; +import javax.xml.bind.annotation.XmlRegistry; +import javax.xml.namespace.QName; + + +/** + * This object contains factory methods for each + * Java content interface and Java element interface + * generated in the it.polito.nffg.neo4j.jaxb package. + * <p>An ObjectFactory allows you to programatically + * construct new instances of the Java representation + * for XML content. The Java representation of XML + * content can consist of schema derived interfaces + * and classes representing the binding of schema + * type definitions, element declarations and model + * groups. Factory methods for each of these are + * provided in this class. + */ +@XmlRegistry +public class ObjectFactory { + + private final static QName _Nffg_QNAME = new QName("http://www.example.org/nffg/", "nffg"); + private final static QName _NffgSet_QNAME = new QName("http://www.example.org/nffg/", "nffg-set"); + + + /** + * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: it.polito.nffg.neo4j.jaxb + */ + public ObjectFactory() { + } + + /** + * Create an instance of {@link FlowrulesType } + */ + public FlowrulesType createFlowrulesType() { + return new FlowrulesType(); + } + + /** + * Create an instance of {@link FlowrulesType.Flowspace } + */ + public FlowrulesType.Flowspace createFlowrulesTypeFlowspace() { + return new FlowrulesType.Flowspace(); + } + + /** + * Create an instance of {@link CiType } + */ + public CiType createCiType() { + return new CiType(); + } + + /** + * Create an instance of {@link CiType.Attributes } + */ + public CiType.Attributes createCiTypeAttributes() { + return new CiType.Attributes(); + } + + /** + * Create an instance of {@link EpType } + */ + public EpType createEpType() { + return new EpType(); + } + + /** + * Create an instance of {@link SpecType } + */ + public SpecType createSpecType() { + return new SpecType(); + } + + /** + * Create an instance of {@link MonParamsType } + */ + public MonParamsType createMonParamsType() { + return new MonParamsType(); + } + + /** + * Create an instance of {@link NffgSet } + */ + public NffgSet createNffgSet() { + return new NffgSet(); + } + + /** + * Create an instance of {@link Nffg } + */ + public Nffg createNffg() { + return new Nffg(); + } + + /** + * Create an instance of {@link EpointsType } + */ + public EpointsType createEpointsType() { + return new EpointsType(); + } + + /** + * Create an instance of {@link NfunctionsType } + */ + public NfunctionsType createNfunctionsType() { + return new NfunctionsType(); + } + + /** + * Create an instance of {@link NelementsType } + */ + public NelementsType createNelementsType() { + return new NelementsType(); + } + + /** + * Create an instance of {@link CpointsType } + */ + public CpointsType createCpointsType() { + return new CpointsType(); + } + + /** + * Create an instance of {@link NfType } + */ + public NfType createNfType() { + return new NfType(); + } + + /** + * Create an instance of {@link EpCpType } + */ + public EpCpType createEpCpType() { + return new EpCpType(); + } + + /** + * Create an instance of {@link EpsCpsType } + */ + public EpsCpsType createEpsCpsType() { + return new EpsCpsType(); + } + + /** + * Create an instance of {@link ActionsType } + */ + public ActionsType createActionsType() { + return new ActionsType(); + } + + /** + * Create an instance of {@link ActionType } + */ + public ActionType createActionType() { + return new ActionType(); + } + + /** + * Create an instance of {@link PortType } + */ + public PortType createPortType() { + return new PortType(); + } + + /** + * Create an instance of {@link CpType } + */ + public CpType createCpType() { + return new CpType(); + } + + /** + * Create an instance of {@link CtrlInterfacesType } + */ + public CtrlInterfacesType createCtrlInterfacesType() { + return new CtrlInterfacesType(); + } + + /** + * Create an instance of {@link NeType } + */ + public NeType createNeType() { + return new NeType(); + } + + /** + * Create an instance of {@link Paths } + */ + public Paths createPaths() { + return new Paths(); + } + + /** + * Create an instance of {@link HttpMessage } + */ + public HttpMessage createHttpMessage() { + return new HttpMessage(); + } + + /** + * Create an instance of {@link Property } + */ + public Property createProperty() { + return new Property(); + } + + /** + * Create an instance of {@link FlowrulesType.Flowspace.Mac } + */ + public FlowrulesType.Flowspace.Mac createFlowrulesTypeFlowspaceMac() { + return new FlowrulesType.Flowspace.Mac(); + } + + /** + * Create an instance of {@link FlowrulesType.Flowspace.Ip } + */ + public FlowrulesType.Flowspace.Ip createFlowrulesTypeFlowspaceIp() { + return new FlowrulesType.Flowspace.Ip(); + } + + /** + * Create an instance of {@link FlowrulesType.Flowspace.Tcp } + */ + public FlowrulesType.Flowspace.Tcp createFlowrulesTypeFlowspaceTcp() { + return new FlowrulesType.Flowspace.Tcp(); + } + + /** + * Create an instance of {@link FlowrulesType.Flowspace.Udp } + */ + public FlowrulesType.Flowspace.Udp createFlowrulesTypeFlowspaceUdp() { + return new FlowrulesType.Flowspace.Udp(); + } + + /** + * Create an instance of {@link CiType.Attributes.Attribute } + */ + public CiType.Attributes.Attribute createCiTypeAttributesAttribute() { + return new CiType.Attributes.Attribute(); + } + + /** + * Create an instance of {@link EpType.Flowspace } + */ + public EpType.Flowspace createEpTypeFlowspace() { + return new EpType.Flowspace(); + } + + /** + * Create an instance of {@link SpecType.Deployment } + */ + public SpecType.Deployment createSpecTypeDeployment() { + return new SpecType.Deployment(); + } + + /** + * Create an instance of {@link SpecType.Image } + */ + public SpecType.Image createSpecTypeImage() { + return new SpecType.Image(); + } + + /** + * Create an instance of {@link SpecType.Cpu } + */ + public SpecType.Cpu createSpecTypeCpu() { + return new SpecType.Cpu(); + } + + /** + * Create an instance of {@link SpecType.Memory } + */ + public SpecType.Memory createSpecTypeMemory() { + return new SpecType.Memory(); + } + + /** + * Create an instance of {@link SpecType.Storage } + */ + public SpecType.Storage createSpecTypeStorage() { + return new SpecType.Storage(); + } + + /** + * Create an instance of {@link MonParamsType.Parameter } + */ + public MonParamsType.Parameter createMonParamsTypeParameter() { + return new MonParamsType.Parameter(); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link NffgType }{@code >}} + */ + @XmlElementDecl(namespace = "http://www.example.org/nffg/", name = "nffg") + public JAXBElement<Nffg> createNffg(Nffg value) { + return new JAXBElement<Nffg>(_Nffg_QNAME, Nffg.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link NffgSetType }{@code >}} + */ + @XmlElementDecl(namespace = "http://www.example.org/nffg/", name = "nffg-set") + public JAXBElement<NffgSet> createNffgSet(NffgSet value) { + return new JAXBElement<NffgSet>(_NffgSet_QNAME, NffgSet.class, null, value); + } + +} diff --git a/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/Paths.java b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/Paths.java new file mode 100644 index 0000000..f097b30 --- /dev/null +++ b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/Paths.java @@ -0,0 +1,163 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.nffg.neo4j.jaxb; + +import java.util.ArrayList; +import java.util.List; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + + +/** + * <p>Java class for anonymous complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <choice> + * <element name="message" type="{http://www.w3.org/2001/XMLSchema}string"/> + * <element name="path" type="{http://www.w3.org/2001/XMLSchema}string" maxOccurs="unbounded"/> + * </choice> + * <attribute name="source" type="{http://www.w3.org/2001/XMLSchema}string" /> + * <attribute name="destination" type="{http://www.w3.org/2001/XMLSchema}string" /> + * <attribute name="direction" type="{http://www.w3.org/2001/XMLSchema}string" /> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "", propOrder = { + "message", + "path" +}) +@XmlRootElement(name = "paths", namespace = "http://www.example.org/response/") +public class Paths { + + @XmlElement(namespace = "http://www.example.org/response/") + protected String message; + @XmlElement(namespace = "http://www.example.org/response/") + protected List<String> path; + @XmlAttribute(name = "source") + protected String source; + @XmlAttribute(name = "destination") + protected String destination; + @XmlAttribute(name = "direction") + protected String direction; + + /** + * Gets the value of the message property. + * @return + * possible object is + * {@link String } + */ + public String getMessage() { + return message; + } + + /** + * Sets the value of the message property. + * @param value + * allowed object is + * {@link String } + */ + public void setMessage(String value) { + this.message = value; + } + + /** + * Gets the value of the path property. + * <p> + * This accessor method returns a reference to the live list, + * not a snapshot. Therefore any modification you make to the + * returned list will be present inside the JAXB object. + * This is why there is not a <CODE>set</CODE> method for the path property. + * <p> + * For example, to add a new item, do as follows: + * <pre> + * getPath().add(newItem); + * </pre> + * <p> + * Objects of the following type(s) are allowed in the list + * {@link String } + */ + public List<String> getPath() { + if (path == null) { + path = new ArrayList<String>(); + } + return this.path; + } + + /** + * Gets the value of the source property. + * @return + * possible object is + * {@link String } + */ + public String getSource() { + return source; + } + + /** + * Sets the value of the source property. + * @param value + * allowed object is + * {@link String } + */ + public void setSource(String value) { + this.source = value; + } + + /** + * Gets the value of the destination property. + * @return + * possible object is + * {@link String } + */ + public String getDestination() { + return destination; + } + + /** + * Sets the value of the destination property. + * @param value + * allowed object is + * {@link String } + */ + public void setDestination(String value) { + this.destination = value; + } + + /** + * Gets the value of the direction property. + * @return + * possible object is + * {@link String } + */ + public String getDirection() { + return direction; + } + + /** + * Sets the value of the direction property. + * @param value + * allowed object is + * {@link String } + */ + public void setDirection(String value) { + this.direction = value; + } + +} diff --git a/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/PortDirEnumType.java b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/PortDirEnumType.java new file mode 100644 index 0000000..f98907d --- /dev/null +++ b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/PortDirEnumType.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.nffg.neo4j.jaxb; + +import javax.xml.bind.annotation.XmlEnum; +import javax.xml.bind.annotation.XmlEnumValue; +import javax.xml.bind.annotation.XmlType; + + +/** + * <p>Java class for portDirEnumType. + * <p>The following schema fragment specifies the expected content contained within this class. + * <p> + * <pre> + * <simpleType name="portDirEnumType"> + * <restriction base="{http://www.w3.org/2001/XMLSchema}string"> + * <enumeration value="in"/> + * <enumeration value="out"/> + * <enumeration value="both"/> + * </restriction> + * </simpleType> + * </pre> + */ +@XmlType(name = "portDirEnumType") +@XmlEnum +public enum PortDirEnumType { + + @XmlEnumValue("in") + IN("in"), + @XmlEnumValue("out") + OUT("out"), + @XmlEnumValue("both") + BOTH("both"); + private final String value; + + PortDirEnumType(String v) { + value = v; + } + + public String value() { + return value; + } + + public static PortDirEnumType fromValue(String v) { + for (PortDirEnumType c: PortDirEnumType.values()) { + if (c.value.equals(v)) { + return c; + } + } + throw new IllegalArgumentException(v); + } + +} diff --git a/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/PortType.java b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/PortType.java new file mode 100644 index 0000000..4d44cf5 --- /dev/null +++ b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/PortType.java @@ -0,0 +1,104 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.nffg.neo4j.jaxb; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + + +/** + * <p>Java class for portType complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType name="portType"> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <attribute name="id" use="required" type="{http://www.w3.org/2001/XMLSchema}unsignedShort" /> + * <attribute name="direction" use="required" type="{http://www.example.org/nffg/}portDirEnumType" /> + * <attribute name="type" type="{http://www.w3.org/2001/XMLSchema}string" default="N.A." /> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "portType") +public class PortType { + + @XmlAttribute(name = "id", required = true) + @XmlSchemaType(name = "unsignedShort") + protected int id; + @XmlAttribute(name = "direction", required = true) + protected PortDirEnumType direction; + @XmlAttribute(name = "type") + protected String type; + + /** + * Gets the value of the id property. + */ + public int getId() { + return id; + } + + /** + * Sets the value of the id property. + */ + public void setId(int value) { + this.id = value; + } + + /** + * Gets the value of the direction property. + * @return + * possible object is + * {@link PortDirEnumType } + */ + public PortDirEnumType getDirection() { + return direction; + } + + /** + * Sets the value of the direction property. + * @param value + * allowed object is + * {@link PortDirEnumType } + */ + public void setDirection(PortDirEnumType value) { + this.direction = value; + } + + /** + * Gets the value of the type property. + * @return + * possible object is + * {@link String } + */ + public String getType() { + if (type == null) { + return "N.A."; + } else { + return type; + } + } + + /** + * Sets the value of the type property. + * @param value + * allowed object is + * {@link String } + */ + public void setType(String value) { + this.type = value; + } + +} diff --git a/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/Property.java b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/Property.java new file mode 100644 index 0000000..973eaf8 --- /dev/null +++ b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/Property.java @@ -0,0 +1,152 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.nffg.neo4j.jaxb; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; + + +/** + * <p>Java class for anonymous complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <sequence> + * <element name="name" type="{http://www.w3.org/2001/XMLSchema}string"/> + * <element name="response" type="{http://www.w3.org/2001/XMLSchema}boolean"/> + * </sequence> + * <attribute name="source" type="{http://www.w3.org/2001/XMLSchema}string" /> + * <attribute name="destination" type="{http://www.w3.org/2001/XMLSchema}string" /> + * <attribute name="direction" type="{http://www.w3.org/2001/XMLSchema}string" /> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "", propOrder = { + "name", + "response" +}) +@XmlRootElement(name = "property", namespace = "http://www.example.org/response/") +public class Property { + + @XmlElement(namespace = "http://www.example.org/response/", required = true) + protected String name; + @XmlElement(namespace = "http://www.example.org/response/") + protected boolean response; + @XmlAttribute(name = "source") + protected String source; + @XmlAttribute(name = "destination") + protected String destination; + @XmlAttribute(name = "direction") + protected String direction; + + /** + * Gets the value of the name property. + * @return + * possible object is + * {@link String } + */ + public String getName() { + return name; + } + + /** + * Sets the value of the name property. + * @param value + * allowed object is + * {@link String } + */ + public void setName(String value) { + this.name = value; + } + + /** + * Gets the value of the response property. + */ + public boolean isResponse() { + return response; + } + + /** + * Sets the value of the response property. + */ + public void setResponse(boolean value) { + this.response = value; + } + + /** + * Gets the value of the source property. + * @return + * possible object is + * {@link String } + */ + public String getSource() { + return source; + } + + /** + * Sets the value of the source property. + * @param value + * allowed object is + * {@link String } + */ + public void setSource(String value) { + this.source = value; + } + + /** + * Gets the value of the destination property. + * @return + * possible object is + * {@link String } + */ + public String getDestination() { + return destination; + } + + /** + * Sets the value of the destination property. + * @param value + * allowed object is + * {@link String } + */ + public void setDestination(String value) { + this.destination = value; + } + + /** + * Gets the value of the direction property. + * @return + * possible object is + * {@link String } + */ + public String getDirection() { + return direction; + } + + /** + * Sets the value of the direction property. + * @param value + * allowed object is + * {@link String } + */ + public void setDirection(String value) { + this.direction = value; + } + +} diff --git a/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/SpecType.java b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/SpecType.java new file mode 100644 index 0000000..e4d434b --- /dev/null +++ b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/SpecType.java @@ -0,0 +1,577 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +package it.polito.nffg.neo4j.jaxb; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlSchemaType; +import javax.xml.bind.annotation.XmlType; + + +/** + * <p>Java class for specType complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType name="specType"> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <sequence> + * <element name="deployment"> + * <complexType> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <attribute name="type" type="{http://www.w3.org/2001/XMLSchema}string" default="N.A." /> + * </restriction> + * </complexContent> + * </complexType> + * </element> + * <element name="image"> + * <complexType> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <attribute name="uri" type="{http://www.w3.org/2001/XMLSchema}anyURI" default="N.A." /> + * </restriction> + * </complexContent> + * </complexType> + * </element> + * <element name="cpu"> + * <complexType> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <attribute name="model" type="{http://www.w3.org/2001/XMLSchema}string" default="N.A." /> + * <attribute name="architecture" type="{http://www.w3.org/2001/XMLSchema}string" default="N.A." /> + * <attribute name="numCores" type="{http://www.w3.org/2001/XMLSchema}unsignedByte" default="1" /> + * <attribute name="clockSpeed" type="{http://www.w3.org/2001/XMLSchema}string" default="N.A." /> + * </restriction> + * </complexContent> + * </complexType> + * </element> + * <element name="memory"> + * <complexType> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <attribute name="type" type="{http://www.w3.org/2001/XMLSchema}string" default="N.A." /> + * <attribute name="size" type="{http://www.w3.org/2001/XMLSchema}string" default="N.A." /> + * </restriction> + * </complexContent> + * </complexType> + * </element> + * <element name="storage"> + * <complexType> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <attribute name="type" type="{http://www.w3.org/2001/XMLSchema}string" default="N.A." /> + * <attribute name="size" type="{http://www.w3.org/2001/XMLSchema}string" default="N.A." /> + * </restriction> + * </complexContent> + * </complexType> + * </element> + * </sequence> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "specType", propOrder = { + "deployment", + "image", + "cpu", + "memory", + "storage" +}) +public class SpecType { + + @XmlElement(required = true) + protected SpecType.Deployment deployment; + @XmlElement(required = true) + protected SpecType.Image image; + @XmlElement(required = true) + protected SpecType.Cpu cpu; + @XmlElement(required = true) + protected SpecType.Memory memory; + @XmlElement(required = true) + protected SpecType.Storage storage; + + /** + * Gets the value of the deployment property. + * @return + * possible object is + * {@link SpecType.Deployment } + */ + public SpecType.Deployment getDeployment() { + return deployment; + } + + /** + * Sets the value of the deployment property. + * @param value + * allowed object is + * {@link SpecType.Deployment } + */ + public void setDeployment(SpecType.Deployment value) { + this.deployment = value; + } + + /** + * Gets the value of the image property. + * @return + * possible object is + * {@link SpecType.Image } + */ + public SpecType.Image getImage() { + return image; + } + + /** + * Sets the value of the image property. + * @param value + * allowed object is + * {@link SpecType.Image } + */ + public void setImage(SpecType.Image value) { + this.image = value; + } + + /** + * Gets the value of the cpu property. + * @return + * possible object is + * {@link SpecType.Cpu } + */ + public SpecType.Cpu getCpu() { + return cpu; + } + + /** + * Sets the value of the cpu property. + * @param value + * allowed object is + * {@link SpecType.Cpu } + */ + public void setCpu(SpecType.Cpu value) { + this.cpu = value; + } + + /** + * Gets the value of the memory property. + * @return + * possible object is + * {@link SpecType.Memory } + */ + public SpecType.Memory getMemory() { + return memory; + } + + /** + * Sets the value of the memory property. + * @param value + * allowed object is + * {@link SpecType.Memory } + */ + public void setMemory(SpecType.Memory value) { + this.memory = value; + } + + /** + * Gets the value of the storage property. + * @return + * possible object is + * {@link SpecType.Storage } + */ + public SpecType.Storage getStorage() { + return storage; + } + + /** + * Sets the value of the storage property. + * @param value + * allowed object is + * {@link SpecType.Storage } + */ + public void setStorage(SpecType.Storage value) { + this.storage = value; + } + + + /** + * <p>Java class for anonymous complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <attribute name="model" type="{http://www.w3.org/2001/XMLSchema}string" default="N.A." /> + * <attribute name="architecture" type="{http://www.w3.org/2001/XMLSchema}string" default="N.A." /> + * <attribute name="numCores" type="{http://www.w3.org/2001/XMLSchema}unsignedByte" default="1" /> + * <attribute name="clockSpeed" type="{http://www.w3.org/2001/XMLSchema}string" default="N.A." /> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "") + public static class Cpu { + + @XmlAttribute(name = "model") + protected String model; + @XmlAttribute(name = "architecture") + protected String architecture; + @XmlAttribute(name = "numCores") + @XmlSchemaType(name = "unsignedByte") + protected Short numCores; + @XmlAttribute(name = "clockSpeed") + protected String clockSpeed; + + /** + * Gets the value of the model property. + * @return + * possible object is + * {@link String } + */ + public String getModel() { + if (model == null) { + return "N.A."; + } else { + return model; + } + } + + /** + * Sets the value of the model property. + * @param value + * allowed object is + * {@link String } + */ + public void setModel(String value) { + this.model = value; + } + + /** + * Gets the value of the architecture property. + * @return + * possible object is + * {@link String } + */ + public String getArchitecture() { + if (architecture == null) { + return "N.A."; + } else { + return architecture; + } + } + + /** + * Sets the value of the architecture property. + * @param value + * allowed object is + * {@link String } + */ + public void setArchitecture(String value) { + this.architecture = value; + } + + /** + * Gets the value of the numCores property. + * @return + * possible object is + * {@link Short } + */ + public short getNumCores() { + if (numCores == null) { + return ((short) 1); + } else { + return numCores; + } + } + + /** + * Sets the value of the numCores property. + * @param value + * allowed object is + * {@link Short } + */ + public void setNumCores(Short value) { + this.numCores = value; + } + + /** + * Gets the value of the clockSpeed property. + * @return + * possible object is + * {@link String } + */ + public String getClockSpeed() { + if (clockSpeed == null) { + return "N.A."; + } else { + return clockSpeed; + } + } + + /** + * Sets the value of the clockSpeed property. + * @param value + * allowed object is + * {@link String } + */ + public void setClockSpeed(String value) { + this.clockSpeed = value; + } + + } + + + /** + * <p>Java class for anonymous complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <attribute name="type" type="{http://www.w3.org/2001/XMLSchema}string" default="N.A." /> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "") + public static class Deployment { + + @XmlAttribute(name = "type") + protected String type; + + /** + * Gets the value of the type property. + * @return + * possible object is + * {@link String } + */ + public String getType() { + if (type == null) { + return "N.A."; + } else { + return type; + } + } + + /** + * Sets the value of the type property. + * @param value + * allowed object is + * {@link String } + */ + public void setType(String value) { + this.type = value; + } + + } + + + /** + * <p>Java class for anonymous complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <attribute name="uri" type="{http://www.w3.org/2001/XMLSchema}anyURI" default="N.A." /> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "") + public static class Image { + + @XmlAttribute(name = "uri") + @XmlSchemaType(name = "anyURI") + protected String uri; + + /** + * Gets the value of the uri property. + * @return + * possible object is + * {@link String } + */ + public String getUri() { + if (uri == null) { + return "N.A."; + } else { + return uri; + } + } + + /** + * Sets the value of the uri property. + * @param value + * allowed object is + * {@link String } + */ + public void setUri(String value) { + this.uri = value; + } + + } + + + /** + * <p>Java class for anonymous complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <attribute name="type" type="{http://www.w3.org/2001/XMLSchema}string" default="N.A." /> + * <attribute name="size" type="{http://www.w3.org/2001/XMLSchema}string" default="N.A." /> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "") + public static class Memory { + + @XmlAttribute(name = "type") + protected String type; + @XmlAttribute(name = "size") + protected String size; + + /** + * Gets the value of the type property. + * @return + * possible object is + * {@link String } + */ + public String getType() { + if (type == null) { + return "N.A."; + } else { + return type; + } + } + + /** + * Sets the value of the type property. + * @param value + * allowed object is + * {@link String } + */ + public void setType(String value) { + this.type = value; + } + + /** + * Gets the value of the size property. + * @return + * possible object is + * {@link String } + */ + public String getSize() { + if (size == null) { + return "N.A."; + } else { + return size; + } + } + + /** + * Sets the value of the size property. + * @param value + * allowed object is + * {@link String } + */ + public void setSize(String value) { + this.size = value; + } + + } + + + /** + * <p>Java class for anonymous complex type. + * <p>The following schema fragment specifies the expected content contained within this class. + * <pre> + * <complexType> + * <complexContent> + * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> + * <attribute name="type" type="{http://www.w3.org/2001/XMLSchema}string" default="N.A." /> + * <attribute name="size" type="{http://www.w3.org/2001/XMLSchema}string" default="N.A." /> + * </restriction> + * </complexContent> + * </complexType> + * </pre> + */ + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "") + public static class Storage { + + @XmlAttribute(name = "type") + protected String type; + @XmlAttribute(name = "size") + protected String size; + + /** + * Gets the value of the type property. + * @return + * possible object is + * {@link String } + */ + public String getType() { + if (type == null) { + return "N.A."; + } else { + return type; + } + } + + /** + * Sets the value of the type property. + * @param value + * allowed object is + * {@link String } + */ + public void setType(String value) { + this.type = value; + } + + /** + * Gets the value of the size property. + * @return + * possible object is + * {@link String } + */ + public String getSize() { + if (size == null) { + return "N.A."; + } else { + return size; + } + } + + /** + * Sets the value of the size property. + * @param value + * allowed object is + * {@link String } + */ + public void setSize(String value) { + this.size = value; + } + + } + +} diff --git a/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/package-info.java b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/package-info.java new file mode 100644 index 0000000..3d3c7b4 --- /dev/null +++ b/verigraph/src/main/java/it/polito/nffg/neo4j/jaxb/package-info.java @@ -0,0 +1,11 @@ +/******************************************************************************* + * Copyright (c) 2017 Politecnico di Torino and others. + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Apache License, Version 2.0 + * which accompanies this distribution, and is available at + * http://www.apache.org/licenses/LICENSE-2.0 + *******************************************************************************/ + +@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.example.org/nffg/", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED) +package it.polito.nffg.neo4j.jaxb; diff --git a/verigraph/src/main/proto/verigraph.proto b/verigraph/src/main/proto/verigraph.proto new file mode 100644 index 0000000..5f77c78 --- /dev/null +++ b/verigraph/src/main/proto/verigraph.proto @@ -0,0 +1,154 @@ +syntax = "proto3"; + +package verigraph; + +option java_multiple_files = true; +option java_package = "io.grpc.verigraph"; +option java_outer_classname = "VerigraphProto"; + +// The service definition. +service Verigraph { + // Obtains a list of graphs + rpc GetGraphs (GetRequest) returns (stream GraphGrpc) {} + // Obtains a graph + rpc GetGraph (RequestID) returns (GraphGrpc) {} + // Obtains a list of Nodes + rpc GetNodes (RequestID) returns (stream NodeGrpc) {} + // Obtains a node + rpc GetNode (RequestID) returns (NodeGrpc) {} + // Obtains a list of Neighbours + rpc GetNeighbours (RequestID) returns (stream NeighbourGrpc) {} + // Obtains a Neighbour + rpc GetNeighbour (RequestID) returns (NeighbourGrpc) {} + + // Creates a graph + rpc CreateGraph (GraphGrpc) returns (NewGraph) {} + // Delete a graph + rpc DeleteGraph (RequestID) returns (Status) {} + // Updates a graph + rpc UpdateGraph (GraphGrpc) returns (NewGraph) {} + // Verify a policy + rpc VerifyPolicy (Policy) returns (VerificationGrpc) {} + + // Creates a Node + rpc CreateNode (NodeGrpc) returns (NewNode) {} + // Delete a Node + rpc DeleteNode (RequestID) returns (Status) {} + // Updates a Node + rpc UpdateNode (NodeGrpc) returns (NewNode) {} + // Configures a Node + rpc ConfigureNode (ConfigurationGrpc) returns (Status) {} + + // Creates a neighbour + rpc CreateNeighbour (NeighbourGrpc) returns (NewNeighbour) {} + // Delete a neighbour + rpc DeleteNeighbour (RequestID) returns (Status) {} + // Updates a neighbour + rpc UpdateNeighbour (NeighbourGrpc) returns (NewNeighbour) {} +} + +message GetRequest { +} + +message RequestID { + int64 idGraph = 1; + int64 idNode = 2; + int64 idNeighbour = 3; +} + +message Policy{ + int64 idGraph = 1; + string source = 2; + string destination = 3; + enum PolicyType { + reachability = 0; + isolation = 1; + traversal = 2; + } + PolicyType type = 4; + string middlebox = 5; +} + +message ConfigurationGrpc{ + int64 idGraph = 1; + int64 idNode = 2; + string description = 3; + string configuration = 4; + string id = 5; +} + +message NodeGrpc{ + int64 idGraph = 1; + string name = 2; + int64 id = 3; //long + enum FunctionalType { + antispam = 0; + cache = 1; + dpi = 2; + endhost = 3; + endpoint = 4; + fieldmodifier = 5; + firewall = 6; + mailclient = 7; + mailserver = 8; + nat = 9; + vpnaccess = 10; + vpnexit = 11; + webclient = 12; + webserver = 13; + } + FunctionalType functional_type = 4; + repeated NeighbourGrpc neighbour = 5; + ConfigurationGrpc configuration = 6; + string errorMessage = 7; +} + +message GraphGrpc{ + int64 id = 1; //long + repeated NodeGrpc node = 2; + string errorMessage = 3; +} + +message NeighbourGrpc{ + int64 idGraph = 1; + int64 idNode = 2; + string name = 3; + int64 id = 4; //long + string errorMessage = 5; +} + +message NewGraph{ + bool success = 1; + GraphGrpc graph = 2; + string errorMessage = 3; +} + +message NewNode{ + bool success = 1; + NodeGrpc node = 2; + string errorMessage = 3; +} + +message NewNeighbour{ + bool success = 1; + NeighbourGrpc neighbour = 2; + string errorMessage = 3; +} + +message TestGrpc { + repeated NodeGrpc node = 1; + string result = 2; +} + +message VerificationGrpc{ + bool successOfOperation = 1; + string result = 2; + string comment = 3; + repeated TestGrpc test = 4; + string errorMessage = 5; +} + +message Status{ + bool success = 1; + string errorMessage = 2; +}
\ No newline at end of file diff --git a/verigraph/src/main/schema/net_types.xsd b/verigraph/src/main/schema/net_types.xsd new file mode 100644 index 0000000..c99c7a6 --- /dev/null +++ b/verigraph/src/main/schema/net_types.xsd @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="UTF-8"?> +<schema xmlns="http://www.w3.org/2001/XMLSchema" + xmlns:net="http://www.example.org/net/" + targetNamespace="http://www.example.org/net/" + elementFormDefault="qualified"> + + <annotation> + <documentation> + Copyright (C) 2006-2007 Code Synthesis Tools CC + + Redistribution and use with or without modification are permitted + under the terms of the new BSD license. See the accompanying LICENSE + file. + </documentation> + </annotation> + + <simpleType name="macAddressType"> + <restriction base="string"> + <pattern value="(([a-fA-F0-9]{2})-){5,7}[a-fA-F0-9]{2}"/> + </restriction> + </simpleType> + + <simpleType name="ipAddressType"> + <restriction base="string"> + <pattern value="((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])"/> + <pattern value="(([0-9a-fA-F]{1,4}:){6})(([0-9a-fA-F]{1,4}:[0-9a-fA-F]{1,4})|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))"/> + <pattern value="(([0-9a-fA-F]{1,4}:)*|([0-9a-fA-F]{1,4}))*(::)(([0-9a-fA-F]{1,4}:)*|([0-9a-fA-F]{1,4}))*"/> + </restriction> + </simpleType> + + <simpleType name="portNumberType"> + <restriction base="unsignedShort"> + <minInclusive value="1"/> + </restriction> + </simpleType> + + <!-- <complexType name="ipEndpointStructType"> + <sequence> + <element name="address" type="net:ipAddressType"/> + <element name="port" type="net:portNumberType"/> + </sequence> + </complexType> --> + + <simpleType name="ethertypeType"> + <restriction base="unsignedShort"> + <minInclusive value="1536"/> + </restriction> + </simpleType> + + <simpleType name="vlanIdType"> + <restriction base="unsignedShort"> + <minInclusive value="1"/> + <maxInclusive value="4095"/> + </restriction> + </simpleType> + + <simpleType name="vlanPcpType"> + <restriction base="unsignedShort"> + <maxInclusive value="7"/> + </restriction> + </simpleType> +</schema>
\ No newline at end of file diff --git a/verigraph/src/main/schema/nffg.xsd b/verigraph/src/main/schema/nffg.xsd new file mode 100644 index 0000000..77e6f40 --- /dev/null +++ b/verigraph/src/main/schema/nffg.xsd @@ -0,0 +1,363 @@ +<?xml version="1.0" encoding="UTF-8"?> +<schema xmlns="http://www.w3.org/2001/XMLSchema" + xmlns:tns="http://www.example.org/nffg/" + xmlns:net="http://www.example.org/net/" + targetNamespace="http://www.example.org/nffg/" + elementFormDefault="qualified"> + + <import namespace="http://www.example.org/net/" schemaLocation="net_types.xsd"/> + + <annotation> + <documentation xml:lang="it"> + Il formato prevede si possa avere come radice "nffg-set" oppure "nffg". + Nel primo caso ci sono più nf-fg contenuti nello stesso documento XML. + </documentation> + </annotation> + + <group name="L2HeaderParameters"> + <sequence> + <element name="Mac" minOccurs="0"> + <complexType> + <attribute name="src" type="net:macAddressType" use="optional"/> + <attribute name="dst" type="net:macAddressType" use="optional"/> + <attribute name="ethertype" type="net:ethertypeType" use="optional"/> + <attribute name="vlanId" type="net:vlanIdType" use="optional"/> + <attribute name="vlanPcp" type="net:vlanPcpType" use="optional"/> + </complexType> + </element> + </sequence> + </group> + + <group name="L3HeaderParameters"> + <sequence> + <element name="Ip" minOccurs="0"> + <complexType> + <attribute name="src" type="net:ipAddressType" use="optional"/> + <attribute name="dst" type="net:ipAddressType" use="optional"/> + <attribute name="ipProtocol" type="unsignedByte" use="optional"/> + <attribute name="tos" type="unsignedByte" use="optional"/> + </complexType> + </element> + </sequence> + </group> + + <!-- controllare nel programma che non ci siano combinazioni non ammesse --> + <group name="L4HeaderParameters"> + <choice> + <element name="Tcp" minOccurs="0"> + <complexType> + <attribute name="src" type="net:portNumberType" use="optional"/> + <attribute name="dst" type="net:portNumberType" use="optional"/> + </complexType> + </element> + <element name="Udp" minOccurs="0"> + <complexType> + <attribute name="src" type="net:portNumberType" use="optional"/> + <attribute name="dst" type="net:portNumberType" use="optional"/> + </complexType> + </element> + </choice> + </group> + + <!-- alla fine controlloare tutti gli xpath perchè dopo dei cambiamenti potrebbero non andare più bene --> + <element name="nffg-set" type="tns:nffg-setType"> + <unique name="nffgIdUnique"> + <selector xpath="tns:nf-fg"/> + <field xpath="@id"/> + </unique> + + <!-- forse la NF va spostata dentro graphs e resa referenziabile (condivisibile da più nffg) --> + <!-- così facendo però, si deve trovare un modo per avere le NF dentro nffg nel caso sia questo la radice --> + <unique name="nfIdUnique"> + <selector xpath="tns:nf-fg/tns:network_functions/tns:network_function"/> + <field xpath="@id"/> + </unique> + </element> + + <element name="nffg" type="tns:nffgType"> + <unique name="epIdUnique"> + <selector xpath="tns:endpoints/tns:endpoint"/> + <field xpath="@id"/> + </unique> + + <unique name="cpIdUnique"> + <selector xpath="tns:network_functions/tns:network_function/tns:connection_points/tns:connection_point"/> + <field xpath="@id"/> + </unique> + + <unique name="portIdUnique"> + <selector xpath="tns:network_functions/tns:network_function/tns:connection_points/tns:connection_point/tns:port"/> + <field xpath="@id"/> + </unique> + + <unique name="ciIdUnique"> + <selector xpath="tns:network_functions/tns:network_function/tns:control_interfaces/tns:control_interface"/> + <field xpath="@id"/> + </unique> + + <unique name="neIdUnique"> + <selector xpath="tns:network_elements/tns:network_element"/> + <field xpath="@id"/> + </unique> + + <unique name="epcpIdRefUnique"> + <selector xpath="tns:network_elements/tns:network_element/tns:eps-cps/tns:ep-cp"/> + <field xpath="@id_ref"/> + </unique> + </element> + + <complexType name="monParamsType"> + <sequence> + <element name="parameter" maxOccurs="unbounded"> + <complexType> + <attribute name="value" type="NMTOKENS" use="required"/> + </complexType> + </element> + </sequence> + </complexType> + + <complexType name="nffg-setType"> + <sequence> + <element ref="tns:nffg" maxOccurs="unbounded"/> + </sequence> + </complexType> + + <complexType name="nffgType"> + <sequence> + <element name="endpoints" type="tns:epointsType" nillable="true"/> + <element name="network_functions" type="tns:nfunctionsType" nillable="true"/> + <element name="network_elements" type="tns:nelementsType" nillable="true"/> + <element name="monitoring_parameters" type="tns:monParamsType" nillable="true"/> + </sequence> + <attribute name="id" type="tns:nffgIdType" use="optional"/> + <attribute name="version" type="string" use="optional"/> + </complexType> + + <simpleType name="nffgIdType"> + <restriction base="string"> + <pattern value="nffg_\d+"/> + </restriction> + </simpleType> + + <complexType name="epointsType"> + <sequence> + <element name="endpoint" type="tns:epType" maxOccurs="unbounded"/> + </sequence> + </complexType> + + <complexType name="epType"> + <sequence> + <!-- valutare se renderlo nillable o tenere la cardinalità a * --> + <element name="flowspace"> + <complexType> + <sequence> + <group ref="tns:L2HeaderParameters"/> + <group ref="tns:L3HeaderParameters"/> + <group ref="tns:L4HeaderParameters"/> + </sequence> + <attribute name="nodeId" type="string" use="optional"/> + <attribute name="ingPhysPort" type="string" use="optional"/> + </complexType> + </element> + </sequence> + <attribute name="id" type="tns:epIdType" use="required"/> + </complexType> + + <simpleType name="epIdType"> + <restriction base="string"> + <pattern value="[a-z]*_\d+"/> + </restriction> + </simpleType> + + <complexType name="nfunctionsType"> + <sequence> + <element name="network_function" type="tns:nfType" maxOccurs="unbounded"/> + </sequence> + </complexType> + + <complexType name="nfType"> + <sequence> + <element name="specification" type="tns:specType"/> + <element name="connection_points" type="tns:cpointsType"/> + <element name="control_interfaces" type="tns:ctrlInterfacesType"/> + <element name="monitoring_parameters" type="tns:monParamsType" nillable="true"/> + </sequence> + <attribute name="id" type="tns:nfIdType" use="required"/> + <attribute name="functionalType" type="string" use="required"/> + </complexType> + + <simpleType name="nfIdType"> + <restriction base="string"> + <pattern value="[a-z]*_\d+"/> + </restriction> + </simpleType> + + <complexType name="specType"> + <sequence> + <element name="deployment"> + <complexType> + <attribute name="type" type="string" use="optional" default="N.A."/> + </complexType> + </element> + <element name="image"> + <complexType> + <!-- controllare come viene mappata la info --> + <attribute name="uri" type="anyURI" use="optional" default="N.A."/> + </complexType> + </element> + <element name="cpu"> + <complexType> + <attribute name="model" type="string" use="optional" default="N.A."/> + <attribute name="architecture" type="string" use="optional" default="N.A."/> + <attribute name="numCores" type="unsignedByte" use="optional" default="1"/> + <attribute name="clockSpeed" type="string" use="optional" default="N.A."/> + </complexType> + </element> + <element name="memory"> + <complexType> + <attribute name="type" type="string" use="optional" default="N.A."/> + <attribute name="size" type="string" use="optional" default="N.A."/> + </complexType> + </element> + <element name="storage"> + <complexType> + <attribute name="type" type="string" use="optional" default="N.A."/> + <attribute name="size" type="string" use="optional" default="N.A."/> + </complexType> + </element> + </sequence> + </complexType> + + <complexType name="cpointsType"> + <sequence> + <element name="connection_point" type="tns:cpType" maxOccurs="unbounded"/> + </sequence> + </complexType> + + <complexType name="cpType"> + <sequence> + <element name="port" type="tns:portType"/> + </sequence> + <attribute name="id" type="tns:cpIdType" use="required"/> + </complexType> + + <complexType name="portType"> + <attribute name="id" type="unsignedShort" use="required"/> + <attribute name="direction" type="tns:portDirEnumType" use="required"/> + <attribute name="type" type="string" use="optional" default="N.A."/> + </complexType> + + <simpleType name="portDirEnumType"> + <restriction base="string"> + <enumeration value="in"/> + <enumeration value="out"/> + <enumeration value="both"/> + </restriction> + </simpleType> + + <simpleType name="cpIdType"> + <restriction base="string"> + <pattern value="cp_\d+"/> + </restriction> + </simpleType> + + <complexType name="ctrlInterfacesType"> + <sequence> + <!-- valutare se renderlo nillable --> + <element name="control_interface" type="tns:ciType" minOccurs="0" maxOccurs="unbounded"/> + </sequence> + </complexType> + + <complexType name="ciType"> + <sequence> + <element name="attributes"> + <complexType> + <sequence> + <element name="attribute" minOccurs="0" maxOccurs="unbounded"> + <complexType> + <attribute name="value" type="string" use="required"/> + </complexType> + </element> + </sequence> + </complexType> + </element> + </sequence> + <attribute name="id" type="tns:ciIdType" use="required"/> + </complexType> + + <simpleType name="ciIdType"> + <restriction base="string"> + <pattern value="ci_\d+"/> + </restriction> + </simpleType> + + <complexType name="nelementsType"> + <sequence> + <element name="network_element" type="tns:neType" maxOccurs="unbounded"/> + </sequence> + </complexType> + + <complexType name="neType"> + <sequence> + <element name="eps-cps" type="tns:eps-cpsType"/> + <element name="monitoring_parameters" type="tns:monParamsType" nillable="true"/> + </sequence> + <attribute name="id" type="tns:neIdType" use="required"/> + <attribute name="type" type="string" use="required"/> + </complexType> + + <simpleType name="neIdType"> + <restriction base="string"> + <pattern value="ne_\d+"/> + </restriction> + </simpleType> + + <complexType name="eps-cpsType"> + <sequence> + <element name="ep-cp" type="tns:ep-cpType" minOccurs="0" maxOccurs="unbounded"/> + </sequence> + </complexType> + + <complexType name="ep-cpType"> + <sequence> + <element name="flowrules" type="tns:flowrulesType" minOccurs="0" maxOccurs="unbounded"/> + </sequence> + <attribute name="id_ref" type="string" use="required"/> + </complexType> + + <complexType name="flowrulesType"> + <sequence> + <!-- da fare valutazioni analoghe al flowspace di sopra --> + <element name="flowspace"> + <complexType> + <sequence> + <group ref="tns:L2HeaderParameters"/> + <group ref="tns:L3HeaderParameters"/> + <group ref="tns:L4HeaderParameters"/> + </sequence> + <attribute name="ingPort" type="string" use="optional"/> + </complexType> + </element> + <element name="actions" type="tns:actionsType"/> + </sequence> + </complexType> + + <complexType name="actionsType"> + <sequence> + <element name="action" type="tns:actionType" maxOccurs="unbounded"/> + </sequence> + </complexType> + + <complexType name="actionType"> + <attribute name="type" type="tns:actionEnumType" use="required"/> + <attribute name="port" type="string" use="optional"/> + </complexType> + + <!-- controllare via SW che se l'aziione è output la porta deve esserci --> + <simpleType name="actionEnumType"> + <restriction base="string"> + <enumeration value="discard"/> + <enumeration value="output"/> + </restriction> + </simpleType> +</schema>
\ No newline at end of file diff --git a/verigraph/src/main/webapp/json/antispam.json b/verigraph/src/main/webapp/json/antispam.json new file mode 100644 index 0000000..dae3db9 --- /dev/null +++ b/verigraph/src/main/webapp/json/antispam.json @@ -0,0 +1,11 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Antispam", + "description": "Polito Antispam", + "type": "array", + "items": { + "type": "string" + }, + "minItems": 0, + "uniqueItems": true +}
\ No newline at end of file diff --git a/verigraph/src/main/webapp/json/cache.json b/verigraph/src/main/webapp/json/cache.json new file mode 100644 index 0000000..0511e7b --- /dev/null +++ b/verigraph/src/main/webapp/json/cache.json @@ -0,0 +1,11 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Cache", + "description": "Polito Cache", + "type": "array", + "items": { + "type": "string" + }, + "minItems": 0, + "uniqueItems": true +}
\ No newline at end of file diff --git a/verigraph/src/main/webapp/json/database.json b/verigraph/src/main/webapp/json/database.json new file mode 100644 index 0000000..5b02a50 --- /dev/null +++ b/verigraph/src/main/webapp/json/database.json @@ -0,0 +1,5 @@ +[ + + + +] diff --git a/verigraph/src/main/webapp/json/dpi.json b/verigraph/src/main/webapp/json/dpi.json new file mode 100644 index 0000000..6e4dd6f --- /dev/null +++ b/verigraph/src/main/webapp/json/dpi.json @@ -0,0 +1,11 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Dpi", + "description": "Polito IDS", + "type": "array", + "items": { + "type": "string" + }, + "minItems": 0, + "uniqueItems": true +}
\ No newline at end of file diff --git a/verigraph/src/main/webapp/json/endhost.json b/verigraph/src/main/webapp/json/endhost.json new file mode 100644 index 0000000..37c8881 --- /dev/null +++ b/verigraph/src/main/webapp/json/endhost.json @@ -0,0 +1,42 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Endhost", + "description": "Polito Endhost", + "type": "array", + "items": { + "type": "object", + "properties": { + "body": { + "description": "HTTP body", + "type": "string" + }, + "sequence": { + "description": "Sequence number", + "type": "integer" + }, + "protocol": { + "description": "Protocol", + "type": "string", + "enum": ["HTTP_REQUEST", "HTTP_RESPONSE", "POP3_REQUEST", "POP3_RESPONSE"] + }, + "email_from": { + "description": "E-mail sender", + "type": "string" + }, + "url": { + "description": "URL", + "type": "string" + }, + "options": { + "description": "Options", + "type": "string" + }, + "destination": { + "description": "Destination node", + "type": "string" + } + }, + "additionalProperties": false + }, + "maxItems": 1 +}
\ No newline at end of file diff --git a/verigraph/src/main/webapp/json/endpoint.json b/verigraph/src/main/webapp/json/endpoint.json new file mode 100644 index 0000000..1e6a521 --- /dev/null +++ b/verigraph/src/main/webapp/json/endpoint.json @@ -0,0 +1,9 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Endpoint", + "description": "Polito Endpoint", + "type": "array", + "minItems": 0, + "maxItems":0, + "uniqueItems": true +}
\ No newline at end of file diff --git a/verigraph/src/main/webapp/json/fieldmodifier.json b/verigraph/src/main/webapp/json/fieldmodifier.json new file mode 100644 index 0000000..8be9419 --- /dev/null +++ b/verigraph/src/main/webapp/json/fieldmodifier.json @@ -0,0 +1,12 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Field Modifier", + "description": "Polito Field Modifier", + "type": "array", + "items": { + "type": "object" + }, + "minItems": 0, + "maxItems":0, + "uniqueItems": true +}
\ No newline at end of file diff --git a/verigraph/src/main/webapp/json/firewall.json b/verigraph/src/main/webapp/json/firewall.json new file mode 100644 index 0000000..01ec63f --- /dev/null +++ b/verigraph/src/main/webapp/json/firewall.json @@ -0,0 +1,11 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Firewall", + "description": "Polito Firewall", + "type": "array", + "items": { + "type": "object" + }, + "minItems": 0, + "uniqueItems": true +}
\ No newline at end of file diff --git a/verigraph/src/main/webapp/json/mailclient.json b/verigraph/src/main/webapp/json/mailclient.json new file mode 100644 index 0000000..cacfd5f --- /dev/null +++ b/verigraph/src/main/webapp/json/mailclient.json @@ -0,0 +1,22 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Mail Client", + "description": "Polito Mail Client", + "type": "array", + "items": { + "type": "object", + "properties": { + "mailserver": { + "description": "Mail server name", + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "mailserver" + ] + }, + "minItems": 1, + "maxItems": 1, + "uniqueItems": true +}
\ No newline at end of file diff --git a/verigraph/src/main/webapp/json/mailserver.json b/verigraph/src/main/webapp/json/mailserver.json new file mode 100644 index 0000000..974b560 --- /dev/null +++ b/verigraph/src/main/webapp/json/mailserver.json @@ -0,0 +1,12 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Mail Server", + "description": "Polito Mail Server", + "type": "array", + "items": { + "type": "object" + }, + "minItems": 0, + "maxItems": 0, + "uniqueItems": true +}
\ No newline at end of file diff --git a/verigraph/src/main/webapp/json/nat.json b/verigraph/src/main/webapp/json/nat.json new file mode 100644 index 0000000..f2b973a --- /dev/null +++ b/verigraph/src/main/webapp/json/nat.json @@ -0,0 +1,11 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Nat", + "description": "Polito Nat", + "type": "array", + "items": { + "type": "string" + }, + "minItems": 0, + "uniqueItems": true +}
\ No newline at end of file diff --git a/verigraph/src/main/webapp/json/vpnaccess.json b/verigraph/src/main/webapp/json/vpnaccess.json new file mode 100644 index 0000000..907118d --- /dev/null +++ b/verigraph/src/main/webapp/json/vpnaccess.json @@ -0,0 +1,22 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Vpn Access", + "description": "Polito Vpn Access", + "type": "array", + "items": { + "type": "object", + "properties": { + "vpnexit": { + "description": "Vpn Exit", + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "vpnexit" + ] + }, + "minItems": 1, + "maxItems": 1, + "uniqueItems": true +}
\ No newline at end of file diff --git a/verigraph/src/main/webapp/json/vpnexit.json b/verigraph/src/main/webapp/json/vpnexit.json new file mode 100644 index 0000000..c80a138 --- /dev/null +++ b/verigraph/src/main/webapp/json/vpnexit.json @@ -0,0 +1,22 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Vpn Exit", + "description": "Polito Vpn Exit", + "type": "array", + "items": { + "type": "object", + "properties": { + "vpnaccess": { + "description": "Vpn Access", + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "vpnaccess" + ] + }, + "minItems": 1, + "maxItems": 1, + "uniqueItems": true +}
\ No newline at end of file diff --git a/verigraph/src/main/webapp/json/webclient.json b/verigraph/src/main/webapp/json/webclient.json new file mode 100644 index 0000000..dfbc55e --- /dev/null +++ b/verigraph/src/main/webapp/json/webclient.json @@ -0,0 +1,22 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Web client", + "description": "Polito Web Client", + "type": "array", + "items": { + "type": "object", + "properties": { + "webserver": { + "description": "Web server name", + "type": "string" + } + }, + "additionalProperties": false, + "required": [ + "webserver" + ] + }, + "minItems": 1, + "maxItems": 1, + "uniqueItems": true +}
\ No newline at end of file diff --git a/verigraph/src/main/webapp/json/webserver.json b/verigraph/src/main/webapp/json/webserver.json new file mode 100644 index 0000000..5d7a1c4 --- /dev/null +++ b/verigraph/src/main/webapp/json/webserver.json @@ -0,0 +1,12 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Web Server", + "description": "Polito Web Server", + "type": "array", + "items": { + "type": "object" + }, + "minItems": 0, + "maxItems": 0, + "uniqueItems": true +}
\ No newline at end of file diff --git a/verigraph/target/m2e-wtp/web-resources/META-INF/MANIFEST.MF b/verigraph/target/m2e-wtp/web-resources/META-INF/MANIFEST.MF new file mode 100644 index 0000000..6cec037 --- /dev/null +++ b/verigraph/target/m2e-wtp/web-resources/META-INF/MANIFEST.MF @@ -0,0 +1,5 @@ +Manifest-Version: 1.0
+Built-By: verigraph
+Build-Jdk: 1.8.0_121
+Created-By: Maven Integration for Eclipse
+
diff --git a/verigraph/target/m2e-wtp/web-resources/META-INF/maven/it.polito.escape/verify/pom.properties b/verigraph/target/m2e-wtp/web-resources/META-INF/maven/it.polito.escape/verify/pom.properties new file mode 100644 index 0000000..0d84612 --- /dev/null +++ b/verigraph/target/m2e-wtp/web-resources/META-INF/maven/it.polito.escape/verify/pom.properties @@ -0,0 +1,7 @@ +#Generated by Maven Integration for Eclipse +#Sat Feb 25 09:43:36 CET 2017 +version=0.0.1-SNAPSHOT +groupId=it.polito.escape +m2e.projectName=Verigraph4Parser +m2e.projectLocation=/home/verigraph/workspace/Verigraph4Parser +artifactId=verify diff --git a/verigraph/target/m2e-wtp/web-resources/META-INF/maven/it.polito.escape/verify/pom.xml b/verigraph/target/m2e-wtp/web-resources/META-INF/maven/it.polito.escape/verify/pom.xml new file mode 100644 index 0000000..cc211f1 --- /dev/null +++ b/verigraph/target/m2e-wtp/web-resources/META-INF/maven/it.polito.escape/verify/pom.xml @@ -0,0 +1,211 @@ +<!-- Copyright (c) 2017 Politecnico di Torino and others. All rights reserved. + This program and the accompanying materials are made available under the + terms of the Apache License, Version 2.0 which accompanies this distribution, + and is available at http://www.apache.org/licenses/LICENSE-2.0 --> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <groupId>it.polito.escape</groupId> + <artifactId>verify</artifactId> + <packaging>war</packaging> + <version>0.0.1-SNAPSHOT</version> + <name>verify</name> + <url>http://maven.apache.org</url> + <properties> + <grpc.version>1.0.3</grpc.version><!-- CURRENT_GRPC_VERSION --> + <jersey.version>2.22.1</jersey.version> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + <build> + <finalName>verify</finalName> + <extensions> + <extension> + <groupId>kr.motd.maven</groupId> + <artifactId>os-maven-plugin</artifactId> + <version>1.4.1.Final</version> + </extension> + </extensions> + <plugins> + <plugin> + <groupId>org.xolstice.maven.plugins</groupId> + <artifactId>protobuf-maven-plugin</artifactId> + <version>0.5.0</version> + <configuration> + <protocArtifact>com.google.protobuf:protoc:3.1.0:exe:${os.detected.classifier}</protocArtifact> + <pluginId>grpc-java</pluginId> + <pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}</pluginArtifact> + </configuration> + <executions> + <execution> + <goals> + <goal>compile</goal> + <goal>compile-custom</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>2.5.1</version> + <inherited>true</inherited> + <configuration> + <source>1.8</source> + <target>1.8</target> + </configuration> + </plugin> + </plugins> + <pluginManagement> + <plugins> + <plugin> + <groupId>org.eclipse.m2e</groupId> + <artifactId>lifecycle-mapping</artifactId> + <version>1.0.0</version> + <configuration> + <lifecycleMappingMetadata> + <pluginExecutions> + <pluginExecution> + <pluginExecutionFilter> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-enforcer-plugin</artifactId> + <versionRange>[1.0.0,)</versionRange> + <goals> + <goal>enforce</goal> + </goals> + </pluginExecutionFilter> + <action> + <ignore /> + </action> + </pluginExecution> + </pluginExecutions> + </lifecycleMappingMetadata> + </configuration> + </plugin> + </plugins> + </pluginManagement> + </build> + + <dependencyManagement> + <dependencies> + <dependency> + <groupId>org.glassfish.jersey</groupId> + <artifactId>jersey-bom</artifactId> + <version>${jersey.version}</version> + <type>pom</type> + <scope>import</scope> + </dependency> + </dependencies> + </dependencyManagement> + + <dependencies> + <dependency> + <groupId>org.glassfish.jersey.containers</groupId> + <artifactId>jersey-container-servlet-core</artifactId> + <!-- use the following artifactId if you don't need servlet 2.x compatibility --> + <!-- artifactId>jersey-container-servlet</artifactId --> + </dependency> + + <dependency> + <groupId>org.glassfish.jersey.bundles</groupId> + <artifactId>jaxrs-ri</artifactId> + </dependency> + + <!-- <dependency> <groupId>org.glassfish.jersey.media</groupId> <artifactId>jersey-media-moxy</artifactId> + </dependency> --> + + <dependency> + <groupId>org.glassfish.jersey.media</groupId> + <artifactId>jersey-media-json-jackson</artifactId> + </dependency> + + <dependency> + <groupId>io.swagger</groupId> + <artifactId>swagger-jersey2-jaxrs</artifactId> + <version>1.5.0</version> + </dependency> + + <dependency> + <groupId>com.googlecode.json-simple</groupId> + <artifactId>json-simple</artifactId> + <version>1.1</version> + </dependency> + + <!-- added to retrieve server path --> + <!-- <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> + <version>3.1.0</version> <scope>provided</scope> </dependency> --> + + <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 --> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + <version>1.5.6</version> + </dependency> + + + <dependency> + <groupId>com.github.fge</groupId> + <artifactId>json-schema-validator</artifactId> + <version>2.2.6</version> + </dependency> + + <!-- http://mvnrepository.com/artifact/org.json/json --> + <dependency> + <groupId>org.json</groupId> + <artifactId>json</artifactId> + <version>20160212</version> + </dependency> + + <!-- https://mvnrepository.com/artifact/junit/junit --> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.12</version> + </dependency> + + + <dependency> + <groupId>javax.servlet</groupId> + <artifactId>javax.servlet-api</artifactId> + <version>3.1.0</version> + <scope>provided</scope> + </dependency> + + <!-- here start dependencies for grpc --> + <dependency> + <groupId>org.apache.thrift</groupId> + <artifactId>libthrift</artifactId> + <version>0.9.1</version> + </dependency> + <dependency> + <groupId>io.grpc</groupId> + <artifactId>grpc-netty</artifactId> + <version>${grpc.version}</version> + </dependency> + <dependency> + <groupId>io.grpc</groupId> + <artifactId>grpc-protobuf</artifactId> + <version>${grpc.version}</version> + </dependency> + <dependency> + <groupId>io.grpc</groupId> + <artifactId>grpc-stub</artifactId> + <version>${grpc.version}</version> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <version>1.9.5</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>com.google.protobuf</groupId> + <artifactId>protobuf-java</artifactId> + <version>3.0.2</version> + </dependency> + + </dependencies> + +</project> diff --git a/verigraph/tester/README.rst b/verigraph/tester/README.rst new file mode 100644 index 0000000..35396a3 --- /dev/null +++ b/verigraph/tester/README.rst @@ -0,0 +1,38 @@ +.. This work is licensed under a Creative Commons Attribution 4.0 International License. +.. http://creativecommons.org/licenses/by/4.0 + +In order to run the automatic testing script test.py, you need the +following dependencies installed on your python distribution: + +- "requests" python package -> + http://docs.python-requests.org/en/master/ +- "jsonschema" python package -> + https://pypi.python.org/pypi/jsonschema + +IMPORTANT - If you have multiple versions of Python installed on your +machine, check carefully that the version you are actually using when +running the script, has the required packages installed. Requested +version is Python 3+ + +| HINT - to install a package you can raise the following command (Bash + on Linux or DOS shell on Windows): +| python -m pip install jsonschema +| python -m pip install requests + +Tested on PYTHON 3.4.3 + +To add a new test, just put a new .json file inside the testcases +folder. The corresponding JSON schema is in the testcase\_schema.json +file and some examples are already available. Each json file should +specify: + +- id, an integer for the testcase; +- name, the name for the testcase; +- description, an optional description; +- policy\_url\_parameters, the parameters to be appended after the + verification URL (including the '?' character); +- result, the expected verification result; +- graph, the graph to be tested (the same object that you usually POST + to VeriGraph to create a new graph). + The test.py script will test each .json file contained into the + testcases folder and will provide a complete output. diff --git a/verigraph/tester/test.py b/verigraph/tester/test.py new file mode 100644 index 0000000..ad0b82a --- /dev/null +++ b/verigraph/tester/test.py @@ -0,0 +1,115 @@ +#!/usr/bin/python + +############################################################################## +# Copyright (c) 2017 Politecnico di Torino and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +from __future__ import print_function +from jsonschema import validate +from pprint import pprint +import sys +import requests +from requests.exceptions import * +from jsonschema.exceptions import * +import json +import getopt +import os +import subprocess + +# Constants (change them, if appropriate) +VERIGRAPH_PORT = "8080" +TEST_CASES_DIR = "testcases" +BASE_URL = "http://localhost:"+VERIGRAPH_PORT+"/verify/api/graphs/" +SCHEMA_FILE = "testcase_schema.json" + +# Variables +success = 0 +run = 0 + +# Utils +def eprint(toPrint): + sys.stdout.flush() + print(toPrint, file=sys.stderr) + sys.stderr.flush() + +# Print PYTHON ver +print("PYTHON " + sys.version) + +# Loading schema file +try: + schema = json.load(open(SCHEMA_FILE)) +except ValueError: + eprint("Invalid json schema (check your "+SCHEMA_FILE+")!\nExiting.") + exit(-1) + +# Iterate over .json files contained in the TEST_CASES_DIR +for i in os.listdir(TEST_CASES_DIR): + if i.endswith(".json"): + with open(TEST_CASES_DIR+os.path.sep+i) as data_file: + try: + # Load json file (raise exception if malformed) + data = json.load(data_file) + + # Validate input json against schema (raise exception if invalid) + validate(data, schema) + + run += 1 + print("Test case ID: "+str(data["id"])) + print("\tFILE NAME: "+i) + print("\tTEST NAME: "+data["name"]) + print("\tTEST DESCRIPTION: "+data["description"]) + + # POST the graph + r = requests.post(BASE_URL, json=data["graph"]) + if r.status_code == 201: + graph_id = r.json()["id"] + print("\tCreated Graph has ID " + str(graph_id) + " on VeriGraph") + + # GET the policy verification result + policy = requests.get(BASE_URL+str(graph_id)+"/policy"+data["policy_url_parameters"]) + + # Check the response + if policy.status_code == 200: + print("\tVerification result is " + policy.json()["result"]) + + # Check the result with the expected one + if policy.json()["result"] == data["result"]: + # SUCCESS + print("\t+++ Test passed +++") + success += 1 + else: + # FAIL + eprint("\t[ERROR] Expected result was " + data["result"] + " but VeriGraph returned " + policy.json()["result"]) + print("\t--- Test failed ---") + else: + print("\tVeriGraph returned an unexpected response -> " + str(policy.status_code), policy.reason) + print("\t--- Test failed ---") + print() + except ValueError: + print("Malformed json!\nSkipping "+i+" file") + print("\t--- Test failed ---") + except ValidationError: + print("Invalid json (see Schema file)!\nSkipping "+i+" file") + print("\t--- Test failed ---") + except ConnectionError: + print("Connection refused!") + print("\t--- Test failed ---") + except HTTPError: + print("HTTP error!") + print("\t--- Test failed ---") + +# Final output +print("\nTest run = "+str(run)) +print("Test succeded = "+str(success)) +if run != 0: + if success != run: + print("\n --- Some tests failed. See the output. ---") + else: + print("\n +++ All tests passed +++") +else: + print("\n\n +++ 0 tests executed +++")
\ No newline at end of file diff --git a/verigraph/tester/testcase_schema.json b/verigraph/tester/testcase_schema.json new file mode 100644 index 0000000..b069705 --- /dev/null +++ b/verigraph/tester/testcase_schema.json @@ -0,0 +1,33 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Testcase", + "description": "A testcase for VeriGraph", + "type": "object", + "properties": { + "id": { + "description": "The unique identifier for a testcase", + "type": "integer" + }, + "name": { + "description": "Name of the testcase", + "type": "string" + }, + "description": { + "description": "A description for the testcase, specifying what is going to be tested", + "type": "string" + }, + "policy_url_parameters": { + "description": "The set of parameters to be passed in GET request to the verification service", + "type": "string" + }, + "result": { + "description": "The set of parameters to be passed in GET request to the verification service", + "type": "string" + }, + "graph": { + "description": "The graph to be tested", + "type": "object" + } + }, + "required": ["id", "name", "policy_url_parameters", "result", "graph"] +}
\ No newline at end of file diff --git a/verigraph/tester/testcases/test_budapest_sap1_webserver_sat.json b/verigraph/tester/testcases/test_budapest_sap1_webserver_sat.json new file mode 100644 index 0000000..62b4eb5 --- /dev/null +++ b/verigraph/tester/testcases/test_budapest_sap1_webserver_sat.json @@ -0,0 +1,122 @@ +{ + "id":6, + "name":"budapest_test_case_sat", + "description":"This test case verifies budapest scenario, chain sap1->webserver1", + "policy_url_parameters":"?type=reachability&source=sap1&destination=webserver1", + "result":"SAT", + "graph": { + "nodes":[ + { + "neighbours":[ + { + "name":"webserver1" + }, + { + "name":"nat" + } + ], + "configuration":[ + { + "ip_sap1":"webserver1" + } + ], + "name":"fw", + "functional_type":"firewall" + }, + { + "neighbours":[ + { + "name":"sap3" + }, + { + "name":"fw" + } + ], + "name":"webserver1", + "functional_type":"webserver" + }, + { + "neighbours":[ + { + "name":"sap1" + }, + { + "name":"dpi" + }, + { + "name":"fw" + } + ], + "configuration":[ + "sap1", + "sap2" + ], + "name":"nat", + "functional_type":"nat" + }, + { + "neighbours":[ + { + "name":"sap2" + } + ], + "configuration":[ + "drug" + ], + "name":"dpi", + "functional_type":"dpi" + }, + { + "neighbours":[ + { + "name":"nat" + } + ], + "configuration":[ + { + "url":"www.facebook.com", + "body":"cats", + "destination":"webserver1", + "protocol":"HTTP_REQUEST" + } + ], + "name":"sap2", + "functional_type":"endhost" + }, + { + "neighbours":[ + { + "name":"nat" + } + ], + "configuration":[ + { + "url":"www.facebook.com", + "body":"cats", + "destination":"webserver1", + "protocol":"HTTP_REQUEST" + } + ], + "name":"sap1", + "functional_type":"endhost" + }, + { + "neighbours":[ + { + "name":"webserver1" + } + ], + "configuration":[ + { + "url":"www.facebook.com", + "body":"cats", + "destination":"webserver1", + "protocol":"HTTP_REQUEST" + } + ], + "name":"sap3", + "functional_type":"endhost" + } + ] + } +}
\ No newline at end of file diff --git a/verigraph/tester/testcases/test_budapest_sap1_webserver_unsat.json b/verigraph/tester/testcases/test_budapest_sap1_webserver_unsat.json new file mode 100644 index 0000000..211b310 --- /dev/null +++ b/verigraph/tester/testcases/test_budapest_sap1_webserver_unsat.json @@ -0,0 +1,122 @@ +{ + "id":7, + "name":"budapest_test_case_unsat", + "description":"This test case verifies budapest scenario, chain sap1->webserver1 with fw blocking", + "policy_url_parameters":"?type=reachability&source=sap1&destination=webserver1", + "result":"UNSAT", + "graph":{ + "nodes":[ + { + "neighbours":[ + { + "name":"webserver1" + }, + { + "name":"nat" + } + ], + "configuration":[ + { + "webserver1":"nat" + } + ], + "name":"fw", + "functional_type":"firewall" + }, + { + "neighbours":[ + { + "name":"sap3" + }, + { + "name":"fw" + } + ], + "name":"webserver1", + "functional_type":"webserver" + }, + { + "neighbours":[ + { + "name":"sap1" + }, + { + "name":"dpi" + }, + { + "name":"fw" + } + ], + "configuration":[ + "sap1", + "sap2" + ], + "name":"nat", + "functional_type":"nat" + }, + { + "neighbours":[ + { + "name":"sap2" + } + ], + "configuration":[ + "drug" + ], + "name":"dpi", + "functional_type":"dpi" + }, + { + "neighbours":[ + { + "name":"nat" + } + ], + "configuration":[ + { + "url":"www.facebook.com", + "body":"cats", + "destination":"webserver1", + "protocol":"HTTP_REQUEST" + } + ], + "name":"sap2", + "functional_type":"endhost" + }, + { + "neighbours":[ + { + "name":"nat" + } + ], + "configuration":[ + { + "url":"www.facebook.com", + "body":"cats", + "destination":"webserver1", + "protocol":"HTTP_REQUEST" + } + ], + "name":"sap1", + "functional_type":"endhost" + }, + { + "neighbours":[ + { + "name":"webserver1" + } + ], + "configuration":[ + { + "url":"www.facebook.com", + "body":"cats", + "destination":"webserver1", + "protocol":"HTTP_REQUEST" + } + ], + "name":"sap3", + "functional_type":"endhost" + } + ] + } +}
\ No newline at end of file diff --git a/verigraph/tester/testcases/test_user_nat_dpi_webserver_trafficAllowed.json b/verigraph/tester/testcases/test_user_nat_dpi_webserver_trafficAllowed.json new file mode 100644 index 0000000..8e19352 --- /dev/null +++ b/verigraph/tester/testcases/test_user_nat_dpi_webserver_trafficAllowed.json @@ -0,0 +1,59 @@ +{ + "id": 2, + "name": "simple_test_case", + "description": "This test case contains a graph with client, firewall and server", + "policy_url_parameters": "?type=reachability&source=user1&destination=webserver", + "result": "SAT", + "graph": { + "nodes":[ + { + "name":"user1", + "functional_type":"endhost", + "neighbours":[ + { + "name":"nat" + } + ], + "configuration": + [ + { + "body": "cartoon", + "protocol": "HTTP_REQUEST", + "destination": "webserver" + } + ] + }, + { + "name":"nat", + "functional_type":"nat", + "neighbours":[ + { + "name":"dpi" + } + ], + "configuration":[ + "user1" + ] + }, + { + "name":"dpi", + "functional_type":"dpi", + "neighbours":[ + { + "name":"webserver" + } + ], + "configuration":[ + "sex", "droga" + ] + }, + { + "name":"webserver", + "functional_type":"webserver", + "neighbours":[ + + ] + } + ] + } +}
\ No newline at end of file diff --git a/verigraph/tester/testcases/test_user_nat_dpi_webserver_trafficBlocked.json b/verigraph/tester/testcases/test_user_nat_dpi_webserver_trafficBlocked.json new file mode 100644 index 0000000..285ecf2 --- /dev/null +++ b/verigraph/tester/testcases/test_user_nat_dpi_webserver_trafficBlocked.json @@ -0,0 +1,59 @@ +{ + "id": 1, + "name": "simple_test_case", + "description": "This test case contains a graph with client, firewall and server", + "policy_url_parameters": "?type=reachability&source=user1&destination=webserver", + "result": "UNSAT", + "graph": { + "nodes":[ + { + "name":"user1", + "functional_type":"endhost", + "neighbours":[ + { + "name":"nat" + } + ], + "configuration": + [ + { + "body": "sex", + "protocol": "HTTP_REQUEST", + "destination": "webserver" + } + ] + }, + { + "name":"nat", + "functional_type":"nat", + "neighbours":[ + { + "name":"dpi" + } + ], + "configuration":[ + "user1" + ] + }, + { + "name":"dpi", + "functional_type":"dpi", + "neighbours":[ + { + "name":"webserver" + } + ], + "configuration":[ + "sex", "droga" + ] + }, + { + "name":"webserver", + "functional_type":"webserver", + "neighbours":[ + + ] + } + ] + } +}
\ No newline at end of file diff --git a/verigraph/tester/testcases/test_user_nat_vpn_fieldmod_webserver_unsat.json b/verigraph/tester/testcases/test_user_nat_vpn_fieldmod_webserver_unsat.json new file mode 100644 index 0000000..252e3b5 --- /dev/null +++ b/verigraph/tester/testcases/test_user_nat_vpn_fieldmod_webserver_unsat.json @@ -0,0 +1,94 @@ +{ + "id": 4, + "name": "nat_vpn_with_fieldmodifier_test_case", + "description": "This test case contains a graph with client, nat, vpn (with field mod in between) and server", + "policy_url_parameters": "?type=reachability&source=user1&destination=webserver", + "result": "UNSAT", + "graph": { + "nodes":[ + { + "name":"user1", + "functional_type":"endhost", + "neighbours":[ + { + "name":"nat" + } + ], + "configuration": + [ + { + "body": "cartoon", + "protocol": "HTTP_REQUEST", + "destination": "webserver" + } + ] + }, + { + "name":"nat", + "functional_type":"nat", + "neighbours":[ + { + "name":"user1" + }, + { + "name":"vpnaccess" + } + ], + "configuration":[ + "user1" + ] + }, + { + "name":"vpnaccess", + "functional_type":"vpnaccess", + "neighbours":[ + { + "name":"nat" + }, + { + "name":"fieldmodifier" + } + ], + "configuration":[ + {"vpnexit": "vpnexit"} + ] + }, + { + "name":"fieldmodifier", + "functional_type":"fieldmodifier", + "neighbours":[ + { + "name":"vpnaccess" + }, + { + "name":"vpnexit" + } + ] + }, + { + "name":"vpnexit", + "functional_type":"vpnexit", + "neighbours":[ + { + "name":"fieldmodifier" + }, + { + "name":"webserver" + } + ], + "configuration":[ + {"vpnaccess": "vpnaccess"} + ] + }, + { + "name":"webserver", + "functional_type":"webserver", + "neighbours":[ + { + "name": "vpnexit" + } + ] + } + ] + } +}
\ No newline at end of file diff --git a/verigraph/tester/testcases/test_user_nat_vpn_webserver_sat.json b/verigraph/tester/testcases/test_user_nat_vpn_webserver_sat.json new file mode 100644 index 0000000..2ae31bc --- /dev/null +++ b/verigraph/tester/testcases/test_user_nat_vpn_webserver_sat.json @@ -0,0 +1,82 @@ +{ + "id": 3, + "name": "nat_vpn_test_case", + "description": "This test case contains a graph with client, nat, vpn and server", + "policy_url_parameters": "?type=reachability&source=user1&destination=webserver", + "result": "SAT", + "graph": { + "nodes":[ + { + "name":"user1", + "functional_type":"endhost", + "neighbours":[ + { + "name":"nat" + } + ], + "configuration": + [ + { + "body": "cartoon", + "protocol": "HTTP_REQUEST", + "destination": "webserver" + } + ] + }, + { + "name":"nat", + "functional_type":"nat", + "neighbours":[ + { + "name":"user1" + }, + { + "name":"vpnaccess" + } + ], + "configuration":[ + "user1" + ] + }, + { + "name":"vpnaccess", + "functional_type":"vpnaccess", + "neighbours":[ + { + "name":"nat" + }, + { + "name":"vpnexit" + } + ], + "configuration":[ + {"vpnexit": "vpnexit"} + ] + }, + { + "name":"vpnexit", + "functional_type":"vpnexit", + "neighbours":[ + { + "name":"vpnaccess" + }, + { + "name":"webserver" + } + ], + "configuration":[ + {"vpnaccess": "vpnaccess"} + ] + }, + { + "name":"webserver", + "functional_type":"webserver", + "neighbours":[ + { + "name": "vpnexit" + } + ] + } + ] + } +}
\ No newline at end of file diff --git a/verigraph/tester/testcases/test_webserver_vpn_nat_user_unsat.json b/verigraph/tester/testcases/test_webserver_vpn_nat_user_unsat.json new file mode 100644 index 0000000..60d09b3 --- /dev/null +++ b/verigraph/tester/testcases/test_webserver_vpn_nat_user_unsat.json @@ -0,0 +1,82 @@ +{ + "id": 5, + "name": "nat_vpn_test_case_serv_to_user", + "description": "This test case contains a graph with client, nat, vpn and server. webserver -> client", + "policy_url_parameters": "?type=reachability&source=webserver&destination=user1", + "result": "UNSAT", + "graph": { + "nodes":[ + { + "name":"user1", + "functional_type":"endhost", + "neighbours":[ + { + "name":"nat" + } + ], + "configuration": + [ + { + "body": "cartoon", + "protocol": "HTTP_REQUEST", + "destination": "webserver" + } + ] + }, + { + "name":"nat", + "functional_type":"nat", + "neighbours":[ + { + "name":"user1" + }, + { + "name":"vpnaccess" + } + ], + "configuration":[ + "user1" + ] + }, + { + "name":"vpnaccess", + "functional_type":"vpnaccess", + "neighbours":[ + { + "name":"nat" + }, + { + "name":"vpnexit" + } + ], + "configuration":[ + {"vpnexit": "vpnexit"} + ] + }, + { + "name":"vpnexit", + "functional_type":"vpnexit", + "neighbours":[ + { + "name":"vpnaccess" + }, + { + "name":"webserver" + } + ], + "configuration":[ + {"vpnaccess": "vpnaccess"} + ] + }, + { + "name":"webserver", + "functional_type":"webserver", + "neighbours":[ + { + "name": "vpnexit" + } + ] + } + ] + } +}
\ No newline at end of file |