Exemple #1
0
class SaltKeep(Keep):
    '''
    RAET protocol estate on road data persistence for a given estate
    road specific data

    road/
        keep/
            stackname/
                local/
                    estate.ext
                remote/
                    estate.name.ext
                    estate.name.ext
    '''
    LocalFields = [
        'name', 'uid', 'ha', 'iha', 'natted', 'fqdn', 'dyned', 'sid', 'puid',
        'aha', 'role', 'sighex', 'prihex'
    ]
    LocalDumpFields = [
        'name', 'uid', 'ha', 'iha', 'natted', 'fqdn', 'dyned', 'sid', 'puid',
        'aha', 'role'
    ]
    RemoteFields = [
        'name', 'uid', 'fuid', 'ha', 'iha', 'natted', 'fqdn', 'dyned', 'sid',
        'main', 'kind', 'joined', 'role', 'acceptance', 'verhex', 'pubhex'
    ]
    RemoteDumpFields = [
        'name', 'uid', 'fuid', 'ha', 'iha', 'natted', 'fqdn', 'dyned', 'sid',
        'main', 'kind', 'joined', 'role'
    ]
    Auto = raeting.AutoMode.never.value  #auto accept

    def __init__(self,
                 opts,
                 prefix='estate',
                 basedirpath='',
                 auto=None,
                 **kwa):
        '''
        Setup RoadKeep instance
        '''
        basedirpath = basedirpath or os.path.join(opts['cache_dir'], 'raet')
        super(SaltKeep, self).__init__(prefix=prefix,
                                       basedirpath=basedirpath,
                                       **kwa)
        self.auto = (auto if auto is not None else
                     (raeting.AutoMode.always.value if opts['open_mode'] else
                      (raeting.AutoMode.once.value if opts['auto_accept'] else
                       raeting.AutoMode.never.value)))
        self.saltRaetKey = RaetKey(opts)

    def clearAllDir(self):
        '''
        Clear all keep directories
        '''
        super(SaltKeep, self).clearAllDir()
        self.clearRoleDir()

    def clearRoleDir(self):
        '''
        Clear the Role directory
        '''
        self.saltRaetKey.delete_pki_dir()

    def loadLocalRoleData(self):
        '''
        Load and return the role data
        '''
        keydata = self.saltRaetKey.read_local()
        if not keydata:
            keydata = odict([('sign', None), ('priv', None)])
        data = odict([('sighex', keydata['sign']),
                      ('prihex', keydata['priv'])])
        return data

    def clearLocalRoleData(self):
        '''
        Clear the local file
        '''
        self.saltRaetKey.delete_local()

    def clearLocalRoleDir(self):
        '''
        Clear the Local Role directory
        '''
        self.saltRaetKey.delete_pki_dir()

    def loadLocalData(self):
        '''
        Load and Return the data from the local estate
        '''
        data = super(SaltKeep, self).loadLocalData()
        if not data:
            return None
        roleData = self.loadLocalRoleData(
        )  # if not present defaults None values
        data.update([('sighex', roleData.get('sighex')),
                     ('prihex', roleData.get('prihex'))])
        return data

    def loadRemoteData(self, name):
        '''
        Load and Return the data from the remote file
        '''
        data = super(SaltKeep, self).loadRemoteData(name)
        if not data:
            return None

        mid = data['role']
        for status in [acceptance.name for acceptance in Acceptance]:
            keydata = self.saltRaetKey.read_remote(mid, status)
            if keydata:
                break

        if not keydata:
            data.update([('acceptance', None), ('verhex', None),
                         ('pubhex', None)])
        else:
            data.update(acceptance=raeting.Acceptance[status].value,
                        verhex=keydata['verify'],
                        pubhex=keydata['pub'])

        return data

    def loadAllRemoteData(self):
        '''
        Load and Return the data from the all the remote estate files
        '''
        keeps = super(SaltKeep, self).loadAllRemoteData()
        for name, data in keeps.items():
            keeps[name].update([('acceptance', None), ('verhex', None),
                                ('pubhex', None)])

        for status, mids in self.saltRaetKey.list_keys().items():
            for mid in mids:
                keydata = self.saltRaetKey.read_remote(mid, status)
                if keydata:
                    for name, data in keeps.items():
                        if data['role'] == mid:
                            keeps[name].update([
                                ('acceptance',
                                 raeting.Acceptance[status].value),
                                ('verhex', keydata['verify']),
                                ('pubhex', keydata['pub'])
                            ])
        return keeps

    def clearRemoteRoleData(self, role):
        '''
        Clear data from the role data file
        '''
        self.saltRaetKey.delete_key(role)  #now delete role key file

    def clearAllRemoteRoleData(self):
        '''
        Remove all the role data files
        '''
        self.saltRaetKey.delete_all()

    def clearRemoteRoleDir(self):
        '''
        Clear the Remote Role directory
        '''
        self.saltRaetKey.delete_pki_dir()

    def dumpLocal(self, local):
        '''
        Dump local estate
        '''
        data = odict([
            ('name', local.name),
            ('uid', local.uid),
            ('ha', local.ha),
            ('iha', local.iha),
            ('natted', local.natted),
            ('fqdn', local.fqdn),
            ('dyned', local.dyned),
            ('sid', local.sid),
            ('puid', local.stack.puid),
            ('aha', local.stack.aha),
            ('role', local.role),
        ])
        if self.verifyLocalData(data, localFields=self.LocalDumpFields):
            self.dumpLocalData(data)

        self.saltRaetKey.write_local(local.priver.keyhex, local.signer.keyhex)

    def dumpRemote(self, remote):
        '''
        Dump remote estate
        '''
        data = odict([
            ('name', remote.name),
            ('uid', remote.uid),
            ('fuid', remote.fuid),
            ('ha', remote.ha),
            ('iha', remote.iha),
            ('natted', remote.natted),
            ('fqdn', remote.fqdn),
            ('dyned', remote.dyned),
            ('sid', remote.sid),
            ('main', remote.main),
            ('kind', remote.kind),
            ('joined', remote.joined),
            ('role', remote.role),
        ])
        if self.verifyRemoteData(data, remoteFields=self.RemoteDumpFields):
            self.dumpRemoteData(data, remote.name)

        if remote.pubber.keyhex and remote.verfer.keyhex:
            # kludge to persist the keys since no way to write
            self.saltRaetKey.status(remote.role, remote.pubber.keyhex,
                                    remote.verfer.keyhex)

    def statusRemote(self, remote, dump=True):
        '''
        Calls .statusRole on remote role and keys and updates remote.acceptance
        dump indicates if statusRole should update persisted values when
        appropriate.

        Returns status
        Where status is acceptance status of role and keys
        and has value from raeting.acceptances
        '''
        status = self.statusRole(role=remote.role,
                                 verhex=remote.verfer.keyhex,
                                 pubhex=remote.pubber.keyhex,
                                 dump=dump)

        remote.acceptance = status

        return status

    def statusRole(self, role, verhex, pubhex, dump=True):
        '''
        Returns status

        Where status is acceptance status of role and keys
        and has value from raeting.acceptances
        '''
        status = raeting.Acceptance[self.saltRaetKey.status(
            role, pubhex, verhex)].value

        return status

    def rejectRemote(self, remote):
        '''
        Set acceptance status to rejected
        '''
        mid = remote.role
        self.saltRaetKey.reject(match=mid, include_accepted=True)
        remote.acceptance = raeting.Acceptance.rejected.value

    def pendRemote(self, remote):
        '''
        Set acceptance status to pending
        '''
        pass

    def acceptRemote(self, remote):
        '''
        Set acceptance status to accepted
        '''
        mid = remote.role
        self.saltRaetKey.accept(match=mid, include_rejected=True)
        remote.acceptance = raeting.Acceptance.accepted.value
