diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..4d5352d --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,3 @@ +# Contributing + +See [Contributing](https://minicps.readthedocs.io/en/latest/contributing.html) diff --git a/Makefile b/Makefile index 7611c5e..8f728dc 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,8 @@ # MiniCPS makefile # VARIABLES {{{1 + +LATEST_VERSION = 1.1.3 MININET = sudo mn PYTHON = sudo python @@ -145,6 +147,6 @@ pypi-wheel: ./setup.py sdist bdist_wheel pypi-upload: - $(UPLOADER) upload dist/* + $(UPLOADER) upload dist/minicps-$(LATEST_VERSION)* # }}} diff --git a/README.md b/README.md index ca23f61..3b0717f 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [CS img]: https://travis-ci.org/scy-phy/minicps.svg [![Awesome](https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg)](https://github.com/hslatman/awesome-industrial-control-system-security) -# MiniCPS # +# MiniCPS MiniCPS is a framework for Cyber-Physical Systems real-time simulation. It includes support for physical process and control devices simulation, and @@ -15,3 +15,7 @@ network emulation. It is build on top of MiniCPS is developed by the [SCy-Phy](http://scy-phy.github.io/index.html) group from SUTD (Singapore University of Design and Technology). + +## Contributing + +See [Contributing](https://minicps.readthedocs.io/en/latest/contributing.html) diff --git a/RELEASES.md b/RELEASES.md index 6303d51..6958af6 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,5 +1,14 @@ # Releases and Changelog +## Version 1.1.3 (2017-05-14) + +### Misc + +* Add `CONTRIBTING.md` and related docs + * Clarify difference between user and devs installations + +* Fix dependencies issues + ## Version 1.1.2 (2017-05-14) ### Misc diff --git a/docs/conf.py b/docs/conf.py index 3a8766c..94c20b9 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -58,7 +58,7 @@ # General information about the project. project = u'minicps' -copyright = u'2015, scy-phy' +copyright = u'2017, Daniele Antonioli' author = u'scy-phy' # The version info for the project you're documenting, acts as replacement for diff --git a/docs/contributing.rst b/docs/contributing.rst new file mode 100644 index 0000000..f921048 --- /dev/null +++ b/docs/contributing.rst @@ -0,0 +1,239 @@ +.. CONTRIBUTING {{{1 +.. _contributing: + +************* +Contributing +************* + +This doc provides information about how to contribute to the MiniCPS +projects. + +.. HOW TO START {{{2 + +============= +How to start +============= + + +General design principles +------------------------- + +MiniCPS follows an object-oriented design pattern. It is using ``python2.x`` +for compatibility reasons with ``mininet``. We are trying to lower the number +of external dependencies, and eventually move to ``python3.x``. + +* Design points: + + * separation of concerns (eg: public API vs private APi) + * modularity (eg: different protocols and state backends) + * testability (eg: unit tests and TDD) + * performance (eg: real-time simulation) + +* Security points: + + * avoid unsafe programming languages + * user input is untrusted and has to be validated (eg: prepared statements) + * safe vs unsafe code separation + * automated static analysis + +* Core components: + + * ``minicps`` module (should be in the ``PYTHONPATH``) + * ``examples`` use cases (can be anywhere in the filesystem) + + +Development sytle +----------------- + +MiniCPS is hosted on Github and encourages `canonical submission of +contributions +`_ +it uses +`semantic versioning `_, +``nose`` for `test-driven development +`_ and +``make`` as a launcher for various tasks. + +Required code +--------------- + +Clone the ``minicps`` repository: + +.. code-block:: console + + git clone https://github.com/scy-phy/minicps + +Add ``minicps`` to the python path, for example using a soft link: + +.. code-block:: console + + ln -s ~/minicps/minicps /usr/lib/python2.7/minicps + + +Install the requirements using: + +.. code-block:: console + + pip install -r ~/minicps/requirements-dev.txt + +Run the tests with: + +.. code-block:: console + + cd ~/minicps + make tests + +Code conventions +---------------- + +The project it is based on PEP8 (code) and PEP257 (docstring). + +* Naming scheme: + + * Private data: prepend ``_`` eg: ``_method_name`` or ``_attribute_name`` + * Classes: ``ClassName`` or ``CLASSName``, ``method_name`` and ``instance_name`` + * Others: ``function_name``, ``local_variable_name``, ``GLOBAL_VARIABLE_NAME`` + * Filenames: ``foldername``, ``module.py``, ``another_module.py`` + and ``module_tests.py`` + * Test: ``test_ClassName`` ``test_function_name`` + * Makefile: ``target-name`` ``VARIABLE_NAME`` + * Makers: ``TODO``, ``FIXME``, ``XXX``, ``NOTE`` ``VIM MARKER {{{ + ... }}}`` + * Docs: ``doc.rst``, ``another-doc.rst`` \and ``SPHINX_DOC_NAME SOMETHING(`` for + Sphinx's ``literalinclude`` + + +Module docstring: + +.. code-block:: python + + """ + ``modulename`` contains: + + - bla + + First paragraph. + + ... + + Last paragraph. + """ + +Function docstrings: + +.. code-block:: python + + def my_func(): + """Bla.""" + + pass + + def my_func(): + """Bla. + + :returns: wow + """ + + pass + +Class docstring to document (at least) public methods: + +.. code-block:: python + + class MyClass(object): + + """Bla.""" + + def __init__(self): + """Bla.""" + + pass + +.. }}} + +.. PROTOCOLS {{{2 + +========= +Protocols +========= + +Compatibility with new (industrial) protocols depends on the availability of +a good open-source library implementing that protocol (eg: ``pymodbus`` for +Modbus protocols). + +If you want to add a new protocol please look at the ``minicps/protocols.py`` +module. ``Protocol`` is the base class, and the +``[NewProtocolName]Protocol(Protocol)`` should be your new child class +(inheriting from the ``Protocol`` class) containing +the code to manage the new protocol. A good point to start it to take a look +at ``tests/protocols_tests.py`` to see how other protocols classes +are unit-tested. + +If you want to improve the compatibility of a supported protocol please take +a look at its implementation and unit-testing classes. For example, look at +``ModbusProtocol(Protocol)`` and ``TestModbusProtocol()`` if you want to improve +the Modbus protocol support. + +.. }}} + +.. STATES {{{2 + +====== +States +====== + +The same reasoning presented in the Protocols section applies here. The +relevant source code is located in ``minicps/states.py`` and +``tests/states_tests.py``. + +.. }}} + +.. TESTING {{{2 + +======== +Testing +======== + +Unit testing is hard to setup properly! Please if you find any inconsistent unit test or +decomposable unit test or you want to add a new one then send a PR. + +.. }}} + +.. EXAMPLES {{{2 + +======== +Examples +======== + +Please feel free to send PRs about new use cases that are not already present +in the ``examples`` directory. + +.. }}} + +.. DOCS {{{2 + +======== +Docs +======== + +All the docs are stored in the ``docs`` folder. We are using ``sphinx`` to +render the docs and the ``rst`` markup language to write them. Some of the +docs are automatically generated from the code and others are written by +hands. + +To build you documentation locally use one of the target of the ``Makefile`` +present in the ``docs`` folder. For example, to build and navigate an html +version of our docs type: + +.. code-block:: console + + cd docs + make html + firefox _build/html/index.html + +Please send a PR if you find any typo, incorrect explanation, etc. + +.. }}} + +.. }}} + diff --git a/docs/index.rst b/docs/index.rst index faf097c..727ca18 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -14,6 +14,7 @@ Contents: userguide api swat-tutorial + contributing tests misc diff --git a/docs/swat-tutorial.rst b/docs/swat-tutorial.rst index 85ac4e0..c3c0999 100644 --- a/docs/swat-tutorial.rst +++ b/docs/swat-tutorial.rst @@ -5,10 +5,10 @@ SWaT tutorial ************* -This tutorial shows how to use MiniCPS to simulate a subprocess of a +This tutorial shows how to use MiniCPS to simulate a subprocess of a Water Treatment testbed. In particular, we demonstrate basic controls through simulated PLCs, the network traffic, and simple physical layer simulation. We -now provide: +now provide: * A list of the pre-requisites to run the tutorial * A brief system overview diff --git a/docs/userguide.rst b/docs/userguide.rst index 7e0fc1e..9a4c8b8 100644 --- a/docs/userguide.rst +++ b/docs/userguide.rst @@ -42,9 +42,8 @@ requirements for MiniCPS (e.g., it can be used to display a pop-up window with sensor data visualization). The `Install MiniCPS`_ section provides instructions to install ``minicps`` -on a machine that is running the **latest official mininet VM (Ubuntu)**. Please -refer to your distribution documentation if you need to install Mininet on -other Linux distributions. +for a user or a developer, and it assumes that you *already* have installed +``mininet``. .. INSTALL MINICPS {{{3 @@ -52,45 +51,41 @@ other Linux distributions. Install MiniCPS --------------- -Login the OS containing ``mininet`` installation then navigate to your home -directory: +MiniCPS is can be installed using ``pip``: .. code-block:: console - cd + sudo pip install minicps -Make sure that the distro is up to date (if necessary, restart the system): +Test the installation downloading one of our examples from +https://github.com/scy-phy/minicps/tree/master/examples and try to run it. -.. code-block:: console - - sudo apt-get update - sudo apt-get upgrade - -Then clone ``minicps`` repository: +For example, given that you downloaded the ``examples`` directory, +then you can ``cd swat-s1`` folder and run: .. code-block:: console - git clone https://github.com/scy-phy/minicps + sudo python run.py -and add ``minicps`` to the python path, for example using a soft link: +And you should see the following: .. code-block:: console - ln -s ~/minicps/minicps /usr/lib/python2.7/minicps - -MiniCPS is compatible with *python 2.7.X*. Install dependencies using: - -.. code-block:: console + *** Ping: testing ping reachability + attacker -> plc1 plc2 plc3 + plc1 -> attacker plc2 plc3 + plc2 -> attacker plc1 plc3 + plc3 -> attacker plc1 plc2 + *** Results: 0% dropped (12/12 received) + mininet> - sudo apt-get install python-matplotlib python-networkx python-pil.imagetk -For *Ethernet/IP* support install ``cpppo`` - -.. code-block:: console +.. INSTALL OPTIONAL {{{3 +.. _install-optional: - sudo pip install cpppo +Install Optional Packages +------------------------- -.. TODO: add modbus maybe reorganize the deps For *SDN controller development* there are many options, ``pox`` is a good starting point and Mininet's VM already includes it. If you @@ -109,50 +104,17 @@ execute the following: ~/minicps/bin/pox-init.py [-p POX_PATH -m MINICPS_PATH -vv] -Notice that: +Notice that: * You can increase the verbosity level using either ``v`` or ``-vv`` * ``POX_PATH`` defaults to ``~/pox`` and ``MINICPS_PATH`` defaults to ``~/minicps``, indeed ``~/minicps/bin/init`` should work for you. -.. INSTALL OPTIONAL {{{3 -.. _install-optional: - -Install optional dependencies --------------------------------- - -For *testing* support install dependencies using: - -.. code-block:: console - - sudo apt-get install python-pip python-nose python-coverage - sudo pip install nose-cov - -To generate the *documentation* from the source we use the ``sphinx`` tool. -Please type: - -.. code-block:: console - - sudo apt-get install python-sphinx libjs-mathjax - sudo pip install sphinx-rtd-theme - -.. TESTING INSTALLATION {{{3 - -Testing installation ----------------------- - -Now you should be able to run: - -.. code-block:: console - - cd ~/minicps - make tests - -.. Which should start the command line with ``mininet>`` prompt. To directly -.. continue with the tutorial, look at :ref:`swat-tutorial`. +If you want to contribute to the project please take a look at +:ref:`contributing`. .. CONFIGURE MINICPS {{{2 @@ -178,8 +140,7 @@ using the ``-Y`` option: .. code-block:: console - ssh -Y mininet@minnetvm - + ssh -Y mininet@mininetvm .. IPv6 {{{3 @@ -215,32 +176,3 @@ Instruction taken from `here `_ -.. OFFILNE DOCUMENTATION {{{3 - -Offline Documentation ---------------------- - -First install packages listed in `Install optional dependencies`_. - -Then open ``docs/Makefile`` and check that ``SPHINXBUILD`` reference to -``sphinx-build`` command. (e.g., Arch Linux users can use ``sphinx-build2``) - -Then to build the doc in ``html`` format type: - -.. code-block:: console - - cd docs - make html - -Then to navigate a static version through a browser (e.g., ``firefox``) type: - -.. code-block:: console - - firefox _build/html/index.html - - -.. LOGGING AND TESTING {{{2 - -.. Logging and Testing -.. ==================== -.. TODO diff --git a/examples/swat-s1/run.py b/examples/swat-s1/run.py index 759c7f8..1c38810 100644 --- a/examples/swat-s1/run.py +++ b/examples/swat-s1/run.py @@ -20,7 +20,9 @@ def __init__(self, name, net): self.name = name self.net = net - self.net.start() + net.start() + + net.pingAll() # start devices plc1, plc2, plc3, s1 = self.net.get( @@ -35,7 +37,7 @@ def __init__(self, name, net): CLI(self.net) - self.net.stop() + net.stop() if __name__ == "__main__": diff --git a/examples/swat-s1/tests.py b/examples/swat-s1/tests.py index fbe73dc..93d8f0f 100644 --- a/examples/swat-s1/tests.py +++ b/examples/swat-s1/tests.py @@ -5,8 +5,6 @@ # from mininet.cli import CLI from mininet.net import Mininet -from nose.plugins.skip import SkipTest - from utils import STATE, RWT_INIT_LEVEL from utils import TANK_SECTION from topo import SwatTopo @@ -17,7 +15,6 @@ # import sys -@SkipTest def test_init(): pass diff --git a/minicps/utils.py b/minicps/utils.py index 82a446f..5606943 100644 --- a/minicps/utils.py +++ b/minicps/utils.py @@ -16,8 +16,6 @@ import os from mininet.util import dumpNodeConnections -from nose import with_setup - # logging {{{1 # https://docs.python.org/2/howto/logging.html @@ -118,14 +116,6 @@ def teardown_func(test_name): pass -def with_named_setup(setup=None, teardown=None): - def wrap(f): - return with_setup( - lambda: setup(f.__name__) if (setup is not None) else None, - lambda: teardown(f.__name__) if (teardown is not None) else None)(f) - return wrap - - # TODO: test it def _arp_cache_rtts(net, h1, h2): """Learning check on the first two ping ICMP packets RTT. diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 0000000..1788721 --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1,9 @@ +networkx +coverage +nose +rednose +cryptography +pyasn1 +pymodbus +cpppo + diff --git a/requirements.txt b/requirements.txt index d4745f7..d7aa635 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,3 @@ -coverage nose rednose cryptography diff --git a/setup.py b/setup.py index ec9b577..3d14dd7 100755 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ # NOTE: https://packaging.python.org/ setup( name='minicps', - version='1.1.2', + version='1.1.3', description='MiniCPS: a framework for Cyber-Physical Systems \ real-time simulation, built on top of mininet.', # NOTE: long_description displayed on PyPi diff --git a/tests/states_tests.py b/tests/states_tests.py index 62bf04a..2d323a4 100644 --- a/tests/states_tests.py +++ b/tests/states_tests.py @@ -10,8 +10,6 @@ from nose.tools import eq_ from nose.plugins.skip import SkipTest -# TODO: change to /tmp when install SQLitesutdio in ubuntu - PATH = "/tmp/states_tests.sqlite" NAME = 'states_tests' STATE = {