Skip to content

Commit

Permalink
Merge pull request #9 from wrocha/bugfix-tacacsrc
Browse files Browse the repository at this point in the history
TACACSRC multiline bug fix and unittests update
  • Loading branch information
Jathan McCollum committed Mar 28, 2014
2 parents 7a508e5 + 604ecf9 commit 36d91dc
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 11 deletions.
7 changes: 7 additions & 0 deletions tests/data/brokenpw_tacacsrc
@@ -0,0 +1,7 @@
# Saved by test_tacacsrc at 2014-03-20 15:35:23 GMT

LONGPWCREDS_uname_ = hpRBGORH+9y7OLTVV2fZcA==
LONGPWCREDS_pwd_ = DgEBETXDEncOAQERNcMSdw4BARE1wxJ3DgEBETXDEncOAQERNcMSdw4BARE1wxJ3DgEBETXDEncO
AQERNcMSdw4BARE1wxJ3DgEBETXDEncOAQERNcMSdw4BARE1wxJ3DgEBETXDEncOAQERNcMSdw4B
ARE1wxJ3DgEBETXDEncOAQERNcMSdw4BARE1wxJ3DgEBETXDEncOAQERNcMSdw4BARE1wxJ3DgEB
ETXDEncOAQERNcMSdw==
4 changes: 4 additions & 0 deletions tests/data/emptypw_tacacsrc
@@ -0,0 +1,4 @@
# Saved by trigger.tacacsrc at 2014-03-27 16:10:33 GMT

EMPTYPWCREDS_uname_ = vjG6C84fD8fLdkVMuX+8Dw==
EMPTYPWCREDS_pwd_ =
4 changes: 4 additions & 0 deletions tests/data/longpw_tacacsrc
@@ -0,0 +1,4 @@
# Saved by test_tacacsrc at 2014-03-20 15:35:23 GMT

LONGPWCREDS_uname_ = hpRBGORH+9y7OLTVV2fZcA==
LONGPWCREDS_pwd_ = DgEBETXDEncOAQERNcMSdw4BARE1wxJ3DgEBETXDEncOAQERNcMSdw4BARE1wxJ3DgEBETXDEncOAQERNcMSdw4BARE1wxJ3DgEBETXDEncOAQERNcMSdw4BARE1wxJ3DgEBETXDEncOAQERNcMSdw4BARE1wxJ3DgEBETXDEncOAQERNcMSdw4BARE1wxJ3DgEBETXDEncOAQERNcMSdw4BARE1wxJ3DgEBETXDEncOAQERNcMSdw==
4 changes: 4 additions & 0 deletions tests/data/medium_tacacsrc
@@ -0,0 +1,4 @@
# Saved by test_tacacsrc at 2014-03-20 15:35:23 GMT
#
MEDIUMPWCREDS_uname_ = lCyjasq21Yp+ZvqgftGOWw==
MEDIUMPWCREDS_pwd_ = zDZLFvLK8dlXO2tgTeIC3H+2NVzGxQt1zDZLFvLK8dlXO2tgTeIC3H+2NVzGxQt1zDZLFvLK8dlXO2tgTeIC3H+2NVzGxQt1
6 changes: 6 additions & 0 deletions tests/data/settings.py
Expand Up @@ -13,6 +13,12 @@
DEFAULT_REALM = 'aol'
TACACSRC_KEYFILE = os.getenv('TACACSRC_KEYFILE', os.path.join(PREFIX, 'tackf'))
TACACSRC = os.getenv('TACACSRC', os.path.join(PREFIX, 'tacacsrc'))
RIGHT_TACACSRC = os.getenv('TACACSRC', os.path.join(PREFIX, 'right_tacacsrc'))
MEDIUMPW_TACACSRC = os.getenv('TACACSRC', os.path.join(PREFIX, 'mediumpw_tacacsrc'))
LONGPW_TACACSRC = os.getenv('TACACSRC', os.path.join(PREFIX, 'longpw_tacacsrc'))
BROKENPW_TACACSRC = os.getenv('TACACSRC', os.path.join(PREFIX, 'brokenpw_tacacsrc'))
EMPTYPW_TACACSRC = os.getenv('TACACSRC', os.path.join(PREFIX, 'emptypw_tacacsrc'))


