Exemple #1
0
    def fetch(self, princ, addresses):
        """fetch keytabs of the address from locker
        returns:
            list -- encoded keytab contents belonging to addresses
        """
        if not princ or not princ.startswith('host/'):
            raise keytabs2.KeytabLockerError(
                'princ "{}" not accepted'.format(princ))

        hostname = princ[len('host/'):princ.rfind('@')]
        if not self.zkclient.exists(z.path.server(hostname)):
            _LOGGER.error('Invalid server: %s', hostname)
            return {}

        try:
            for hostname in addresses:
                keytab_files = glob.glob(
                    os.path.join(self._kt_spool_dir,
                                 '*#{}@*'.format(hostname)))
                kts = {
                    os.path.basename(keytab_file):
                    keytabs2.read_keytab(keytab_file)
                    for keytab_file in keytab_files
                }
        except OSError as err:
            raise keytabs2.KeytabLockerError(err)

        return kts
Exemple #2
0
def validate_as_file(encoded_keytabs, basedir):
    """
    validate keytab by given encoded data

    return keytab files validated
    """
    temp_dir = tempfile.mkdtemp(dir=basedir)
    try:
        for encoded in encoded_keytabs:
            test_file = os.path.join(temp_dir, _NAME)
            keytabs2.write_keytab(
                test_file,
                encoded,
            )

            try:
                subproc.check_call(
                    ['kt_split', '--dir={}'.format(basedir), test_file])
            except subproc.CalledProcessError:
                raise keytabs2.KeytabLockerError(
                    'wrong keytab data: {}'.format(encoded))

        for kt_file in os.listdir(basedir):
            full_path = os.path.join(basedir, kt_file)
            # we ignore temp_dir in basedir
            if os.path.isdir(full_path):
                continue

            yield full_path

    finally:
        fs.rmtree_safe(temp_dir)
Exemple #3
0
 def _get(self, req):
     """get keytabs from appname
     """
     try:
         app_name = req['app']
     except KeyError:
         raise keytabs2.KeytabLockerError('No "app" in request')
     keytabs = locker.get(self.peer(), app_name)
     return _response(success=True, keytabs=keytabs)
Exemple #4
0
        def _query(self, req):
            """query keytabs from appname
            """
            try:
                app_name = req['app']
            except KeyError:
                raise keytabs2.KeytabLockerError('No "app" in request')

            locker.query(self.peer(), app_name)
            return _response(success=True)
Exemple #5
0
        def _put(self, req):
            """Store encoded keytab.
            """
            try:
                keytabs = req['keytabs']
            except KeyError:
                raise keytabs2.KeytabLockerError('No "keytabs" in request')

            _LOGGER.debug('put keytabs: %s', keytabs)
            receiver.add(self.peer(), keytabs)

            return _response(success=True)
Exemple #6
0
 def _get(self, req):
     """get keytabs from appname
     """
     if 'app' in req:
         app_name = req['app']
         kts = locker.get(self.peer(), app_name)
     elif 'addresses' in req:
         addresses = req['addresses']
         kts = locker.fetch(self.peer(), addresses)
     else:
         raise keytabs2.KeytabLockerError(
             '"app" or "addresses" must be in request')
     return _response(success=True, keytabs=kts)
Exemple #7
0
def _translate_vip(keytab):
    """Get ip address from hostname inside keytab string
    """
    match = _KEYTAB_RE_OBJ.match(keytab)
    if match:
        hostname = match.group(1)
    else:
        raise keytabs2.KeytabLockerError(
            'Keytab {} in wrong format'.format(keytab))

    _LOGGER.debug('Trying to get vip of %s', hostname)
    ipaddress = socket.gethostbyname(hostname)
    _LOGGER.info('keytab => vip: %s => %s', keytab, ipaddress)
    return ipaddress
Exemple #8
0
        def _sync(self, req):
            """sync proid keytab relationship
            """
            try:
                mapping = req['mapping']
            except KeyError:
                raise keytabs2.KeytabLockerError('No "mapping" in request')

            # we convert into a tuple list
            mapping = [(item[0], item[1]) for item in mapping]

            _LOGGER.debug('sync mapping: %r', mapping)
            receiver.sync(self.peer(), mapping)

            return _response(success=True)
Exemple #9
0
    def query(self, princ, app_name):
        """query if keytabs are valid in manifest
        returns:
            list -- keytab names required by app
        """
        vips = self._query_proid_vips(app_name)
        keytabs = self._get_app_keytabs(princ, app_name)

        for keytab in keytabs:
            vip = _translate_vip(keytab)

            if vip not in vips:
                raise keytabs2.KeytabLockerError(
                    '{} of keytab {} does not exist or of wrong proid'.format(
                        vip, keytab))
        return keytabs
Exemple #10
0
    def get(self, princ, app_name):
        """Get keytabs defined in manifest from locker.
        returns:
            list -- encoded keytab contents required by app
        """
        keytab_names = self.query(princ, app_name)

        try:
            keytabs = {
                keytab:
                keytabs2.read_keytab(os.path.join(self._kt_spool_dir, keytab))
                for keytab in keytab_names
            }
        except OSError as err:
            raise keytabs2.KeytabLockerError(err)

        return keytabs
Exemple #11
0
    def _get_app_keytabs(self, princ, appname):
        """Get keytabs required for the given app."""
        # TODO: the logic is duplicated with ticket locker
        # we need to refactor to implement generic locker in the future
        if not princ or not princ.startswith('host/'):
            raise keytabs2.KeytabLockerError(
                'princ "{}" not accepted'.format(princ))

        hostname = princ[len('host/'):princ.rfind('@')]

        if not self.zkclient.exists(z.path.placement(hostname, appname)):
            _LOGGER.error('App %s not scheduled on node %s', appname, hostname)
            return []

        try:
            appnode = z.path.scheduled(appname)
            app = zkutils.with_retry(zkutils.get, self.zkclient, appnode)

            return app.get('keytabs', [])
        except kazoo.client.NoNodeError:
            _LOGGER.info('App does not exist: %s', appname)
            return []
Exemple #12
0
    def _query_proid_vips(self, appname):
        """query proid vips relationship
        """
        proid = appname.split('.')[0]

        res = set()
        if not os.path.exists(self._database):
            _LOGGER.error('DB %s not exist', self._database)
            raise keytabs2.KeytabLockerError('DB not exist')

        conn = sqlite3.connect(self._database)
        cur = conn.cursor()
        try:
            query = 'SELECT vip FROM {} where proid = ?'.format(keytabs2.TABLE)
            store_virtuals = cur.execute(query, (proid, )).fetchall()
            res = {virtual[0] for virtual in store_virtuals}
        except sqlite3.OperationalError as err:
            # table may not exist yet, try sync in the next execution
            _LOGGER.warning('wait for keytab locker starting.')
        finally:
            conn.close()
        return res
Exemple #13
0
 def _check_principal_user(self, princ):
     """Validate keytab principal."""
     if not princ or princ.split('/')[0] != self._owner:
         raise keytabs2.KeytabLockerError('expect user {}, got: {}'.format(
             self._owner, princ))