Exemple #2
0
class BasicTestCase(unittest.TestCase):
    """"""

    def setUp(self):
        self.store = storing.Store(stamp=0.0)
        self.timer = StoreTimer(store=self.store, duration=1.0)

        self.saltDirpath = tempfile.mkdtemp(prefix="salt", suffix="main", dir='/tmp')

        pkiDirpath = os.path.join(self.saltDirpath, 'pki')
        if not os.path.exists(pkiDirpath):
                os.makedirs(pkiDirpath)

        acceptedDirpath = os.path.join(pkiDirpath, 'accepted')
        if not os.path.exists(acceptedDirpath):
            os.makedirs(acceptedDirpath)

        pendingDirpath = os.path.join(pkiDirpath, 'pending')
        if not os.path.exists(pendingDirpath):
            os.makedirs(pendingDirpath)

        rejectedDirpath = os.path.join(pkiDirpath, 'rejected')
        if not os.path.exists(rejectedDirpath):
            os.makedirs(rejectedDirpath)

        self.localFilepath = os.path.join(pkiDirpath, 'local.key')
        if os.path.exists(self.localFilepath):
            mode = os.stat(self.localFilepath).st_mode
            os.chmod(self.localFilepath, mode | stat.S_IWUSR | stat.S_IWUSR)

        self.cacheDirpath = os.path.join(self.saltDirpath, 'cache')
        self.sockDirpath = os.path.join(self.saltDirpath, 'sock')

        self.opts = dict(
                        __role='master',
                        id='master',
                        pki_dir=pkiDirpath,
                        sock_dir=self.sockDirpath,
                        cachedir=self.cacheDirpath,
                        open_mode=False,
                        auto_accept=True,
                        transport='raet',
                        )

        self.mainKeeper = RaetKey(opts=self.opts)
        self.baseDirpath = tempfile.mkdtemp(prefix="salt",  suffix="base", dir='/tmp')

    def tearDown(self):
        if os.path.exists(self.saltDirpath):
            shutil.rmtree(self.saltDirpath)

    def createRoadData(self, name, base):
        '''
        Creates odict and populates with data to setup road stack
        {
            name: stack name local estate name
            dirpath: dirpath for keep files
            sighex: signing key
            verhex: verify key
            prihex: private key
            pubhex: public key
        }
        '''
        data = odict()
        data['name'] = name
        data['dirpath'] = os.path.join(base, 'road', 'keep', name)
        signer = nacling.Signer()
        data['sighex'] = signer.keyhex
        data['verhex'] = signer.verhex
        privateer = nacling.Privateer()
        data['prihex'] = privateer.keyhex
        data['pubhex'] = privateer.pubhex

        return data

    def testAutoAccept(self):
        '''
        Basic function of RaetKey in auto accept mode
        '''
        console.terse("{0}\n".format(self.testAutoAccept.__doc__))
        self.opts['auto_accept'] = True
        self.assertTrue(self.opts['auto_accept'])
        self.assertDictEqual(self.mainKeeper.all_keys(), {'accepted': [],
                                                            'local': [],
                                                            'rejected': [],
                                                            'pending': []})

        localkeys = self.mainKeeper.read_local()
        self.assertDictEqual(localkeys, {})

        main = self.createRoadData(name='main', base=self.baseDirpath)
        self.mainKeeper.write_local(main['prihex'], main['sighex'])
        localkeys = self.mainKeeper.read_local()
        self.assertDictEqual(localkeys, {'priv': main['prihex'],
                                     'sign': main['sighex']})
        allkeys = self.mainKeeper.all_keys()
        self.assertDictEqual(allkeys, {'accepted': [],
                                       'local': [self.localFilepath],
                                       'rejected': [],
                                       'pending': []})

        other1 = self.createRoadData(name='other1', base=self.baseDirpath)
        other2 = self.createRoadData(name='other2', base=self.baseDirpath)

        status = self.mainKeeper.status(other1['name'], other1['pubhex'], other1['verhex'])
        self.assertEqual(status, 'accepted')
        status = self.mainKeeper.status(other2['name'], other2['pubhex'], other2['verhex'])
        self.assertEqual(status, 'accepted')

        allkeys = self.mainKeeper.all_keys()
        self.assertDictEqual(allkeys, {'accepted': ['other1', 'other2'],
                                'local': [self.localFilepath],
                                'pending': [],
                                'rejected': []} )

        remotekeys = self.mainKeeper.read_remote(other1['name'])
        self.assertDictEqual(remotekeys, {   'minion_id': 'other1',
                                             'pub': other1['pubhex'],
                                             'verify': other1['verhex']} )

        remotekeys = self.mainKeeper.read_remote(other2['name'])
        self.assertDictEqual(remotekeys, {  'minion_id': 'other2',
                                            'pub': other2['pubhex'],
                                            'verify': other2['verhex']} )

        listkeys = self.mainKeeper.list_keys()
        self.assertDictEqual(listkeys, {'accepted': ['other1', 'other2'],
                                        'rejected': [],
                                        'pending': []})


        allremotekeys = self.mainKeeper.read_all_remote()
        self.assertDictEqual(allremotekeys, {'other1':
                                                 {'verify': other1['verhex'],
                                                  'minion_id': 'other1',
                                                  'acceptance': 'accepted',
                                                  'pub': other1['pubhex'],},
                                             'other2':
                                                 {'verify': other2['verhex'],
                                                  'minion_id': 'other2',
                                                  'acceptance': 'accepted',
                                                  'pub': other2['pubhex'],}
                                            })


    def testManualAccept(self):
        '''
        Basic function of RaetKey in non auto accept mode
        '''
        console.terse("{0}\n".format(self.testAutoAccept.__doc__))
        self.opts['auto_accept'] = False
        self.assertFalse(self.opts['auto_accept'])
        self.assertDictEqual(self.mainKeeper.all_keys(), {'accepted': [],
                                                            'local': [],
                                                            'rejected': [],
                                                            'pending': []})

        localkeys = self.mainKeeper.read_local()
        self.assertDictEqual(localkeys, {})

        main = self.createRoadData(name='main', base=self.baseDirpath)
        self.mainKeeper.write_local(main['prihex'], main['sighex'])
        localkeys = self.mainKeeper.read_local()
        self.assertDictEqual(localkeys, {'priv': main['prihex'],
                                     'sign': main['sighex']})
        allkeys = self.mainKeeper.all_keys()
        self.assertDictEqual(allkeys, {'accepted': [],
                                       'local': [self.localFilepath],
                                       'rejected': [],
                                       'pending': []})

        other1 = self.createRoadData(name='other1', base=self.baseDirpath)
        other2 = self.createRoadData(name='other2', base=self.baseDirpath)

        status = self.mainKeeper.status(other1['name'], other1['pubhex'], other1['verhex'])
        self.assertEqual(status, 'pending')
        status = self.mainKeeper.status(other2['name'], other2['pubhex'], other2['verhex'])
        self.assertEqual(status, 'pending')

        allkeys = self.mainKeeper.all_keys()
        self.assertDictEqual(allkeys, {'accepted': [],
                                'local': [self.localFilepath],
                                'pending': ['other1', 'other2'],
                                'rejected': []} )

        remotekeys = self.mainKeeper.read_remote(other1['name'])
        self.assertDictEqual(remotekeys, {})

        remotekeys = self.mainKeeper.read_remote(other2['name'])
        self.assertDictEqual(remotekeys, {})

        listkeys = self.mainKeeper.list_keys()
        self.assertDictEqual(listkeys, {'accepted': [],
                                        'rejected': [],
                                        'pending': ['other1', 'other2']})


        allremotekeys = self.mainKeeper.read_all_remote()
        self.assertDictEqual(allremotekeys, {'other1':
                                                 {'verify': other1['verhex'],
                                                  'minion_id': 'other1',
                                                  'acceptance': 'pending',
                                                  'pub': other1['pubhex'],},
                                             'other2':
                                                 {'verify': other2['verhex'],
                                                  'minion_id': 'other2',
                                                  'acceptance': 'pending',
                                                  'pub': other2['pubhex'],}
                                            })

        self.mainKeeper.accept_all()

        allkeys = self.mainKeeper.all_keys()
        self.assertDictEqual(allkeys, {'accepted': ['other1', 'other2'],
                                'local': [self.localFilepath],
                                'pending': [],
                                'rejected': []} )

        remotekeys = self.mainKeeper.read_remote(other1['name'])
        self.assertDictEqual(remotekeys, {   'minion_id': 'other1',
                                             'pub': other1['pubhex'],
                                             'verify': other1['verhex']} )

        remotekeys = self.mainKeeper.read_remote(other2['name'])
        self.assertDictEqual(remotekeys, {  'minion_id': 'other2',
                                            'pub': other2['pubhex'],
                                            'verify': other2['verhex']} )

        listkeys = self.mainKeeper.list_keys()
        self.assertDictEqual(listkeys, {'accepted': ['other1', 'other2'],
                                        'rejected': [],
                                        'pending': []})


        allremotekeys = self.mainKeeper.read_all_remote()
        self.assertDictEqual(allremotekeys, {'other1':
                                                 {'verify': other1['verhex'],
                                                  'minion_id': 'other1',
                                                  'acceptance': 'accepted',
                                                  'pub': other1['pubhex'],},
                                             'other2':
                                                 {'verify': other2['verhex'],
                                                  'minion_id': 'other2',
                                                  'acceptance': 'accepted',
                                                  'pub': other2['pubhex'],}
                                            })

    def testDelete(self):
        '''
        Basic function of RaetKey to delete key
        '''
        console.terse("{0}\n".format(self.testDelete.__doc__))
        self.opts['auto_accept'] = True
        self.assertTrue(self.opts['auto_accept'])
        self.assertDictEqual(self.mainKeeper.all_keys(), {'accepted': [],
                                                            'local': [],
                                                            'rejected': [],
                                                            'pending': []})

        localkeys = self.mainKeeper.read_local()
        self.assertDictEqual(localkeys, {})

        main = self.createRoadData(name='main', base=self.baseDirpath)
        self.mainKeeper.write_local(main['prihex'], main['sighex'])
        localkeys = self.mainKeeper.read_local()
        self.assertDictEqual(localkeys, {'priv': main['prihex'],
                                     'sign': main['sighex']})
        allkeys = self.mainKeeper.all_keys()
        self.assertDictEqual(allkeys, {'accepted': [],
                                       'local': [self.localFilepath],
                                       'rejected': [],
                                       'pending': []})

        other1 = self.createRoadData(name='other1', base=self.baseDirpath)
        other2 = self.createRoadData(name='other2', base=self.baseDirpath)

        status = self.mainKeeper.status(other1['name'], other1['pubhex'], other1['verhex'])
        self.assertEqual(status, 'accepted')
        status = self.mainKeeper.status(other2['name'], other2['pubhex'], other2['verhex'])
        self.assertEqual(status, 'accepted')

        allkeys = self.mainKeeper.all_keys()
        self.assertDictEqual(allkeys, {'accepted': ['other1', 'other2'],
                                'local': [self.localFilepath],
                                'pending': [],
                                'rejected': []} )

        remotekeys = self.mainKeeper.read_remote(other1['name'])
        self.assertDictEqual(remotekeys, {   'minion_id': 'other1',
                                             'pub': other1['pubhex'],
                                             'verify': other1['verhex']} )

        remotekeys = self.mainKeeper.read_remote(other2['name'])
        self.assertDictEqual(remotekeys, {  'minion_id': 'other2',
                                            'pub': other2['pubhex'],
                                            'verify': other2['verhex']} )

        listkeys = self.mainKeeper.list_keys()
        self.assertDictEqual(listkeys, {'accepted': ['other1', 'other2'],
                                        'rejected': [],
                                        'pending': []})


        allremotekeys = self.mainKeeper.read_all_remote()
        self.assertDictEqual(allremotekeys, {'other1':
                                                 {'verify': other1['verhex'],
                                                  'minion_id': 'other1',
                                                  'acceptance': 'accepted',
                                                  'pub': other1['pubhex']},
                                             'other2':
                                                 {'verify': other2['verhex'],
                                                  'minion_id': 'other2',
                                                  'acceptance': 'accepted',
                                                  'pub': other2['pubhex'],}
                                            })

        self.mainKeeper.delete_key(match=other1['name'])

        allkeys = self.mainKeeper.all_keys()
        self.assertDictEqual(allkeys, {'accepted': ['other2'],
                                'local': [self.localFilepath],
                                'pending': [],
                                'rejected': []} )

        remotekeys = self.mainKeeper.read_remote(other1['name'])
        self.assertDictEqual(remotekeys, {} )

        remotekeys = self.mainKeeper.read_remote(other2['name'])
        self.assertDictEqual(remotekeys, {  'minion_id': 'other2',
                                            'pub': other2['pubhex'],
                                            'verify': other2['verhex']} )

        listkeys = self.mainKeeper.list_keys()
        self.assertDictEqual(listkeys, {'accepted': [ 'other2'],
                                        'rejected': [],
                                        'pending': []})


        allremotekeys = self.mainKeeper.read_all_remote()
        self.assertDictEqual(allremotekeys, {
                                             'other2':
                                                 {'verify': other2['verhex'],
                                                  'minion_id': 'other2',
                                                  'acceptance': 'accepted',
                                                  'pub': other2['pubhex'],}
                                             })
Exemple #3
0
class SaltSafe(object):
    '''
    Interface between Salt Key management and RAET keep key management
    '''
    Auto = False  #auto accept
    LocalFields = ['sighex', 'prihex']
    RemoteFields = ['eid', 'name', 'acceptance', 'verhex', 'pubhex']

    def __init__(self, opts=None, **kwa):
        '''
        Setup SaltSafe instance
        '''
        if opts is None:
            opts = {}
        self.saltRaetKey = RaetKey(opts)

    def verifyLocalData(self, data):
        '''
        Returns True if the fields in .LocalFields match the fields in data
        '''
        return (set(self.LocalFields) == set(data.keys()))

    def dumpLocalData(self, data):
        '''
        Dump the key data from the local estate
        '''
        self.saltRaetKey.write_local(data['prihex'], data['sighex'])

    def loadLocalData(self):
        '''
        Load and Return the data from the local estate
        '''
        data = self.saltRaetKey.read_local()
        if not data:
            return None
        return (odict(sighex=data['sign'], prihex=data['priv']))

    def clearLocalData(self):
        '''
        Load and Return the data from the local estate
        '''
        pass

    def verifyRemoteData(self, data):
        '''
        Returns True if the fields in .RemoteFields match the fields in data
        '''
        return (set(self.RemoteFields) == set(data.keys()))

    def dumpRemoteData(self, data, uid):
        '''
        Dump the data from the remote estate given by uid
        '''
        self.saltRaetKey.status(data['name'], data['eid'], data['pubhex'],
                                data['verhex'])

    def loadAllRemoteData(self):
        '''
        Load and Return the data from the all the remote estate files
        '''
        data = odict()

        for status, mids in self.saltRaetKey.list_keys().items():
            for mid in mids:
                keydata = self.saltRaetKey.read_remote(mid, status)
                if keydata:
                    rdata = odict()
                    rdata['eid'] = keydata['device_id']
                    rdata['name'] = keydata['minion_id']
                    rdata['acceptance'] = raeting.ACCEPTANCES[status]
                    rdata['verhex'] = keydata['verify']
                    rdata['pubhex'] = keydata['pub']
                    data[rdata['eid']] = rdata

        return data

    def clearAllRemoteData(self):
        '''
        Remove all the remote estate files
        '''
        self.saltRaetKey.delete_all()

    def dumpLocal(self, local):
        '''
        Dump the key data from the local estate
        '''
        data = odict([
            ('sighex', local.signer.keyhex),
            ('prihex', local.priver.keyhex),
        ])
        if self.verifyLocalData(data):
            self.dumpLocalData(data)

    def dumpRemote(self, remote):
        '''
        Dump the data from the remote estate by calling status on it which
        will persist the data
        '''
        data = odict([
            ('eid', remote.eid),
            ('name', remote.name),
            ('acceptance', remote.acceptance),
            ('verhex', remote.verfer.keyhex),
            ('pubhex', remote.pubber.keyhex),
        ])
        if self.verifyRemoteData(data):
            self.dumpRemoteData(data, remote.uid)

    def loadRemote(self, remote):
        '''
        Load and Return the data from the remote estate file
        Override this in sub class to change uid
        '''
        status = 'accepted'

        mid = remote.name
        keydata = self.saltRaetKey.read_remote(mid, status)
        if not keydata:
            return None

        data = odict()
        data['eid'] = keydata['device_id']
        data['name'] = keydata['minion_id']
        data['acceptance'] = raeting.ACCEPTANCES[status]
        data['verhex'] = keydata['verify']
        data['pubhex'] = keydata['pub']

        return data

    def clearRemote(self, remote):
        '''
        Clear the remote estate file
        Override this in sub class to change uid
        '''
        mid = remote.eid
        self.saltRaetKey.delete_key(mid)

    def statusRemote(self, remote, verhex, pubhex, main=True):
        '''
        Evaluate acceptance status of remote estate per its keys
        persist key data differentially based on status
        '''
        status = raeting.ACCEPTANCES[self.saltRaetKey.status(
            remote.name, remote.eid, pubhex, verhex)]

        if status != raeting.acceptances.rejected:
            if (verhex and verhex != remote.verfer.keyhex):
                remote.verfer = nacling.Verifier(verhex)
            if (pubhex and pubhex != remote.pubber.keyhex):
                remote.pubber = nacling.Publican(pubhex)
            remote.acceptance = status

        return status

    def rejectRemote(self, remote):
        '''
        Set acceptance status to rejected
        '''
        remote.acceptance = raeting.acceptances.rejected
        mid = remote.name
        self.saltRaetKey.reject(match=mid, include_accepted=True)

    def pendRemote(self, remote):
        '''
        Set acceptance status to pending
        '''
        pass

    def acceptRemote(self, remote):
        '''
        Set acceptance status to accepted
        '''
        remote.acceptance = raeting.acceptances.accepted
        mid = remote.name
        self.saltRaetKey.accept(match=mid, include_rejected=True)
Exemple #4
0
class SaltKeep(Keep):
    '''
    RAET protocol estate on road data persistence for a given estate
    road specific data

    road/
        keep/
            stackname/
                local/
                    estate.ext
                remote/
                    estate.name.ext
                    estate.name.ext
    '''
    LocalFields = ['name', 'uid', 'ha', 'iha', 'natted', 'fqdn', 'dyned', 'sid',
                   'puid', 'aha', 'role', 'sighex','prihex']
    LocalDumpFields = ['name', 'uid', 'ha', 'iha', 'natted', 'fqdn', 'dyned', 'sid',
                       'puid', 'aha', 'role']
    RemoteFields = ['name', 'uid', 'fuid', 'ha', 'iha', 'natted', 'fqdn', 'dyned',
                    'sid', 'main', 'kind', 'joined',
                    'role', 'acceptance', 'verhex', 'pubhex']
    RemoteDumpFields = ['name', 'uid', 'fuid', 'ha', 'iha', 'natted', 'fqdn', 'dyned',
                         'sid', 'main', 'kind', 'joined', 'role']
    Auto = raeting.AutoMode.never.value #auto accept

    def __init__(self, opts, prefix='estate', basedirpath='',  auto=None, **kwa):
        '''
        Setup RoadKeep instance
        '''
        basedirpath = basedirpath or os.path.join(opts['cache_dir'], 'raet')
        super(SaltKeep, self).__init__(prefix=prefix, basedirpath=basedirpath, **kwa)
        self.auto = (auto if auto is not None else
                            (raeting.AutoMode.always.value if opts['open_mode'] else
                                (raeting.AutoMode.once.value if opts['auto_accept'] else
                                 raeting.AutoMode.never.value)))
        self.saltRaetKey = RaetKey(opts)

    def clearAllDir(self):
        '''
        Clear all keep directories
        '''
        super(SaltKeep, self).clearAllDir()
        self.clearRoleDir()

    def clearRoleDir(self):
        '''
        Clear the Role directory
        '''
        self.saltRaetKey.delete_pki_dir()

    def loadLocalRoleData(self):
        '''
        Load and return the role data
        '''
        keydata = self.saltRaetKey.read_local()
        if not keydata:
            keydata = odict([('sign', None), ('priv', None)])
        data = odict([('sighex', keydata['sign']),
                     ('prihex', keydata['priv'])])
        return data

    def clearLocalRoleData(self):
        '''
        Clear the local file
        '''
        self.saltRaetKey.delete_local()

    def clearLocalRoleDir(self):
        '''
        Clear the Local Role directory
        '''
        self.saltRaetKey.delete_pki_dir()

    def loadLocalData(self):
        '''
        Load and Return the data from the local estate
        '''
        data = super(SaltKeep, self).loadLocalData()
        if not data:
            return None
        roleData = self.loadLocalRoleData() # if not present defaults None values
        data.update([('sighex', roleData.get('sighex')),
                     ('prihex', roleData.get('prihex'))])
        return data

    def loadRemoteData(self, name):
        '''
        Load and Return the data from the remote file
        '''
        data = super(SaltKeep, self).loadRemoteData(name)
        if not data:
            return None

        mid = data['role']
        for status in [acceptance.name for acceptance in Acceptance]:
            keydata = self.saltRaetKey.read_remote(mid, status)
            if keydata:
                break

        if not keydata:
            data.update([('acceptance', None),
                         ('verhex', None),
                         ('pubhex', None)])
        else:
            data.update(acceptance=raeting.Acceptance[status].value,
                        verhex=keydata['verify'],
                        pubhex=keydata['pub'])

        return data

    def loadAllRemoteData(self):
        '''
        Load and Return the data from the all the remote estate files
        '''
        keeps = super(SaltKeep, self).loadAllRemoteData()
        for name, data in keeps.items():
            keeps[name].update([('acceptance', None),
                                ('verhex', None),
                                ('pubhex', None)])

        for status, mids in self.saltRaetKey.list_keys().items():
            for mid in mids:
                keydata = self.saltRaetKey.read_remote(mid, status)
                if keydata:
                    for name, data in keeps.items():
                        if data['role'] == mid:
                            keeps[name].update(
                                    [('acceptance', raeting.Acceptance[status].value),
                                     ('verhex', keydata['verify']),
                                     ('pubhex', keydata['pub'])])
        return keeps

    def clearRemoteRoleData(self, role):
        '''
        Clear data from the role data file
        '''
        self.saltRaetKey.delete_key(role) #now delete role key file

    def clearAllRemoteRoleData(self):
        '''
        Remove all the role data files
        '''
        self.saltRaetKey.delete_all()

    def clearRemoteRoleDir(self):
        '''
        Clear the Remote Role directory
        '''
        self.saltRaetKey.delete_pki_dir()

    def dumpLocal(self, local):
        '''
        Dump local estate
        '''
        data = odict([
                        ('name', local.name),
                        ('uid', local.uid),
                        ('ha', local.ha),
                        ('iha', local.iha),
                        ('natted', local.natted),
                        ('fqdn', local.fqdn),
                        ('dyned', local.dyned),
                        ('sid', local.sid),
                        ('puid', local.stack.puid),
                        ('aha', local.stack.aha),
                        ('role', local.role),
                    ])
        if self.verifyLocalData(data, localFields =self.LocalDumpFields):
            self.dumpLocalData(data)

        self.saltRaetKey.write_local(local.priver.keyhex, local.signer.keyhex)

    def dumpRemote(self, remote):
        '''
        Dump remote estate
        '''
        data = odict([
                        ('name', remote.name),
                        ('uid', remote.uid),
                        ('fuid', remote.fuid),
                        ('ha', remote.ha),
                        ('iha', remote.iha),
                        ('natted', remote.natted),
                        ('fqdn', remote.fqdn),
                        ('dyned', remote.dyned),
                        ('sid', remote.sid),
                        ('main', remote.main),
                        ('kind', remote.kind),
                        ('joined', remote.joined),
                        ('role', remote.role),
                    ])
        if self.verifyRemoteData(data, remoteFields=self.RemoteDumpFields):
            self.dumpRemoteData(data, remote.name)

        if remote.pubber.keyhex  and remote.verfer.keyhex:
            # kludge to persist the keys since no way to write
            self.saltRaetKey.status(remote.role,
                                remote.pubber.keyhex,
                                remote.verfer.keyhex)

    def statusRemote(self, remote, dump=True):
        '''
        Calls .statusRole on remote role and keys and updates remote.acceptance
        dump indicates if statusRole should update persisted values when
        appropriate.

        Returns status
        Where status is acceptance status of role and keys
        and has value from raeting.acceptances
        '''
        status = self.statusRole(role=remote.role,
                                 verhex=remote.verfer.keyhex,
                                 pubhex=remote.pubber.keyhex,
                                 dump=dump)

        remote.acceptance = status

        return status

    def statusRole(self, role, verhex, pubhex, dump=True):
        '''
        Returns status

        Where status is acceptance status of role and keys
        and has value from raeting.acceptances
        '''
        status = raeting.Acceptance[self.saltRaetKey.status(role,
                                                             pubhex,
                                                             verhex)].value

        return status

    def rejectRemote(self, remote):
        '''
        Set acceptance status to rejected
        '''
        mid = remote.role
        self.saltRaetKey.reject(match=mid, include_accepted=True)
        remote.acceptance = raeting.Acceptance.rejected.value

    def pendRemote(self, remote):
        '''
        Set acceptance status to pending
        '''
        pass

    def acceptRemote(self, remote):
        '''
        Set acceptance status to accepted
        '''
        mid = remote.role
        self.saltRaetKey.accept(match=mid, include_rejected=True)
        remote.acceptance = raeting.Acceptance.accepted.value
Exemple #5
0
class BasicTestCase(unittest.TestCase):
    """"""
    def setUp(self):
        self.store = storing.Store(stamp=0.0)
        self.timer = StoreTimer(store=self.store, duration=1.0)

        self.saltDirpath = tempfile.mkdtemp(prefix="salt",
                                            suffix="main",
                                            dir='/tmp')

        pkiDirpath = os.path.join(self.saltDirpath, 'pki')
        if not os.path.exists(pkiDirpath):
            os.makedirs(pkiDirpath)

        acceptedDirpath = os.path.join(pkiDirpath, 'accepted')
        if not os.path.exists(acceptedDirpath):
            os.makedirs(acceptedDirpath)

        pendingDirpath = os.path.join(pkiDirpath, 'pending')
        if not os.path.exists(pendingDirpath):
            os.makedirs(pendingDirpath)

        rejectedDirpath = os.path.join(pkiDirpath, 'rejected')
        if not os.path.exists(rejectedDirpath):
            os.makedirs(rejectedDirpath)

        self.localFilepath = os.path.join(pkiDirpath, 'local.key')
        if os.path.exists(self.localFilepath):
            mode = os.stat(self.localFilepath).st_mode
            os.chmod(self.localFilepath, mode | stat.S_IWUSR | stat.S_IWUSR)

        self.cacheDirpath = os.path.join(self.saltDirpath, 'cache')
        self.sockDirpath = os.path.join(self.saltDirpath, 'sock')

        self.opts = dict(
            __role='master',
            id='master',
            pki_dir=pkiDirpath,
            sock_dir=self.sockDirpath,
            cachedir=self.cacheDirpath,
            open_mode=False,
            auto_accept=True,
            transport='raet',
        )

        self.mainKeeper = RaetKey(opts=self.opts)
        self.baseDirpath = tempfile.mkdtemp(prefix="salt",
                                            suffix="base",
                                            dir='/tmp')

    def tearDown(self):
        if os.path.exists(self.saltDirpath):
            shutil.rmtree(self.saltDirpath)

    def createRoadData(self, name, base):
        '''
        Creates odict and populates with data to setup road stack
        {
            name: stack name local estate name
            dirpath: dirpath for keep files
            sighex: signing key
            verhex: verify key
            prihex: private key
            pubhex: public key
        }
        '''
        data = odict()
        data['name'] = name
        data['dirpath'] = os.path.join(base, 'road', 'keep', name)
        signer = nacling.Signer()
        data['sighex'] = signer.keyhex
        data['verhex'] = signer.verhex
        privateer = nacling.Privateer()
        data['prihex'] = privateer.keyhex
        data['pubhex'] = privateer.pubhex

        return data

    def testAutoAccept(self):
        '''
        Basic function of RaetKey in auto accept mode
        '''
        console.terse("{0}\n".format(self.testAutoAccept.__doc__))
        self.opts['auto_accept'] = True
        self.assertTrue(self.opts['auto_accept'])
        self.assertDictEqual(self.mainKeeper.all_keys(), {
            'accepted': [],
            'local': [],
            'rejected': [],
            'pending': []
        })

        localkeys = self.mainKeeper.read_local()
        self.assertDictEqual(localkeys, {})

        main = self.createRoadData(name='main', base=self.baseDirpath)
        self.mainKeeper.write_local(main['prihex'], main['sighex'])
        localkeys = self.mainKeeper.read_local()
        self.assertDictEqual(localkeys, {
            'priv': main['prihex'],
            'sign': main['sighex']
        })
        allkeys = self.mainKeeper.all_keys()
        self.assertDictEqual(
            allkeys, {
                'accepted': [],
                'local': [self.localFilepath],
                'rejected': [],
                'pending': []
            })

        other1 = self.createRoadData(name='other1', base=self.baseDirpath)
        other2 = self.createRoadData(name='other2', base=self.baseDirpath)

        status = self.mainKeeper.status(other1['name'], other1['pubhex'],
                                        other1['verhex'])
        self.assertEqual(status, 'accepted')
        status = self.mainKeeper.status(other2['name'], other2['pubhex'],
                                        other2['verhex'])
        self.assertEqual(status, 'accepted')

        allkeys = self.mainKeeper.all_keys()
        self.assertDictEqual(
            allkeys, {
                'accepted': ['other1', 'other2'],
                'local': [self.localFilepath],
                'pending': [],
                'rejected': []
            })

        remotekeys = self.mainKeeper.read_remote(other1['name'])
        self.assertDictEqual(
            remotekeys, {
                'minion_id': 'other1',
                'pub': other1['pubhex'],
                'verify': other1['verhex']
            })

        remotekeys = self.mainKeeper.read_remote(other2['name'])
        self.assertDictEqual(
            remotekeys, {
                'minion_id': 'other2',
                'pub': other2['pubhex'],
                'verify': other2['verhex']
            })

        listkeys = self.mainKeeper.list_keys()
        self.assertDictEqual(listkeys, {
            'accepted': ['other1', 'other2'],
            'rejected': [],
            'pending': []
        })

        allremotekeys = self.mainKeeper.read_all_remote()
        self.assertDictEqual(
            allremotekeys, {
                'other1': {
                    'verify': other1['verhex'],
                    'minion_id': 'other1',
                    'acceptance': 'accepted',
                    'pub': other1['pubhex'],
                },
                'other2': {
                    'verify': other2['verhex'],
                    'minion_id': 'other2',
                    'acceptance': 'accepted',
                    'pub': other2['pubhex'],
                }
            })

    def testManualAccept(self):
        '''
        Basic function of RaetKey in non auto accept mode
        '''
        console.terse("{0}\n".format(self.testAutoAccept.__doc__))
        self.opts['auto_accept'] = False
        self.assertFalse(self.opts['auto_accept'])
        self.assertDictEqual(self.mainKeeper.all_keys(), {
            'accepted': [],
            'local': [],
            'rejected': [],
            'pending': []
        })

        localkeys = self.mainKeeper.read_local()
        self.assertDictEqual(localkeys, {})

        main = self.createRoadData(name='main', base=self.baseDirpath)
        self.mainKeeper.write_local(main['prihex'], main['sighex'])
        localkeys = self.mainKeeper.read_local()
        self.assertDictEqual(localkeys, {
            'priv': main['prihex'],
            'sign': main['sighex']
        })
        allkeys = self.mainKeeper.all_keys()
        self.assertDictEqual(
            allkeys, {
                'accepted': [],
                'local': [self.localFilepath],
                'rejected': [],
                'pending': []
            })

        other1 = self.createRoadData(name='other1', base=self.baseDirpath)
        other2 = self.createRoadData(name='other2', base=self.baseDirpath)

        status = self.mainKeeper.status(other1['name'], other1['pubhex'],
                                        other1['verhex'])
        self.assertEqual(status, 'pending')
        status = self.mainKeeper.status(other2['name'], other2['pubhex'],
                                        other2['verhex'])
        self.assertEqual(status, 'pending')

        allkeys = self.mainKeeper.all_keys()
        self.assertDictEqual(
            allkeys, {
                'accepted': [],
                'local': [self.localFilepath],
                'pending': ['other1', 'other2'],
                'rejected': []
            })

        remotekeys = self.mainKeeper.read_remote(other1['name'])
        self.assertDictEqual(remotekeys, {})

        remotekeys = self.mainKeeper.read_remote(other2['name'])
        self.assertDictEqual(remotekeys, {})

        listkeys = self.mainKeeper.list_keys()
        self.assertDictEqual(listkeys, {
            'accepted': [],
            'rejected': [],
            'pending': ['other1', 'other2']
        })

        allremotekeys = self.mainKeeper.read_all_remote()
        self.assertDictEqual(
            allremotekeys, {
                'other1': {
                    'verify': other1['verhex'],
                    'minion_id': 'other1',
                    'acceptance': 'pending',
                    'pub': other1['pubhex'],
                },
                'other2': {
                    'verify': other2['verhex'],
                    'minion_id': 'other2',
                    'acceptance': 'pending',
                    'pub': other2['pubhex'],
                }
            })

        self.mainKeeper.accept_all()

        allkeys = self.mainKeeper.all_keys()
        self.assertDictEqual(
            allkeys, {
                'accepted': ['other1', 'other2'],
                'local': [self.localFilepath],
                'pending': [],
                'rejected': []
            })

        remotekeys = self.mainKeeper.read_remote(other1['name'])
        self.assertDictEqual(
            remotekeys, {
                'minion_id': 'other1',
                'pub': other1['pubhex'],
                'verify': other1['verhex']
            })

        remotekeys = self.mainKeeper.read_remote(other2['name'])
        self.assertDictEqual(
            remotekeys, {
                'minion_id': 'other2',
                'pub': other2['pubhex'],
                'verify': other2['verhex']
            })

        listkeys = self.mainKeeper.list_keys()
        self.assertDictEqual(listkeys, {
            'accepted': ['other1', 'other2'],
            'rejected': [],
            'pending': []
        })

        allremotekeys = self.mainKeeper.read_all_remote()
        self.assertDictEqual(
            allremotekeys, {
                'other1': {
                    'verify': other1['verhex'],
                    'minion_id': 'other1',
                    'acceptance': 'accepted',
                    'pub': other1['pubhex'],
                },
                'other2': {
                    'verify': other2['verhex'],
                    'minion_id': 'other2',
                    'acceptance': 'accepted',
                    'pub': other2['pubhex'],
                }
            })

    def testDelete(self):
        '''
        Basic function of RaetKey to delete key
        '''
        console.terse("{0}\n".format(self.testDelete.__doc__))
        self.opts['auto_accept'] = True
        self.assertTrue(self.opts['auto_accept'])
        self.assertDictEqual(self.mainKeeper.all_keys(), {
            'accepted': [],
            'local': [],
            'rejected': [],
            'pending': []
        })

        localkeys = self.mainKeeper.read_local()
        self.assertDictEqual(localkeys, {})

        main = self.createRoadData(name='main', base=self.baseDirpath)
        self.mainKeeper.write_local(main['prihex'], main['sighex'])
        localkeys = self.mainKeeper.read_local()
        self.assertDictEqual(localkeys, {
            'priv': main['prihex'],
            'sign': main['sighex']
        })
        allkeys = self.mainKeeper.all_keys()
        self.assertDictEqual(
            allkeys, {
                'accepted': [],
                'local': [self.localFilepath],
                'rejected': [],
                'pending': []
            })

        other1 = self.createRoadData(name='other1', base=self.baseDirpath)
        other2 = self.createRoadData(name='other2', base=self.baseDirpath)

        status = self.mainKeeper.status(other1['name'], other1['pubhex'],
                                        other1['verhex'])
        self.assertEqual(status, 'accepted')
        status = self.mainKeeper.status(other2['name'], other2['pubhex'],
                                        other2['verhex'])
        self.assertEqual(status, 'accepted')

        allkeys = self.mainKeeper.all_keys()
        self.assertDictEqual(
            allkeys, {
                'accepted': ['other1', 'other2'],
                'local': [self.localFilepath],
                'pending': [],
                'rejected': []
            })

        remotekeys = self.mainKeeper.read_remote(other1['name'])
        self.assertDictEqual(
            remotekeys, {
                'minion_id': 'other1',
                'pub': other1['pubhex'],
                'verify': other1['verhex']
            })

        remotekeys = self.mainKeeper.read_remote(other2['name'])
        self.assertDictEqual(
            remotekeys, {
                'minion_id': 'other2',
                'pub': other2['pubhex'],
                'verify': other2['verhex']
            })

        listkeys = self.mainKeeper.list_keys()
        self.assertDictEqual(listkeys, {
            'accepted': ['other1', 'other2'],
            'rejected': [],
            'pending': []
        })

        allremotekeys = self.mainKeeper.read_all_remote()
        self.assertDictEqual(
            allremotekeys, {
                'other1': {
                    'verify': other1['verhex'],
                    'minion_id': 'other1',
                    'acceptance': 'accepted',
                    'pub': other1['pubhex']
                },
                'other2': {
                    'verify': other2['verhex'],
                    'minion_id': 'other2',
                    'acceptance': 'accepted',
                    'pub': other2['pubhex'],
                }
            })

        self.mainKeeper.delete_key(match=other1['name'])

        allkeys = self.mainKeeper.all_keys()
        self.assertDictEqual(
            allkeys, {
                'accepted': ['other2'],
                'local': [self.localFilepath],
                'pending': [],
                'rejected': []
            })

        remotekeys = self.mainKeeper.read_remote(other1['name'])
        self.assertDictEqual(remotekeys, {})

        remotekeys = self.mainKeeper.read_remote(other2['name'])
        self.assertDictEqual(
            remotekeys, {
                'minion_id': 'other2',
                'pub': other2['pubhex'],
                'verify': other2['verhex']
            })

        listkeys = self.mainKeeper.list_keys()
        self.assertDictEqual(listkeys, {
            'accepted': ['other2'],
            'rejected': [],
            'pending': []
        })

        allremotekeys = self.mainKeeper.read_all_remote()
        self.assertDictEqual(
            allremotekeys, {
                'other2': {
                    'verify': other2['verhex'],
                    'minion_id': 'other2',
                    'acceptance': 'accepted',
                    'pub': other2['pubhex'],
                }
            })
Exemple #6
0
class SaltKeep(Keep):
    '''
    RAET protocol estate on road data persistence for a given estate
    road specific data

    road/
        keep/
            stackname/
                local/
                    estate.ext
                remote/
                    estate.name.ext
                    estate.name.ext
    '''
    LocalFields = [
        'uid', 'name', 'ha', 'main', 'sid', 'neid', 'sighex', 'prihex', 'auto',
        'role'
    ]
    LocalDumpFields = ['uid', 'name', 'ha', 'main', 'sid', 'neid', 'role']
    RemoteFields = [
        'uid', 'name', 'ha', 'sid', 'joined', 'acceptance', 'verhex', 'pubhex',
        'role'
    ]
    RemoteDumpFields = ['uid', 'name', 'ha', 'sid', 'joined', 'role']

    Auto = False  #auto accept

    def __init__(self,
                 opts,
                 prefix='estate',
                 basedirpath='',
                 auto=None,
                 **kwa):
        '''
        Setup RoadKeep instance
        '''
        basedirpath = basedirpath or os.path.join(opts['cache_dir'], 'raet')
        super(SaltKeep, self).__init__(prefix=prefix,
                                       basedirpath=basedirpath,
                                       **kwa)
        self.auto = auto if auto is not None else opts['auto_accept']
        self.saltRaetKey = RaetKey(opts)

    def loadLocalData(self):
        '''
        Load and Return the data from the local estate
        '''

        data = super(SaltKeep, self).loadLocalData()
        if not data:
            return None
        srkdata = self.saltRaetKey.read_local()
        if not srkdata:
            srkdata = dict(sign=None, priv=None)
        data.update(sighex=srkdata['sign'],
                    prihex=srkdata['priv'],
                    auto=self.auto)
        return data

    def loadRemoteData(self, name):
        '''
        Load and Return the data from the remote file
        '''
        data = super(SaltKeep, self).loadRemoteData(name)
        if not data:
            return None

        mid = data['role']
        statae = raeting.ACCEPTANCES.keys()
        for status in statae:
            keydata = self.saltRaetKey.read_remote(mid, status)
            if keydata:
                break

        if not keydata:
            return None

        data.update(acceptance=raeting.ACCEPTANCES[status],
                    verhex=keydata['verify'],
                    pubhex=keydata['pub'])

        return data

    def loadAllRemoteData(self):
        '''
        Load and Return the data from the all the remote estate files
        '''
        keeps = super(SaltKeep, self).loadAllRemoteData()

        for status, mids in self.saltRaetKey.list_keys().items():
            for mid in mids:
                keydata = self.saltRaetKey.read_remote(mid, status)
                if keydata:
                    for name, data in keeps.items():
                        if data['role'] == mid:
                            keeps[name].update(
                                acceptance=raeting.ACCEPTANCES[status],
                                verhex=keydata['verify'],
                                pubhex=keydata['pub'])
        return keeps

    def clearAllRemoteData(self):
        '''
        Remove all the remote estate files
        '''
        super(SaltKeep, self).clearAllRemoteData()
        self.saltRaetKey.delete_all()

    def dumpLocal(self, local):
        '''
        Dump local estate
        '''
        data = odict([
            ('uid', local.uid),
            ('name', local.name),
            ('ha', local.ha),
            ('main', local.main),
            ('sid', local.sid),
            ('neid', local.neid),
            ('role', local.role),
        ])
        if self.verifyLocalData(data, localFields=self.LocalDumpFields):
            self.dumpLocalData(data)

        self.saltRaetKey.write_local(local.priver.keyhex, local.signer.keyhex)

    def dumpRemote(self, remote):
        '''
        Dump remote estate
        '''
        data = odict([
            ('uid', remote.uid),
            ('name', remote.name),
            ('ha', remote.ha),
            ('sid', remote.sid),
            ('joined', remote.joined),
            ('role', remote.role),
        ])
        if self.verifyRemoteData(data, remoteFields=self.RemoteDumpFields):
            self.dumpRemoteData(data, remote.name)

        self.saltRaetKey.status(remote.role, remote.pubber.keyhex,
                                remote.verfer.keyhex)

    def replaceRemoteRole(self, remote, old):
        '''
        Replace the Salt RaetKey record at old role when remote.role has changed
        '''
        new = remote.role
        if new != old:
            #self.dumpRemote(remote)
            # manually fix up acceptance if not pending
            # will be pending by default unless autoaccept
            if remote.acceptance == raeting.acceptances.accepted:
                self.acceptRemote(remote)
            elif remote.acceptance == raeting.acceptances.rejected:
                self.rejectRemote(remote)

            self.saltRaetKey.delete_key(old)  #now delete old key file

    def statusRemote(self, remote, verhex, pubhex, main=True, dump=True):
        '''
        Evaluate acceptance status of remote estate per its keys
        persist key data differentially based on status
        '''
        status = raeting.ACCEPTANCES[self.saltRaetKey.status(
            remote.role, pubhex, verhex)]

        if status != raeting.acceptances.rejected:
            if (verhex and verhex != remote.verfer.keyhex):
                remote.verfer = nacling.Verifier(verhex)
            if (pubhex and pubhex != remote.pubber.keyhex):
                remote.pubber = nacling.Publican(pubhex)
            remote.acceptance = status

        return status

    def rejectRemote(self, remote):
        '''
        Set acceptance status to rejected
        '''
        mid = remote.role
        self.saltRaetKey.reject(match=mid, include_accepted=True)
        remote.acceptance = raeting.acceptances.rejected

    def pendRemote(self, remote):
        '''
        Set acceptance status to pending
        '''
        pass

    def acceptRemote(self, remote):
        '''
        Set acceptance status to accepted
        '''
        mid = remote.role
        self.saltRaetKey.accept(match=mid, include_rejected=True)
        remote.acceptance = raeting.acceptances.accepted