# Configs
NETDEVICES_SOURCE = os.environ.get('NETDEVICES_SOURCE',
Expand Down
6 changes: 5 additions & 1 deletion tests/data/tacacsrc
@@ -1,4 +1,8 @@
# Dummy .tacacsrc file. Decrypts to user "jschmoe", password "abc123".
# tacacsrc file for test_tacacsrc.py

MEDIUMPWCREDS_uname_ = lCyjasq21Yp+ZvqgftGOWw==
MEDIUMPWCREDS_pwd_ = zDZLFvLK8dlXO2tgTeIC3H+2NVzGxQt1zDZLFvLK8dlXO2tgTeIC3H+2NVzGxQt1zDZLFvLK8dlXO2tgTeIC3H+2NVzGxQt1
LONGPWCREDS_uname_ = hpRBGORH+9y7OLTVV2fZcA==
LONGPWCREDS_pwd_ = DgEBETXDEncOAQERNcMSdw4BARE1wxJ3DgEBETXDEncOAQERNcMSdw4BARE1wxJ3DgEBETXDEncOAQERNcMSdw4BARE1wxJ3DgEBETXDEncOAQERNcMSdw4BARE1wxJ3DgEBETXDEncOAQERNcMSdw4BARE1wxJ3DgEBETXDEncOAQERNcMSdw4BARE1wxJ3DgEBETXDEncOAQERNcMSdw4BARE1wxJ3DgEBETXDEncOAQERNcMSdw==
aol_uname_ = xc732xCvl5M=
aol_pwd_ = uJ6J2YMUhao=
56 changes: 47 additions & 9 deletions tests/test_tacacsrc.py
Expand Up @@ -11,18 +11,42 @@
import os
import unittest
import tempfile
from mock import patch
from trigger.conf import settings
from trigger.tacacsrc import Tacacsrc, Credentials


# Constants
RIGHT_CREDS = Credentials('jschmoe', 'abc123', 'aol')
RIGHT_TACACSRC = {
aol = Credentials('jschmoe', 'abc123', 'aol')
AOL_TACACSRC = {
'aol_uname_': 'jschmoe',
'aol_pwd_': 'abc123',
}
RIGHT_PERMS = '0600'

MEDIUMPWCREDS = Credentials('MEDIUMPWCREDS', 'MEDIUMMEDIUMMEDIUMMEDIUMMEDIUMMEDIUMMEDIUMMEDIUMMEDIUMMEDIUMMEDIUMMEDIUM', 'MEDIUMPWCREDS')
MEDIUMPW_TACACSRC = {
'MEDIUMPWCREDS_uname_': 'MEDIUMPWCREDS',
'MEDIUMPWCREDS_pwd_': 'MEDIUMMEDIUMMEDIUMMEDIUMMEDIUMMEDIUMMEDIUMMEDIUMMEDIUMMEDIUMMEDIUMMEDIUM',
}

LONGPWCREDS = Credentials('LONGPWCREDS', 'LONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONG', 'LONGPWCREDS')
LONGPW_TACACSRC = {
'LONGPWCREDS_uname_': 'LONGPWCREDS',
'LONGPWCREDS_pwd_': 'LONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONGLONG',
}

EMPTYPWCREDS = Credentials('EMPTYPWCREDS', '', 'EMPTYPWCREDS')
EMPTYPW_TACACSRC = {
'EMPTYPWCREDS_uname_': 'EMPTYPWCREDS',
'EMPTYPWCREDS_pwd_': '',
}

LIST_OF_CREDS = ['aol', 'MEDIUMPWCREDS', 'LONGPWCREDS', ]
LIST_OF_TACACSRC = [ AOL_TACACSRC, MEDIUMPW_TACACSRC, LONGPW_TACACSRC ]
ALL_CREDS = [ (name,eval(name)) for name in LIST_OF_CREDS]
ALL_TACACSRC = dict()
[ALL_TACACSRC.update(x) for x in LIST_OF_TACACSRC]

def miniparser(data, tcrc):
"""Manually parse .tacacsrc lines into a dict"""
Expand All @@ -43,8 +67,9 @@ class TacacsrcTest(unittest.TestCase):
def testRead(self):
"""Test reading .tacacsrc."""
t = Testing_Tacacsrc()
self.assertEqual(t.version, '2.0')
self.assertEqual(t.creds['aol'], RIGHT_CREDS)
for name,value in ALL_CREDS:
self.assertEqual(t.version, '2.0')
self.assertEqual(t.creds['%s' % name], value)

def _get_perms(self, filename):
"""Get octal permissions for a filename"""
Expand All @@ -55,15 +80,19 @@ def testWrite(self):
"""Test writing .tacacsrc."""
_, file_name = tempfile.mkstemp('_tacacsrc')
t = Testing_Tacacsrc(generate_new=False)
t.creds['aol'] = RIGHT_CREDS
# Overload the default file_name w/ our temp file
t.file_name = file_name
t.write()

for name,value in ALL_CREDS:
t.creds['%s' % name] = value
# Overload the default file_name w/ our temp file or
# create a new tacacsrc by setting file_name to 'tests/data/tacacsrc'
t.file_name = file_name
t.write()

# Read the file we wrote back in and check it against what we think it
# should look like.
self.maxDiff = None
output = miniparser(t._read_file_old(), t)
self.assertEqual(output, RIGHT_TACACSRC)
self.assertEqual(output, ALL_TACACSRC)

# And then compare it against the manually parsed value using
# miniparser()
Expand All @@ -72,6 +101,15 @@ def testWrite(self):
self.assertEqual(output, miniparser(lines, t))
os.remove(file_name)

def test_brokenpw(self):
self.assertRaises(ValueError, Testing_Tacacsrc, tacacsrc_file='tests/data/brokenpw_tacacsrc')

def test_emptypw(self):
devnull = open(os.devnull, 'w')
with patch('trigger.tacacsrc.prompt_credentials', side_effect=KeyError):
with patch('sys.stdout', devnull):
self.assertRaises(KeyError, Testing_Tacacsrc, tacacsrc_file='tests/data/emptypw_tacacsrc')

def test_perms(self):
"""Test that permissions are being enforced."""
t = Testing_Tacacsrc()
Expand Down
2 changes: 1 addition & 1 deletion trigger/tacacsrc.py
Expand Up @@ -384,7 +384,7 @@ def _encrypt_old(self, s):

# We need to return a newline if a field is empty so as not to break
# .tacacsrc parsing (trust me, this is easier)
return encodestring(cryptobj.encrypt(s + padding)) or '\n'
return (encodestring(cryptobj.encrypt(s + padding)).replace('\n', '') or '' ) + '\n'

def _decrypt_old(self, s):
"""Decodes using the old method. Strips newline for you."""
Expand Down

0 comments on commit 36d91dc

Please sign in to comment.