Skip to content

Commit

Permalink
Merge pull request #34 from arista-eosplus/feature-user-sshkey
Browse files Browse the repository at this point in the history
Add sshkey support to users API
  • Loading branch information
devrobo committed Sep 8, 2015
2 parents 9da726e + cc75028 commit 46525df
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 24 deletions.
36 changes: 29 additions & 7 deletions pyeapi/api/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,18 @@ def isprivilege(value):


class Users(EntityCollection):
"""The Users class provides a configuration resource for local users
"""The Users class provides a configuration resource for local users.
The regex used here parses the running configuration to find username
entries. There is extra logic in the regular expression to store
the username as 'user' and then creates a backreference to find a
following configuration line that might contain the users sshkey.
"""

users_re = re.compile(r'username ([^\s]+) privilege (\d+)'
users_re = re.compile(r'username (?P<user>[^\s]+) privilege (\d+)'
r'(?: role ([^\s]+))?'
r'(?: (nopassword))?'
r'(?: secret (0|5|7|sha512) (.+))?', re.M)
r'(?: secret (0|5|7|sha512) (.+))?'
r'.*$\n(?:username (?P=user) sshkey (.+)$)?', re.M)

def get(self, name):
"""Returns the local user configuration as a resource dict
Expand Down Expand Up @@ -122,13 +127,14 @@ def _parse_username(self, config):
dict: A resource dict that is intended to be merged into the
user resource
"""
(username, priv, role, nopass, fmt, secret) = config
(username, priv, role, nopass, fmt, secret, sshkey) = config
resource = dict()
resource['privilege'] = priv
resource['role'] = role
resource['nopassword'] = nopass == 'nopassword'
resource['format'] = fmt
resource['secret'] = secret
resource['sshkey'] = sshkey
return {username: resource}

def create(self, name, nopassword=None, secret=None, encryption=None):
Expand Down Expand Up @@ -243,7 +249,7 @@ def set_privilege(self, name, value=None):
raise TypeError('priviledge value must be between 0 and 15')
cmd += ' privilege %s' % value
else:
cmd += ' no privilege'
cmd += ' privilege 1'
return self.configure(cmd)

def set_role(self, name, value=None):
Expand All @@ -261,9 +267,26 @@ def set_role(self, name, value=None):
if value is not None:
cmd += ' role %s' % value
else:
cmd += ' no role'
cmd = 'default username %s role' % name
return self.configure(cmd)

def set_sshkey(self, name, value=None):
"""Configures the user sshkey
Args:
name (str): The name of the user to add the sshkey to
value (str): The value to configure for the sshkey.
Returns:
True if the operation was successful otherwise False
"""
cmd = 'username %s' % name
if value:
cmd += ' sshkey %s' % value
else:
cmd = 'no username %s sshkey' % name
return self.configure(cmd)

def instance(node):
"""Returns an instance of Users
Expand All @@ -277,4 +300,3 @@ def instance(node):
resource
"""
return Users(node)

84 changes: 77 additions & 7 deletions test/system/test_api_users.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,25 @@

from systestlib import DutSystemTest

TEST_SSH_KEY = ('ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKL1UtBALa4CvFUsHUipNym'
'A04qCXuAtTwNcMj84bTUzUI+q7mdzRCTLkllXeVxKuBnaTm2PW7W67K5CVpl0'
'EVCm6IY7FS7kc4nlnD/tFvTvShy/fzYQRAdM7ZfVtegW8sMSFJzBR/T/Y/sxI'
'16Y/dQb8fC3la9T25XOrzsFrQiKRZmJGwg8d+0RLxpfMg0s/9ATwQKp6tPoLE'
'4f3dKlAgSk5eENyVLA3RsypWADHpenHPcB7sa8D38e1TS+n+EUyAdb3Yov+5E'
'SAbgLIJLd52Xv+FyYi0c2L49ByBjcRrupp4zfXn4DNRnEG4K6GcmswHuMEGZv'
'5vjJ9OYaaaaaaa')

class TestApiUsers(DutSystemTest):

def test_get(self):
for dut in self.duts:
dut.config(['no username test', 'username test nopassword'])
dut.config(['no username test', 'username test nopassword',
'username test sshkey %s' % TEST_SSH_KEY])

result = dut.api('users').get('test')
values = dict(nopassword=True, privilege='1', secret='',
role='', format='')
role='', format='',
sshkey=TEST_SSH_KEY)

result = self.sort_dict_by_keys(result)
values = self.sort_dict_by_keys(values)
Expand Down Expand Up @@ -85,25 +95,85 @@ def test_default(self):
self.assertTrue(result)
self.assertNotIn('username test nopassword', api.config)

def set_privilege_with_value(self):
def test_set_privilege_with_value(self):
for dut in self.duts:
dut.config(['no username test', 'username test nopassword'])
api = dut.api('users')
self.assertIn('username test nopassword', api.config)
# EOS defaults to privilege 1
self.assertIn('username test privilege 1 nopassword', api.config)
result = api.set_privilege('test', 8)
self.assertTrue(result)
self.assertNotIn('username test privilege 8', api.config)
self.assertIn('username test privilege 8 nopassword', api.config)

def set_privilege_with_no_value(self):
def test_set_privilege_with_no_value(self):
for dut in self.duts:
dut.config(['no username test',
'username test privilege 8 nopassword'])
api = dut.api('users')
self.assertIn('username test privilege 8', api.config)
result = api.set_privilege('test')
self.assertTrue(result)
self.assertNotIn('username test privilege 1', api.config)
self.assertIn('username test privilege 1', api.config)

def test_set_role_with_value(self):
for dut in self.duts:
dut.config(['no username test', 'username test nopassword'])
api = dut.api('users')
self.assertIn('username test privilege 1 nopassword', api.config)
result = api.set_role('test', 'network-admin')
self.assertTrue(result)
self.assertIn('username test privilege 1 role network-admin nopassword', api.config)

def test_set_role_with_no_value(self):
for dut in self.duts:
dut.config(['no username test',
'username test role network-admin nopassword'])
api = dut.api('users')
self.assertIn('username test privilege 1 role network-admin nopassword', api.config)
result = api.set_role('test')
self.assertTrue(result)
self.assertNotIn('username test privilege 1 role network-admin nopassword', api.config)

def test_set_sshkey_with_value(self):
for dut in self.duts:
dut.config(['no username test', 'username test nopassword'])
api = dut.api('users')
self.assertIn('username test privilege 1 nopassword', api.config)
self.assertNotIn('username test sshkey', api.config)
result = api.set_sshkey('test', TEST_SSH_KEY)
self.assertTrue(result)
self.assertIn('username test sshkey %s' % TEST_SSH_KEY, api.config)

def test_set_sshkey_with_empty_string(self):
for dut in self.duts:
dut.config(['no username test', 'username test nopassword'])
api = dut.api('users')
self.assertIn('username test privilege 1 nopassword', api.config)
self.assertNotIn('username test sshkey', api.config)
result = api.set_sshkey('test', '')
self.assertTrue(result)
self.assertNotIn('username test sshkey %s' % TEST_SSH_KEY, api.config)

def test_set_sshkey_with_None(self):
for dut in self.duts:
dut.config(['no username test', 'username test nopassword'])
api = dut.api('users')
self.assertIn('username test privilege 1 nopassword', api.config)
self.assertNotIn('username test sshkey', api.config)
result = api.set_sshkey('test', None)
self.assertTrue(result)
self.assertNotIn('username test sshkey %s' % TEST_SSH_KEY, api.config)

def test_set_sshkey_with_no_value(self):
for dut in self.duts:
dut.config(['no username test',
'username test nopassword'])
api = dut.api('users')
self.assertIn('username test privilege 1 nopassword', api.config)
result = api.set_sshkey('test')
self.assertTrue(result)
self.assertNotIn('username test sshkey %s' % TEST_SSH_KEY,
api.config)

if __name__ == '__main__':
unittest.main()
13 changes: 3 additions & 10 deletions test/unit/test_api_users.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def test_isprivilege_returns_false(self):
self.assertFalse(result)

def test_get(self):
keys = ['nopassword', 'privilege', 'role', 'secret', 'format']
keys = ['nopassword', 'privilege', 'role', 'secret', 'format', 'sshkey']
result = self.instance.get('test')
self.assertEqual(sorted(keys), sorted(result.keys()))

Expand Down Expand Up @@ -104,7 +104,7 @@ def test_set_privilege(self):
self.eapi_positive_config_test(func, cmds)

def test_set_privilege_negate(self):
cmds = 'username test no privilege'
cmds = 'username test privilege 1'
func = function('set_privilege', 'test')
self.eapi_positive_config_test(func, cmds)

Expand All @@ -118,17 +118,10 @@ def test_set_role(self):
self.eapi_positive_config_test(func, cmds)

def test_set_role_negate(self):
cmds = 'username test no role'
cmds = 'default username test role'
func = function('set_role', 'test')
self.eapi_positive_config_test(func, cmds)







if __name__ == '__main__':
unittest.main()


0 comments on commit 46525df

Please sign in to comment.