Repository: cowrie/cowrie

Issue:
Cowrie not set up for py.test framework
So I tried running the test in both python2 and python3. For python2 all the tests were passing but for python3 there was some error.

```
 py.test --cov=cowrie                     
===================================================================================== test session starts =====================================================================================
platform linux -- Python 3.7.2, pytest-4.2.0, py-1.7.0, pluggy-0.8.1
rootdir: /home/mzfr/dev/cowrie, inifile:
plugins: cov-2.6.1
collected 3 items / 3 errors                                                                                                                                                                  

=========================================================================================== ERRORS ============================================================================================
___________________________________________________________________ ERROR collecting src/cowrie/test/test_base_commands.py ____________________________________________________________________
../shell/fs.py:26: in <module>
    PICKLE = pickle.load(open(CONFIG.get('shell', 'filesystem'), 'rb'))
../core/config.py:29: in get
    return super(EnvironmentConfigParser, self).get(section, option, **kwargs)
/usr/lib/python3.7/configparser.py:780: in get
    d = self._unify_values(section, vars)
/usr/lib/python3.7/configparser.py:1146: in _unify_values
    raise NoSectionError(section) from None
E   configparser.NoSectionError: No section: 'shell'

During handling of the above exception, another exception occurred:
test_base_commands.py:12: in <module>
    from cowrie.shell import protocol
../shell/protocol.py:21: in <module>
    from cowrie.shell import command
../shell/command.py:20: in <module>
    from cowrie.shell import fs
../shell/fs.py:29: in <module>
    exit(2)
/usr/lib/python3.7/_sitebuiltins.py:26: in __call__
    raise SystemExit(code)
E   SystemExit: 2
--------------------------------------------------------------------------------------- Captured stdout ---------------------------------------------------------------------------------------
ERROR: Config file not found: etc/cowrie.cfg.dist
________________________________________________________________________ ERROR collecting src/cowrie/test/test_echo.py ________________________________________________________________________
../shell/fs.py:26: in <module>
    PICKLE = pickle.load(open(CONFIG.get('shell', 'filesystem'), 'rb'))
../core/config.py:29: in get
    return super(EnvironmentConfigParser, self).get(section, option, **kwargs)
/usr/lib/python3.7/configparser.py:780: in get
    d = self._unify_values(section, vars)
/usr/lib/python3.7/configparser.py:1146: in _unify_values
    raise NoSectionError(section) from None
E   configparser.NoSectionError: No section: 'shell'

During handling of the above exception, another exception occurred:
test_echo.py:16: in <module>
    from cowrie.shell import protocol
../shell/protocol.py:21: in <module>
    from cowrie.shell import command
../shell/command.py:20: in <module>
    from cowrie.shell import fs
../shell/fs.py:29: in <module>
    exit(2)
/usr/lib/python3.7/_sitebuiltins.py:26: in __call__
    raise SystemExit(code)
E   SystemExit: 2
--------------------------------------------------------------------------------------- Captured stdout ---------------------------------------------------------------------------------------
ERROR: Config file not found: etc/cowrie.cfg.dist
________________________________________________________________________ ERROR collecting src/cowrie/test/test_tftp.py ________________________________________________________________________
../shell/fs.py:26: in <module>
    PICKLE = pickle.load(open(CONFIG.get('shell', 'filesystem'), 'rb'))
../core/config.py:29: in get
    return super(EnvironmentConfigParser, self).get(section, option, **kwargs)
/usr/lib/python3.7/configparser.py:780: in get
    d = self._unify_values(section, vars)
/usr/lib/python3.7/configparser.py:1146: in _unify_values
    raise NoSectionError(section) from None
E   configparser.NoSectionError: No section: 'shell'

During handling of the above exception, another exception occurred:
test_tftp.py:16: in <module>
    from cowrie.shell import protocol
../shell/protocol.py:21: in <module>
    from cowrie.shell import command
../shell/command.py:20: in <module>
    from cowrie.shell import fs
../shell/fs.py:29: in <module>
    exit(2)
/usr/lib/python3.7/_sitebuiltins.py:26: in __call__
    raise SystemExit(code)
E   SystemExit: 2
--------------------------------------------------------------------------------------- Captured stdout ---------------------------------------------------------------------------------------
ERROR: Config file not found: etc/cowrie.cfg.dist
```


Discussion:
Hi! 
So far we are running `Twisted Trial` as the unit testing framework. 
There are multiple frameworks around in Python, if there's a need to switch, then we should make a selection, but so far we are using Twisted Trial. 

I'm curious though because most of it seemed to work on Py2 but not Py3? The file system issues you are having with directory paths should be the same on both versions of Python.
This is because of the config file problem.
Right now we don't have an absolute path for the config files which cause the problem.

If we change the [Line 44](https://github.com/cowrie/cowrie/blob/master/src/cowrie/core/config.py#L44) from
```python
CONFIG = readConfigFile(("etc/cowrie.cfg.dist", "/etc/cowrie/cowrie.cfg", "etc/cowrie.cfg", "cowrie.cfg"))
``` 
to 
```python
CONFIG = readConfigFile(("/home/mzfr/dev/cowrie/etc/cowrie.cfg"))
```
This works fine.

Resolving patch:
diff --git a/src/cowrie/core/config.py b/src/cowrie/core/config.py
--- a/src/cowrie/core/config.py
+++ b/src/cowrie/core/config.py
@@ -8,7 +8,8 @@
 from __future__ import absolute_import, division
 
 import configparser
-import os
+from os import environ
+from os.path import abspath, dirname, exists, join
 
 
 def to_environ_key(key):
@@ -18,15 +19,16 @@ def to_environ_key(key):
 class EnvironmentConfigParser(configparser.ConfigParser):
 
     def has_option(self, section, option):
-        if to_environ_key('_'.join((section, option))) in os.environ:
+        if to_environ_key('_'.join((section, option))) in environ:
             return True
         return super(EnvironmentConfigParser, self).has_option(section, option)
 
     def get(self, section, option, **kwargs):
         key = to_environ_key('_'.join((section, option)))
-        if key in os.environ:
-            return os.environ[key]
-        return super(EnvironmentConfigParser, self).get(section, option, **kwargs)
+        if key in environ:
+            return environ[key]
+        return super(EnvironmentConfigParser, self).get(
+            section, option, **kwargs)
 
 
 def readConfigFile(cfgfile):
@@ -36,9 +38,26 @@ def readConfigFile(cfgfile):
     @param cfgfile: filename or array of filenames
     @return: ConfigParser object
     """
-    parser = EnvironmentConfigParser(interpolation=configparser.ExtendedInterpolation())
+    parser = EnvironmentConfigParser(
+        interpolation=configparser.ExtendedInterpolation())
     parser.read(cfgfile)
     return parser
 
 
-CONFIG = readConfigFile(("etc/cowrie.cfg.dist", "/etc/cowrie/cowrie.cfg", "etc/cowrie.cfg", "cowrie.cfg"))
+def get_config_path():
+    """Get absolute path to the config file
+    """
+    config_files = ["etc/cowrie/cowrie.cfg", "etc/cowrie.cfg",
+                    "cowrie.cfg", "etc/cowrie.cfg.dist"]
+    current_path = abspath(dirname(__file__))
+    root = "/".join(current_path.split("/")[:-3])
+
+    for file in config_files:
+        absolute_path = join(root, file)
+        if exists(absolute_path):
+            return absolute_path
+
+    print("Config file not found")
+
+
+CONFIG = readConfigFile(get_config_path())


Test patch: