Skip to content

Commit

Permalink
#13 Validate LDAP authentication
Browse files Browse the repository at this point in the history
- Added Code coverage
- Changed plugin directory
- Added new LDAP authentication test

Signed-off-by: Uilian Ries <uilianries@gmail.com>
  • Loading branch information
uilianries committed Feb 1, 2018
1 parent 6f99b66 commit c840870
Show file tree
Hide file tree
Showing 10 changed files with 173 additions and 97 deletions.
21 changes: 15 additions & 6 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,23 +1,32 @@
os: linux
sudo: required
dist: trusty

cache: pip
language: python
python:
- 2.7
- 3.6
os: linux
sudo: required
dist: trusty

install:
- chmod +x .travis/install.sh
- .travis/install.sh
- ".travis/install.sh"

before_script:
- export PYTHONPATH=$PYTHONPATH:$(pwd)

script:
- chmod +x .travis/run.sh
- .travis/run.sh
- ".travis/run.sh"

after_success:
- codecov

deploy:
provider: pypi
user: uilianries
password:
secure: yGrLzRVZTkV9Sax7fEgJjxFBnkocZGwE5wtHy4hzaByI7SeUO3nKvDGiYESw0OnV0ri7LIZ8CauvH9ltyAkLiLZH3saV0z5c5l2f34R5vy3PoEgk1FG6Wv/HBVnYHY3d1IfzjwK9LZintIMkFkt7WYWgOR+FtaFUip81pAW8EbNe36RHms44dL74oZbvHH5fUBXIxwOxP5L+6+H3tob4YQKlP59GgxeGhv8QfpHHMEHDiwbBDeooV1aD4o1VXc2Aw/6n1rnGRELUaxz+5XwnhW5Uw+bMS6sG7GwQb00R/AOCWa4tT+fo643Hh8xtWb1dfNh+0Qcy4gkzZ7Ebwinz+skEmiS7zMWBhnuNJaJicKvUMHgOoB3Q0sqsFaEXYVVGXVh5ZTFYfQKNdASXg8G/A0cLRyFB1JKGi3McBTMs7cjvLhA3E1XZifP1S/Lx3u4tJojS8ZWgDpy9g5DvD4cefO8UZkyzO2r0Prh10EA+Z7EFn+M/hHdwahd++OzEV/L0/SAOUze1ki/SKHYdICUd3P/lqzCKF4eOadEwuqA9Rgj5Yk9A8w1adImhxc20rfIOPUk5vqReXagxg1z4pDcHa7rsmkN/XceIed/pU16H4X9IkQoXFiLjo7svm5Bak5MZl9M7KefiOLusGVOOqmIb7GhVKR4DSQPqA/SDMwWIcJY=
secure: m53R1xVryG63qFQ/so9EhWFRLmnmxHIImsTR03mGonKrhFTl31pdP8YAbDAaEVx+SttKNeDZH9D5fS1RaDPA0h3RZbP8nZ6nz08kUV0chaF/bQc2j5Za3XtLEqd8ZUxudQlZdqQTfRnnyXIBP9AjRo2eTRhDl7qQvwWwLxAxic3Bl/yYFrgTm8I6bsi6BJ4vOaVGfiSrItXny9oEfiPpnG5+tBmhPm910QlZxaiBIe2mfkmxRFx3UaGruXPWQ5C6g2yt++ixixKEUfMED6A1t63vBdDGTAal+iKU3Oc10afr6yi7SpCRTgDOqEXqsofqVU/llha57yKKasitI24+8eoySFVoS/r3ziW3DZTivZ/Tay4bXTQYg2ZZCDLxYGxrR+CVvz8jQPaJlN98M7kc+36h378/3cJ9CUQ3658SCNWb6JjcrTnzXjwKYUv3mo7QB5ZlRoZNHuGriKGE1XU+FZkNPt/ixwZDEVwRAD1O1ag9nmHHo1okSX9G8FrQjKixSz8jY8lAAcFizIx8s7GUa1X+O9aBy5/lnMRXU4cgV8y0NdLjHnvezz8BYegYGM8KmnpVqiEyfyPCeZhq7dNY9C0v93BeosfPsZ5boY6vK9WEYDPQrUM3fK9wA1loPhaNWHvVrg6MEwxBKHvjA/FAJTgPDwNf689AhbfMbY7wYZY=
on:
tags: true
condition: "$TRAVIS_PYTHON_VERSION = '2.7'"
50 changes: 6 additions & 44 deletions .travis/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,48 +3,10 @@
set -e
set -x

if [[ "$(uname -s)" == 'Darwin' ]]; then
brew update || brew update
brew outdated pyenv || brew upgrade pyenv
brew install pyenv-virtualenv
sudo apt-get -qq update
sudo apt-get -qq install -y gcc-multilib g++-multilib
sudo apt-get -qq install -y libsasl2-dev python-dev libldap2-dev libssl-dev

if which pyenv > /dev/null; then
eval "$(pyenv init -)"
fi
if which pyenv > /dev/null; then
eval "$(pyenv init -)"
fi

case "${PYVER}" in
py27)
pyenv install 2.7.10
pyenv virtualenv 2.7.10 conan
;;
py33)
pyenv install 3.3.6
pyenv virtualenv 3.3.6 conan
;;
py34)
pyenv install 3.4.3
pyenv virtualenv 3.4.3 conan
;;
py35)
pyenv install 3.5.0
pyenv virtualenv 3.5.0 conan
;;
py36)
pyenv install 3.6.0
pyenv virtualenv 3.6.0 conan
;;

esac
pyenv rehash
pyenv activate conan
else
sudo apt-get update
sudo apt-get install gcc-multilib g++-multilib
sudo apt-get install libsasl2-dev python-dev libldap2-dev libssl-dev
fi

pip install -r conan/requirements.txt
pip install -r conan/requirements_test.txt
pip install -U -r conan/requirements.txt
pip install -U -r conan/requirements_test.txt
pip install codecov
8 changes: 0 additions & 8 deletions .travis/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,8 @@
set -e
set -x

if [[ "$(uname -s)" == 'Darwin' ]]; then
if which pyenv > /dev/null; then
eval "$(pyenv init -)"
fi
pyenv activate conan
fi

conan user
# Validate distribution
python setup.py sdist
# Execute unit tests
mkdir -p ~/.conan_server/plugins/authenticator/
nosetests -v --with-coverage --cover-package=conan .
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
[![Build Status](https://travis-ci.org/uilianries/conan-ldap-authentication.svg?branch=master)](https://travis-ci.org/uilianries/conan-ldap-authentication)
[![codecov](https://codecov.io/gh/uilianries/conan-ldap-authentication/branch/master/graph/badge.svg)](https://codecov.io/gh/uilianries/conan-ldap-authentication)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Pypi Download](https://img.shields.io/badge/download-pypi-blue.svg)](https://pypi.python.org/pypi/conan-ldap-authentication)
# Conan LDAP Authentication
Expand Down
2 changes: 2 additions & 0 deletions conan/ldap_authentication.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import ldap
from configparser import ConfigParser
from os.path import isfile
Expand Down
3 changes: 2 additions & 1 deletion conan/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pyldap>=2.4.28
configparser>=3.5.0
configparser>=3.5.0
conan>=0.24.0
51 changes: 51 additions & 0 deletions conan/test/configuration_file.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Virtual LDAP configuration
"""
from tempfile import NamedTemporaryFile
from os import environ, path


class ConfigurationFile(object):
test_valid_config = '''
[ldap]
# LDAP server address
host: ldap://ldap.forumsys.com
# Distinguished name (DN) of the entry
distinguished_name: cn=$username,dc=example,dc=com
'''

test_wrong_config = '''
[ldap]
# LDAP server address
host: ldap://ldap.forumsys
# Distinguished name (DN) of the entry
distinguished_name: cn=$username,dc=example,dc=com
'''

test_invalid_config = '''
[server]
# LDAP server address
host: ldap://ldap.forumsys.com
# Distinguished name (DN) of the entry
distinguished_name: cn=$username,dc=example,dc=com
'''

@staticmethod
def create_config_file(file_content):
temp_file = NamedTemporaryFile(prefix="ldap-authentication-", delete=False)
with open(temp_file.name, 'w') as file:
file.write(file_content)
environ["CONAN_LDAP_AUTHENTICATION_CONFIG_FILE"] = temp_file.name

@staticmethod
def create_valid_config():
ConfigurationFile.create_config_file(ConfigurationFile.test_valid_config)

@staticmethod
def create_wrong_config():
ConfigurationFile.create_config_file(ConfigurationFile.test_wrong_config)

@staticmethod
def create_invalid_config():
ConfigurationFile.create_config_file(ConfigurationFile.test_wrong_config)
50 changes: 16 additions & 34 deletions conan/test/test_authentication.py
Original file line number Diff line number Diff line change
@@ -1,38 +1,26 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import unittest
from tempfile import NamedTemporaryFile
from os import environ
from os import environ, path, makedirs
from conan import ldap_authentication
from conan.test.configuration_file import ConfigurationFile
"""Validation for LDAP authenticator
"""


class TestAuthentication(unittest.TestCase):
__test_config = '''
[ldap]
# LDAP server address
host: ldap://ldap.forumsys.com
# Distinguished name (DN) of the entry
distinguished_name: cn=$username,dc=example,dc=com
'''

__test_wrong_config = '''
[ldap]
# LDAP server address
host: ldap://ldap.forumsys
# Distinguished name (DN) of the entry
distinguished_name: cn=$username,dc=example,dc=com
'''
@classmethod
def setUpClass(TestAuthentication):
user_home = environ.get("HOME")
name = path.join(user_home, '.conan_server', 'plugins', 'authentication')
if not path.exists(name):
makedirs(name=name)

__test_invalid_config = '''
[server]
# LDAP server address
host: ldap://ldap.forumsys.com
# Distinguished name (DN) of the entry
distinguished_name: cn=$username,dc=example,dc=com
'''
@classmethod
def tearDownClass(TestAuthentication):
del environ["CONAN_LDAP_AUTHENTICATION_CONFIG_FILE"]

def setUp(self):
self.__create_config_file(TestAuthentication.__test_config)
ConfigurationFile.create_valid_config()

def test_valid_login(self):
authenticator = ldap_authentication.get_class()
Expand All @@ -47,12 +35,12 @@ def test_invalid_password(self):
self.assertFalse(authenticator.valid_user(username="read-only-admin", password="foobar"))

def test_invalid_server(self):
self.__create_config_file(TestAuthentication.__test_wrong_config)
ConfigurationFile.create_wrong_config()
authenticator = ldap_authentication.get_class()
self.assertFalse(authenticator.valid_user(username="read-only-admin", password="foobar"))

def test_invalid_config(self):
self.__create_config_file(TestAuthentication.__test_invalid_config)
ConfigurationFile.create_invalid_config()
authenticator = ldap_authentication.get_class()
self.assertFalse(authenticator.valid_user(username="read-only-admin", password="foobar"))

Expand All @@ -63,9 +51,3 @@ def test_empty_password(self):
def test_empty_username(self):
authenticator = ldap_authentication.get_class()
self.assertFalse(authenticator.valid_user(username=None, password="password"))

def __create_config_file(self, file_content):
self.__temp_file = NamedTemporaryFile(prefix="ldap-authentication-", delete=False)
with open(self.__temp_file.name, 'w') as file:
file.write(file_content)
environ["CONAN_LDAP_AUTHENTICATION_CONFIG_FILE"] = self.__temp_file.name
75 changes: 75 additions & 0 deletions conan/test/test_conan_authentication.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import unittest
import subprocess
import os
import signal
import time
from conans.client.conan_api import ConanAPIV1
import conans.errors
from conan.test.configuration_file import ConfigurationFile
"""Validate LDAP authentication by Conan Server
"""

class TestConanAuthentication(unittest.TestCase):
conan_server_name = 'conan_server'
pid = 0
conan_api = None
conan_server_conf_data = """
[server]
jwt_secret: MnpuzsExftskYGOMgaTYDKfw
jwt_expire_minutes: 120
ssl_enabled: False
port: 9300
public_port:
host_name: localhost
store_adapter: disk
authorize_timeout: 1800
disk_storage_path: ~/.conan_server/data
disk_authorize_timeout: 1800
updown_secret: NyiSWNWnwumTVpGpoANuyyhR
custom_authenticator: ldap_authentication
[write_permissions]
[read_permissions]
*/*@*/*: *
# Authentication type: [raw, ldap]
[auth]
type: users
[users]
"""

@classmethod
def setUpClass(TestConanAuthentication):
conan_server_conf_path = os.path.join(os.path.expanduser('~'), '.conan_server', 'server.conf')
if not os.path.exists(conan_server_conf_path):
with open(conan_server_conf_path, 'w') as file:
file.write(TestConanAuthentication.conan_server_conf_data)
TestConanAuthentication.pid = subprocess.Popen(TestConanAuthentication.conan_server_name, stdout=subprocess.PIPE).pid
time.sleep(3)
TestConanAuthentication.conan_api, _, _ = ConanAPIV1.factory()
TestConanAuthentication.conan_api.remote_add(remote="local", url="http://localhost:9300/")

@classmethod
def tearDownClass(TestConanAuthentication):
os.kill(TestConanAuthentication.pid, signal.SIGTERM)
TestConanAuthentication.conan_api.remote_remove(remote="local")

def test_valid_ldap_login(self):
TestConanAuthentication.conan_api.user(name="read-only-admin", password="password", remote="local")

def test_invalid_ldap_login(self):
try:
TestConanAuthentication.conan_api.user(name="read-only-admin", password="foobar", remote="local")
self.fail()
except conans.errors.AuthenticationException as exception:
self.assertEqual(str(exception), 'Wrong user or password. [Remote: local]')
9 changes: 5 additions & 4 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ def run(self):
:return: None
"""
paths = ['.conan_server', 'plugins', 'authenticator']
paths = ['.conan_server', 'plugins', 'authentication']
conan_path = expanduser('~')
for path in paths:
conan_path = join(conan_path, path)
Expand Down Expand Up @@ -82,7 +82,7 @@ def __get_sudo_gid(self):
# Versions should comply with PEP440. For a discussion on single-sourcing
# the version across setup.py and the project code, see
# https://packaging.python.org/en/latest/single_source_version.html
version="0.2.0",
version="0.2.1",

description='LDAP authenticator for Conan C/C++ package manager',

Expand All @@ -98,8 +98,9 @@ def __get_sudo_gid(self):

# See https://pypi.python.org/pypi?%3Aaction=list_classifiers
classifiers=[
'Development Status :: 4 - Beta',
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Developers',
'Framework :: Conan',
'Topic :: Software Development :: Build Tools',
'License :: OSI Approved :: MIT License',
'Programming Language :: Python :: 2',
Expand Down Expand Up @@ -142,7 +143,7 @@ def __get_sudo_gid(self):
# need to place data files outside of your packages. See:
# http://docs.python.org/3.4/distutils/setupscript.html#installing-additional-files # noqa
# In this case, 'data_file' will be installed into '<sys.prefix>/my_data'
data_files=[('%s/.conan_server/plugins/authenticator' % expanduser('~'), ['conan/ldap_authentication.py'])],
data_files=[(join(expanduser('~'), '.conan_server', 'plugins', 'authentication'), [join('conan', 'ldap_authentication.py')])],

# Give access to write new files at authenticator directory
cmdclass={'install': PostInstallCommand},
Expand Down

0 comments on commit c840870

Please sign in to comment.