Exemple #7
0
class SaltSafe(object):
    '''
    RAET protocol estate safe (key) data persistence and status
    '''
    Auto = False #auto accept

    def __init__(self, opts=None, **kwa):
        '''
        Setup SaltSafe instance

        '''
        from salt.key import RaetKey

        if opts is None:
            opts = {}
        self.saltRaetKey = RaetKey(opts)

    def loadLocalData(self):
        '''
        Load and Return the data from the local estate
        '''
        data = self.saltRaetKey.read_local()
        if not data:
            return None
        return (odict(sighex=data['sign'], prihex=data['priv']))

    def clearLocalData(self):
        '''
        Load and Return the data from the local estate
        '''
        pass

    def loadAllRemoteData(self):
        '''
        Load and Return the data from the all the remote estate files
        '''
        data = odict()

        for status, mids in self.saltRaetKey.list_keys().items():
            for mid in mids:
                keydata = self.saltRaetKey.read_remote(mid, status)
                if keydata:
                    rdata = odict()
                    rdata['eid'] = keydata['device_id']
                    rdata['name'] = keydata['minion_id']
                    rdata['acceptance'] = raeting.ACCEPTANCES[status]
                    rdata['verhex'] = keydata['verify']
                    rdata['pubhex'] = keydata['pub']
                    data[rdata['eid']] = rdata

        return data

    def clearAllRemoteData(self):
        '''
        Remove all the remote estate files
        '''
        self.saltRaetKey.delete_all()

    def dumpLocalEstate(self, estate):
        '''
        Dump the key data from the local estate
        '''
        self.saltRaetKey.write_local(estate.priver.keyhex, estate.signer.keyhex)

    def dumpRemoteEstate(self, estate):
        '''
        Dump the data from the remote estate
        '''
        pass

    def dumpAllRemoteEstates(self, estates):
        '''
        Dump the data from all the remote estates
        '''
        for estate in estates:
            self.dumpRemoteEstate(estate)


    def loadRemoteEstate(self, estate, status='accepted'):
        '''
        Load and Return the data from the remote estate file
        Override this in sub class to change uid
        '''
        mid = estate.name
        keydata = self.saltRaetKey.read_remote(mid, status)
        if not keydata:
            return None

        data = odict()
        data['eid'] = keydata['device_id']
        data['name'] = keydata['minion_id']
        data['acceptance'] = raeting.ACCEPTANCES[status]
        data['verhex'] = keydata['verify']
        data['pubhex'] = keydata['pub']

        return data

    def clearRemoteEstate(self, estate):
        '''
        Clear the remote estate file
        Override this in sub class to change uid
        '''
        mid = estate.eid
        self.saltRaetKey.delete_key(mid)

    def statusRemoteEstate(self, estate, verhex, pubhex, main=True):
        '''
        Evaluate acceptance status of estate per its keys
        persist key data differentially based on status
        '''
        status = raeting.ACCEPTANCES[self.saltRaetKey.status(estate.name,
                                                             estate.eid,
                                                             pubhex,
                                                             verhex)]

        if status != raeting.acceptances.rejected:
            if (verhex and verhex != estate.verfer.keyhex):
                estate.verfer = nacling.Verifier(verhex)
            if (pubhex and pubhex != estate.pubber.keyhex):
                estate.pubber = nacling.Publican(pubhex)
        estate.acceptance = status
        return status

    def rejectRemoteEstate(self, estate):
        '''
        Set acceptance status to rejected
        '''
        estate.acceptance = raeting.acceptances.rejected
        mid = estate.name
        self.saltRaetKey.reject(match=mid, include_accepted=True)

    def acceptRemoteEstate(self, estate):
        '''
        Set acceptance status to accepted
        '''
        estate.acceptance = raeting.acceptances.accepted
        mid = estate.name
        self.saltRaetKey.accept(match=mid, include_rejected=True)
Exemple #8
0
class SaltSafe(object):
    '''
    Interface between Salt Key management and RAET keep key management
    '''
    Auto = False #auto accept
    LocalFields = ['sighex', 'prihex']
    RemoteFields = ['eid', 'name', 'acceptance', 'verhex', 'pubhex']

    def __init__(self, opts=None, **kwa):
        '''
        Setup SaltSafe instance
        '''
        if opts is None:
            opts = {}
        self.saltRaetKey = RaetKey(opts)

    def verifyLocalData(self, data):
        '''
        Returns True if the fields in .LocalFields match the fields in data
        '''
        return (set(self.LocalFields) == set(data.keys()))

    def dumpLocalData(self, data):
        '''
        Dump the key data from the local estate
        '''
        self.saltRaetKey.write_local(data['prihex'], data['sighex'])

    def loadLocalData(self):
        '''
        Load and Return the data from the local estate
        '''
        data = self.saltRaetKey.read_local()
        if not data:
            return None
        return (odict(sighex=data['sign'], prihex=data['priv']))

    def clearLocalData(self):
        '''
        Load and Return the data from the local estate
        '''
        pass

    def verifyRemoteData(self, data):
        '''
        Returns True if the fields in .RemoteFields match the fields in data
        '''
        return (set(self.RemoteFields) == set(data.keys()))

    def dumpRemoteData(self, data, uid):
        '''
        Dump the data from the remote estate given by uid
        '''
        self.saltRaetKey.status(data['name'],
                                data['eid'],
                                data['pubhex'],
                                data['verhex'])

    def loadAllRemoteData(self):
        '''
        Load and Return the data from the all the remote estate files
        '''
        data = odict()

        for status, mids in self.saltRaetKey.list_keys().items():
            for mid in mids:
                keydata = self.saltRaetKey.read_remote(mid, status)
                if keydata:
                    rdata = odict()
                    rdata['eid'] = keydata['device_id']
                    rdata['name'] = keydata['minion_id']
                    rdata['acceptance'] = raeting.ACCEPTANCES[status]
                    rdata['verhex'] = keydata['verify']
                    rdata['pubhex'] = keydata['pub']
                    data[rdata['eid']] = rdata

        return data

    def clearAllRemoteData(self):
        '''
        Remove all the remote estate files
        '''
        self.saltRaetKey.delete_all()

    def dumpLocal(self, local):
        '''
        Dump the key data from the local estate
        '''
        data = odict([
                        ('sighex', local.signer.keyhex),
                        ('prihex', local.priver.keyhex),
                    ])
        if self.verifyLocalData(data):
            self.dumpLocalData(data)

    def dumpRemote(self, remote):
        '''
        Dump the data from the remote estate by calling status on it which
        will persist the data
        '''
        data = odict([
                        ('eid', remote.eid),
                        ('name', remote.name),
                        ('acceptance', remote.acceptance),
                        ('verhex', remote.verfer.keyhex),
                        ('pubhex', remote.pubber.keyhex),
                    ])
        if self.verifyRemoteData(data):
            self.dumpRemoteData(data, remote.uid)

    def loadRemote(self, remote):
        '''
        Load and Return the data from the remote estate file
        Override this in sub class to change uid
        '''
        status='accepted'

        mid = remote.name
        keydata = self.saltRaetKey.read_remote(mid, status)
        if not keydata:
            return None

        data = odict()
        data['eid'] = keydata['device_id']
        data['name'] = keydata['minion_id']
        data['acceptance'] = raeting.ACCEPTANCES[status]
        data['verhex'] = keydata['verify']
        data['pubhex'] = keydata['pub']

        return data

    def clearRemote(self, remote):
        '''
        Clear the remote estate file
        Override this in sub class to change uid
        '''
        mid = remote.eid
        self.saltRaetKey.delete_key(mid)

    def statusRemote(self, remote, verhex, pubhex, main=True):
        '''
        Evaluate acceptance status of remote estate per its keys
        persist key data differentially based on status
        '''
        status = raeting.ACCEPTANCES[self.saltRaetKey.status(remote.name,
                                                             remote.eid,
                                                             pubhex,
                                                             verhex)]

        if status != raeting.acceptances.rejected:
            if (verhex and verhex != remote.verfer.keyhex):
                remote.verfer = nacling.Verifier(verhex)
            if (pubhex and pubhex != remote.pubber.keyhex):
                remote.pubber = nacling.Publican(pubhex)
        remote.acceptance = status
        return status

    def rejectRemote(self, remote):
        '''
        Set acceptance status to rejected
        '''
        remote.acceptance = raeting.acceptances.rejected
        mid = remote.name
        self.saltRaetKey.reject(match=mid, include_accepted=True)

    def pendRemote(self, remote):
        '''
        Set acceptance status to pending
        '''
        pass

    def acceptRemote(self, remote):
        '''
        Set acceptance status to accepted
        '''
        remote.acceptance = raeting.acceptances.accepted
        mid = remote.name
        self.saltRaetKey.accept(match=mid, include_rejected=True)
Exemple #9
0
class SaltKeep(Keep):
    '''
    RAET protocol estate on road data persistence for a given estate
    road specific data

    road/
        keep/
            stackname/
                local/
                    estate.ext
                remote/
                    estate.name.ext
                    estate.name.ext
    '''
    LocalFields = ['uid', 'name', 'ha', 'main', 'sid', 'neid', 'sighex', 'prihex', 'auto', 'role']
    LocalDumpFields = ['uid', 'name', 'ha', 'main', 'sid', 'neid', 'role']
    RemoteFields = ['uid', 'name', 'ha', 'sid', 'joined', 'acceptance', 'verhex', 'pubhex', 'role']
    RemoteDumpFields = ['uid', 'name', 'ha', 'sid', 'joined', 'role']

    Auto = False #auto accept

    def __init__(self, opts, prefix='estate', basedirpath='',  auto=None, **kwa):
        '''
        Setup RoadKeep instance
        '''
        basedirpath = basedirpath or os.path.join(opts['cache_dir'], 'raet')
        super(SaltKeep, self).__init__(prefix=prefix, basedirpath=basedirpath, **kwa)
        self.auto = auto if auto is not None else opts['auto_accept']
        self.saltRaetKey = RaetKey(opts)

    def loadLocalData(self):
        '''
        Load and Return the data from the local estate
        '''

        data = super(SaltKeep, self).loadLocalData()
        if not data:
            return None
        srkdata = self.saltRaetKey.read_local()
        if not srkdata:
            srkdata = dict(sign=None, priv=None)
        data.update(sighex=srkdata['sign'], prihex=srkdata['priv'], auto=self.auto)
        return data

    def loadRemoteData(self, name):
        '''
        Load and Return the data from the remote file
        '''
        data = super(SaltKeep, self).loadRemoteData(name)
        if not data:
            return None

        mid = data['role']
        statae = raeting.ACCEPTANCES.keys()
        for status in statae:
            keydata = self.saltRaetKey.read_remote(mid, status)
            if keydata:
                break

        if not keydata:
            return None

        data.update(acceptance=raeting.ACCEPTANCES[status],
                    verhex=keydata['verify'],
                    pubhex=keydata['pub'])

        return data

    def loadAllRemoteData(self):
        '''
        Load and Return the data from the all the remote estate files
        '''
        keeps = super(SaltKeep, self).loadAllRemoteData()

        for status, mids in self.saltRaetKey.list_keys().items():
            for mid in mids:
                keydata = self.saltRaetKey.read_remote(mid, status)
                if keydata:
                    for name, data in keeps.items():
                        if data['role'] == mid:
                            keeps[name].update(acceptance=raeting.ACCEPTANCES[status],
                                         verhex=keydata['verify'],
                                         pubhex=keydata['pub'])
        return keeps

    def clearAllRemoteData(self):
        '''
        Remove all the remote estate files
        '''
        super(SaltKeep, self).clearAllRemoteData()
        self.saltRaetKey.delete_all()

    def dumpLocal(self, local):
        '''
        Dump local estate
        '''
        data = odict([
                        ('uid', local.uid),
                        ('name', local.name),
                        ('ha', local.ha),
                        ('main', local.main),
                        ('sid', local.sid),
                        ('neid', local.neid),
                        ('role', local.role),
                    ])
        if self.verifyLocalData(data, localFields = self.LocalDumpFields):
            self.dumpLocalData(data)

        self.saltRaetKey.write_local(local.priver.keyhex, local.signer.keyhex)

    def dumpRemote(self, remote):
        '''
        Dump remote estate
        '''
        data = odict([
                        ('uid', remote.uid),
                        ('name', remote.name),
                        ('ha', remote.ha),
                        ('sid', remote.sid),
                        ('joined', remote.joined),
                        ('role', remote.role),
                    ])
        if self.verifyRemoteData(data, remoteFields=self.RemoteDumpFields):
            self.dumpRemoteData(data, remote.name)

        self.saltRaetKey.status(remote.role,
                                remote.pubber.keyhex,
                                remote.verfer.keyhex)


    def replaceRemoteRole(self, remote, old):
        '''
        Replace the Salt RaetKey record at old role when remote.role has changed
        '''
        new = remote.role
        if new != old:
            #self.dumpRemote(remote)
            # manually fix up acceptance if not pending
            # will be pending by default unless autoaccept
            if remote.acceptance == raeting.acceptances.accepted:
                self.acceptRemote(remote)
            elif remote.acceptance == raeting.acceptances.rejected:
                self.rejectRemote(remote)

            self.saltRaetKey.delete_key(old) #now delete old key file

    def statusRemote(self, remote, verhex, pubhex, main=True, dump=True):
        '''
        Evaluate acceptance status of remote estate per its keys
        persist key data differentially based on status
        '''
        status = raeting.ACCEPTANCES[self.saltRaetKey.status(remote.role,
                                                             pubhex,
                                                             verhex)]

        if status != raeting.acceptances.rejected:
            if (verhex and verhex != remote.verfer.keyhex):
                remote.verfer = nacling.Verifier(verhex)
            if (pubhex and pubhex != remote.pubber.keyhex):
                remote.pubber = nacling.Publican(pubhex)
            remote.acceptance = status

        return status

    def rejectRemote(self, remote):
        '''
        Set acceptance status to rejected
        '''
        mid = remote.role
        self.saltRaetKey.reject(match=mid, include_accepted=True)
        remote.acceptance = raeting.acceptances.rejected

    def pendRemote(self, remote):
        '''
        Set acceptance status to pending
        '''
        pass

    def acceptRemote(self, remote):
        '''
        Set acceptance status to accepted
        '''
        mid = remote.role
        self.saltRaetKey.accept(match=mid, include_rejected=True)
        remote.acceptance = raeting.acceptances.accepted