def _deny_access_via_manager(self, gluster_mgr, context, share, access,
                                 share_server=None):
        """Deny access to a share that's using cert based auth.

        Remove the SSL CN (Common Name) that's allowed to access the server.
        """

        if access['access_type'] != ACCESS_TYPE_CERT:
            raise exception.InvalidShareAccess(_("Only 'cert' access type "
                                                 "allowed for access "
                                                 "removal."))

        ssl_allow_opt = gluster_mgr.get_vol_option(AUTH_SSL_ALLOW)
        ssl_allow = re.split('[ ,]', ssl_allow_opt)
        access_to = access['access_to']
        if access_to not in ssl_allow:
            LOG.warning(_LW("Access to %(share)s at %(export)s is already "
                            "denied for %(access_to)s. GlusterFS volume "
                            "options might have been changed externally."),
                        {'share': share['id'], 'export': gluster_mgr.qualified,
                         'access_to': access_to})
            return

        ssl_allow.remove(access_to)
        ssl_allow_opt = ','.join(ssl_allow)
        gluster_mgr.set_vol_option(AUTH_SSL_ALLOW, ssl_allow_opt)

        dynauth = gluster_mgr.get_vol_option(DYNAMIC_AUTH) or 'off'
        # TODO(csaba): boolean option processing shoud be done in common
        if dynauth.lower() not in ('on', '1', 'true', 'yes', 'enable'):
            common._restart_gluster_vol(gluster_mgr)
Exemple #2
0
    def _deny_access_via_manager(self, gluster_mgr, context, share, access,
                                 share_server=None):
        """Deny access to a share that's using cert based auth.

        Remove the SSL CN (Common Name) that's allowed to access the server.
        """

        if access['access_type'] != ACCESS_TYPE_CERT:
            raise exception.InvalidShareAccess(_("Only 'cert' access type "
                                                 "allowed for access "
                                                 "removal."))

        ssl_allow_opt = gluster_mgr.get_gluster_vol_option(AUTH_SSL_ALLOW)
        ssl_allow = re.split('[ ,]', ssl_allow_opt)
        access_to = access['access_to']
        if access_to not in ssl_allow:
            LOG.warn(_LW("Access to %(share)s at %(export)s is already "
                         "denied for %(access_to)s. GlusterFS volume "
                         "options might have been changed externally."),
                     {'share': share['id'], 'export': gluster_mgr.qualified,
                      'access_to': access_to})
            return

        ssl_allow.remove(access_to)
        ssl_allow_opt = ','.join(ssl_allow)
        try:
            gluster_mgr.gluster_call(
                'volume', 'set', gluster_mgr.volume,
                AUTH_SSL_ALLOW, ssl_allow_opt)
        except exception.ProcessExecutionError as exc:
            msg = (_("Error in gluster volume set during deny access. "
                     "Volume: %(volname)s, Option: %(option)s, "
                     "access_to: %(access_to)s, Error: %(error)s") %
                   {'volname': gluster_mgr.volume,
                    'option': AUTH_SSL_ALLOW, 'access_to': access_to,
                    'error': exc.stderr})
            LOG.error(msg)
            raise exception.GlusterfsException(msg)

        try:
            dynauth = gluster_mgr.get_gluster_vol_option(DYNAMIC_AUTH) or 'off'
        except exception.ProcessExecutionError as exc:
            if exc.exit_code == 1:
                # dynamic auth is not supported by gluster backend
                dynauth = 'off'
            else:
                # unexpected failure
                msg = (_("Error in querying gluster volume."
                         "Volume: %(volname)s, Option: %(option)s, "
                         "access_to: %(access_to)s, Error: %(error)s") %
                       {'volname': gluster_mgr.volume,
                        'option': AUTH_SSL_ALLOW, 'access_to': access_to,
                        'error': exc.stderr})
                LOG.error(msg)
                raise exception.GlusterfsException(msg)
        # TODO(csaba): boolean option processing shoud be done in common
        if dynauth.lower() not in ('on', '1', 'true', 'yes', 'enable'):
            common._restart_gluster_vol(gluster_mgr)
Exemple #3
0
    def test_restart_gluster_vol(self):
        gmgr = common.GlusterManager(fakeexport, self._execute, None, None)
        test_args = [('volume', 'stop', fakevol, '--mode=script'),
                     ('volume', 'start', fakevol)]

        common._restart_gluster_vol(gmgr)
        self.assertEqual([mock.call(*test_args[0]),
                          mock.call(*test_args[1])],
                         gmgr.gluster_call.call_args_list)
Exemple #4
0
    def test_restart_gluster_vol(self):
        gmgr = common.GlusterManager(fakeexport, self._execute, None, None)
        test_args = [('volume', 'stop', fakevol, '--mode=script'),
                     ('volume', 'start', fakevol)]

        common._restart_gluster_vol(gmgr)
        self.assertEqual(
            [mock.call(*test_args[0]), mock.call(*test_args[1])],
            gmgr.gluster_call.call_args_list)
Exemple #5
0
    def test_restart_gluster_vol(self):
        gmgr = common.GlusterManager(fakeexport, self._execute, None, None)
        test_args = [(('volume', 'stop', fakevol, '--mode=script'),
                      {'log': mock.ANY}),
                     (('volume', 'start', fakevol), {'log': mock.ANY})]

        common._restart_gluster_vol(gmgr)
        self.assertEqual(
            [mock.call(*arg[0], **arg[1]) for arg in test_args],
            gmgr.gluster_call.call_args_list)
    def test_restart_gluster_vol(self):
        gmgr = common.GlusterManager(fakeexport, self._execute, None, None)
        test_args = [(('volume', 'stop', fakevol, '--mode=script'),
                      {'log': mock.ANY}),
                     (('volume', 'start', fakevol), {'log': mock.ANY})]

        common._restart_gluster_vol(gmgr)
        self.assertEqual(
            [mock.call(*arg[0], **arg[1]) for arg in test_args],
            gmgr.gluster_call.call_args_list)
    def _deny_access_via_manager(self, gluster_mgr, context, share, access, share_server=None):
        """Deny access to a share that's using cert based auth.

        Remove the SSL CN (Common Name) that's allowed to access the server.
        """

        if access["access_type"] != ACCESS_TYPE_CERT:
            raise exception.InvalidShareAccess(_("Only 'cert' access type " "allowed for access " "removal."))

        ssl_allow_opt = gluster_mgr.get_gluster_vol_option(AUTH_SSL_ALLOW)
        ssl_allow = re.split("[ ,]", ssl_allow_opt)
        access_to = access["access_to"]
        if access_to not in ssl_allow:
            LOG.warn(
                _LW(
                    "Access to %(share)s at %(export)s is already "
                    "denied for %(access_to)s. GlusterFS volume "
                    "options might have been changed externally."
                ),
                {"share": share["id"], "export": gluster_mgr.qualified, "access_to": access_to},
            )
            return

        ssl_allow.remove(access_to)
        ssl_allow_opt = ",".join(ssl_allow)
        try:
            gluster_mgr.gluster_call("volume", "set", gluster_mgr.volume, AUTH_SSL_ALLOW, ssl_allow_opt)
        except exception.ProcessExecutionError as exc:
            msg = _(
                "Error in gluster volume set during deny access. "
                "Volume: %(volname)s, Option: %(option)s, "
                "access_to: %(access_to)s, Error: %(error)s"
            ) % {"volname": gluster_mgr.volume, "option": AUTH_SSL_ALLOW, "access_to": access_to, "error": exc.stderr}
            LOG.error(msg)
            raise exception.GlusterfsException(msg)

        try:
            dynauth = gluster_mgr.get_gluster_vol_option(DYNAMIC_AUTH) or "off"
        except exception.ProcessExecutionError as exc:
            msg = _(
                "Error in querying gluster volume. " "Volume: %(volname)s, Option: %(option)s, " "Error: %(error)s"
            ) % {"volname": gluster_mgr.volume, "option": DYNAMIC_AUTH, "error": exc.stderr}
            LOG.error(msg)
            raise exception.GlusterfsException(msg)
        # TODO(csaba): boolean option processing shoud be done in common
        if dynauth.lower() not in ("on", "1", "true", "yes", "enable"):
            common._restart_gluster_vol(gluster_mgr)
Exemple #8
0
    def _deny_access_via_manager(self,
                                 gluster_mgr,
                                 context,
                                 share,
                                 access,
                                 share_server=None):
        """Deny access to a share that's using cert based auth.

        Remove the SSL CN (Common Name) that's allowed to access the server.
        """

        if access['access_type'] != ACCESS_TYPE_CERT:
            raise exception.InvalidShareAccess(
                _("Only 'cert' access type "
                  "allowed for access "
                  "removal."))

        ssl_allow_opt = gluster_mgr.get_gluster_vol_option(AUTH_SSL_ALLOW)
        ssl_allow = re.split('[ ,]', ssl_allow_opt)
        access_to = access['access_to']
        if access_to not in ssl_allow:
            LOG.warning(
                _LW("Access to %(share)s at %(export)s is already "
                    "denied for %(access_to)s. GlusterFS volume "
                    "options might have been changed externally."), {
                        'share': share['id'],
                        'export': gluster_mgr.qualified,
                        'access_to': access_to
                    })
            return

        ssl_allow.remove(access_to)
        ssl_allow_opt = ','.join(ssl_allow)
        gluster_mgr.gluster_call(
            'volume',
            'set',
            gluster_mgr.volume,
            AUTH_SSL_ALLOW,
            ssl_allow_opt,
            log=_LE("Tuning GlusterFS volume in deny-access"))

        dynauth = gluster_mgr.get_gluster_vol_option(DYNAMIC_AUTH) or 'off'
        # TODO(csaba): boolean option processing shoud be done in common
        if dynauth.lower() not in ('on', '1', 'true', 'yes', 'enable'):
            common._restart_gluster_vol(gluster_mgr)
Exemple #9
0
    def _allow_access_via_manager(self, gluster_mgr, context, share, access,
                                  share_server=None):
        """Allow access to a share using certs.

        Add the SSL CN (Common Name) that's allowed to access the server.
        """

        if access['access_type'] != ACCESS_TYPE_CERT:
            raise exception.InvalidShareAccess(_("Only 'cert' access type "
                                                 "allowed"))

        ssl_allow_opt = gluster_mgr.get_gluster_vol_option(AUTH_SSL_ALLOW)
        # wrt. GlusterFS' parsing of auth.ssl-allow, please see code from
        # https://github.com/gluster/glusterfs/blob/v3.6.2/
        # xlators/protocol/auth/login/src/login.c#L80
        # until end of gf_auth() function
        ssl_allow = re.split('[ ,]', ssl_allow_opt)
        access_to = access['access_to']
        if access_to in ssl_allow:
            LOG.warn(_LW("Access to %(share)s at %(export)s is already "
                         "granted for %(access_to)s. GlusterFS volume "
                         "options might have been changed externally."),
                     {'share': share['id'], 'export': gluster_mgr.qualified,
                      'access_to': access_to})
            return

        ssl_allow.append(access_to)
        ssl_allow_opt = ','.join(ssl_allow)
        try:
            gluster_mgr.gluster_call(
                'volume', 'set', gluster_mgr.volume,
                AUTH_SSL_ALLOW, ssl_allow_opt)
        except exception.ProcessExecutionError as exc:
            msg = (_("Error in gluster volume set during allow access. "
                     "Volume: %(volname)s, Option: %(option)s, "
                     "access_to: %(access_to)s, Error: %(error)s") %
                   {'volname': gluster_mgr.volume,
                    'option': AUTH_SSL_ALLOW, 'access_to': access_to,
                    'error': exc.stderr})
            LOG.error(msg)
            raise exception.GlusterfsException(msg)

        # TODO(deepakcs) Remove this once ssl options can be
        # set dynamically.
        common._restart_gluster_vol(gluster_mgr)
Exemple #10
0
    def _update_access_via_manager(self,
                                   gluster_mgr,
                                   context,
                                   share,
                                   add_rules,
                                   delete_rules,
                                   recovery=False,
                                   share_server=None):
        """Update access rules, authorize SSL CNs (Common Names)."""

        # Fetch existing authorized CNs, the value of Gluster option
        # 'auth.ssl-allow' that is available as a comma seperated string.
        # wrt. GlusterFS' parsing of auth.ssl-allow, please see code from
        # https://github.com/gluster/glusterfs/blob/v3.6.2/
        # xlators/protocol/auth/login/src/login.c#L80
        # until end of gf_auth() function
        ssl_allow_opt = gluster_mgr.get_vol_option(AUTH_SSL_ALLOW)

        existing_rules_set = set(re.split('[ ,]', ssl_allow_opt))
        add_rules_set = {rule['access_to'] for rule in add_rules}
        for rule in add_rules_set:
            if re.search('[ ,]', rule):
                raise exception.GlusterfsException(
                    _("Invalid 'access_to' '%s': common names used for "
                      "GlusterFS authentication should not contain comma "
                      "or whitespace.") % rule)
        delete_rules_set = {rule['access_to'] for rule in delete_rules}
        new_rules_set = ((existing_rules_set | add_rules_set) -
                         delete_rules_set)

        # Addition or removal of CNs in the authorized list through the
        # Gluster CLI, used by 'GlusterManager' objects, can only be done by
        # replacing the existing list with the newly modified list.
        ssl_allow_opt = ','.join(sorted(new_rules_set))
        gluster_mgr.set_vol_option(AUTH_SSL_ALLOW, ssl_allow_opt)

        # When the Gluster option, DYNAMIC_AUTH is not enabled for the gluster
        # volume/manila share, the removal of CN of a client does not affect
        # the client's existing connection to the volume until the volume is
        # restarted.
        if delete_rules:
            dynauth = gluster_mgr.get_vol_option(DYNAMIC_AUTH, boolean=True)
            if not dynauth:
                common._restart_gluster_vol(gluster_mgr)
Exemple #11
0
    def _deny_access_via_manager(self, gluster_mgr, context, share, access,
                                 share_server=None):
        """Deny access to a share that's using cert based auth.

        Remove the SSL CN (Common Name) that's allowed to access the server.
        """

        if access['access_type'] != ACCESS_TYPE_CERT:
            raise exception.InvalidShareAccess(_("Only 'cert' access type "
                                                 "allowed for access "
                                                 "removal."))

        ssl_allow_opt = gluster_mgr.get_gluster_vol_option(AUTH_SSL_ALLOW)
        ssl_allow = re.split('[ ,]', ssl_allow_opt)
        access_to = access['access_to']
        if access_to not in ssl_allow:
            LOG.warn(_LW("Access to %(share)s at %(export)s is already "
                         "denied for %(access_to)s. GlusterFS volume "
                         "options might have been changed externally."),
                     {'share': share['id'], 'export': gluster_mgr.qualified,
                      'access_to': access_to})
            return

        ssl_allow.remove(access_to)
        ssl_allow_opt = ','.join(ssl_allow)
        try:
            gluster_mgr.gluster_call(
                'volume', 'set', gluster_mgr.volume,
                AUTH_SSL_ALLOW, ssl_allow_opt)
        except exception.ProcessExecutionError as exc:
            msg = (_("Error in gluster volume set during deny access. "
                     "Volume: %(volname)s, Option: %(option)s, "
                     "access_to: %(access_to)s, Error: %(error)s") %
                   {'volname': gluster_mgr.volume,
                    'option': AUTH_SSL_ALLOW, 'access_to': access_to,
                    'error': exc.stderr})
            LOG.error(msg)
            raise exception.GlusterfsException(msg)

        # TODO(deepakcs) Remove this once ssl options can be
        # set dynamically.
        common._restart_gluster_vol(gluster_mgr)
Exemple #12
0
    def _update_access_via_manager(self, gluster_mgr, context, share,
                                   add_rules, delete_rules,
                                   recovery=False, share_server=None):
        """Update access rules, authorize SSL CNs (Common Names)."""

        # Fetch existing authorized CNs, the value of Gluster option
        # 'auth.ssl-allow' that is available as a comma seperated string.
        # wrt. GlusterFS' parsing of auth.ssl-allow, please see code from
        # https://github.com/gluster/glusterfs/blob/v3.6.2/
        # xlators/protocol/auth/login/src/login.c#L80
        # until end of gf_auth() function
        ssl_allow_opt = gluster_mgr.get_vol_option(AUTH_SSL_ALLOW)

        existing_rules_set = set(re.split('[ ,]', ssl_allow_opt))
        add_rules_set = {rule['access_to'] for rule in add_rules}
        for rule in add_rules_set:
            if re.search('[ ,]', rule):
                raise exception.GlusterfsException(
                    _("Invalid 'access_to' '%s': common names used for "
                      "GlusterFS authentication should not contain comma "
                      "or whitespace.") % rule)
        delete_rules_set = {rule['access_to'] for rule in delete_rules}
        new_rules_set = (
            (existing_rules_set | add_rules_set) - delete_rules_set)

        # Addition or removal of CNs in the authorized list through the
        # Gluster CLI, used by 'GlusterManager' objects, can only be done by
        # replacing the existing list with the newly modified list.
        ssl_allow_opt = ','.join(sorted(new_rules_set))
        gluster_mgr.set_vol_option(AUTH_SSL_ALLOW, ssl_allow_opt)

        # When the Gluster option, DYNAMIC_AUTH is not enabled for the gluster
        # volume/manila share, the removal of CN of a client does not affect
        # the client's existing connection to the volume until the volume is
        # restarted.
        if delete_rules:
            dynauth = gluster_mgr.get_vol_option(DYNAMIC_AUTH, boolean=True)
            if not dynauth:
                common._restart_gluster_vol(gluster_mgr)
    def _deny_access_via_manager(self, gluster_mgr, context, share, access, share_server=None):
        """Deny access to a share that's using cert based auth.

        Remove the SSL CN (Common Name) that's allowed to access the server.
        """

        if access["access_type"] != ACCESS_TYPE_CERT:
            raise exception.InvalidShareAccess(_("Only 'cert' access type " "allowed for access " "removal."))

        ssl_allow_opt = gluster_mgr.get_gluster_vol_option(AUTH_SSL_ALLOW)
        ssl_allow = re.split("[ ,]", ssl_allow_opt)
        access_to = access["access_to"]
        if access_to not in ssl_allow:
            LOG.warning(
                _LW(
                    "Access to %(share)s at %(export)s is already "
                    "denied for %(access_to)s. GlusterFS volume "
                    "options might have been changed externally."
                ),
                {"share": share["id"], "export": gluster_mgr.qualified, "access_to": access_to},
            )
            return

        ssl_allow.remove(access_to)
        ssl_allow_opt = ",".join(ssl_allow)
        gluster_mgr.gluster_call(
            "volume",
            "set",
            gluster_mgr.volume,
            AUTH_SSL_ALLOW,
            ssl_allow_opt,
            log=_LE("Tuning GlusterFS volume in deny-access"),
        )

        dynauth = gluster_mgr.get_gluster_vol_option(DYNAMIC_AUTH) or "off"
        # TODO(csaba): boolean option processing shoud be done in common
        if dynauth.lower() not in ("on", "1", "true", "yes", "enable"):
            common._restart_gluster_vol(gluster_mgr)
Exemple #14
0
    def _deny_access_via_manager(self,
                                 gluster_mgr,
                                 context,
                                 share,
                                 access,
                                 share_server=None):
        """Deny access to a share that's using cert based auth.

        Remove the SSL CN (Common Name) that's allowed to access the server.
        """

        if access['access_type'] != ACCESS_TYPE_CERT:
            raise exception.InvalidShareAccess(
                _("Only 'cert' access type "
                  "allowed for access "
                  "removal."))

        ssl_allow_opt = gluster_mgr.get_vol_option(AUTH_SSL_ALLOW)
        ssl_allow = re.split('[ ,]', ssl_allow_opt)
        access_to = access['access_to']
        if access_to not in ssl_allow:
            LOG.warning(
                _LW("Access to %(share)s at %(export)s is already "
                    "denied for %(access_to)s. GlusterFS volume "
                    "options might have been changed externally."), {
                        'share': share['id'],
                        'export': gluster_mgr.qualified,
                        'access_to': access_to
                    })
            return

        ssl_allow.remove(access_to)
        ssl_allow_opt = ','.join(ssl_allow)
        gluster_mgr.set_vol_option(AUTH_SSL_ALLOW, ssl_allow_opt)

        dynauth = gluster_mgr.get_vol_option(DYNAMIC_AUTH, boolean=True)
        if not dynauth:
            common._restart_gluster_vol(gluster_mgr)
    def _setup_via_manager(self, share_mgr, share_mgr_parent=None):
        # Enable gluster volumes for SSL access only.

        gluster_mgr = share_mgr['manager']
        gluster_mgr_parent = (share_mgr_parent or {}).get('manager', None)

        ssl_allow_opt = (gluster_mgr_parent if gluster_mgr_parent else
                         gluster_mgr).get_vol_option(
            AUTH_SSL_ALLOW)
        if not ssl_allow_opt:
            # Not having AUTH_SSL_ALLOW set is a problematic edge case.
            # - In GlusterFS 3.6, it implies that access is allowed to
            #   noone, including intra-service access, which causes
            #   problems internally in GlusterFS
            # - In GlusterFS 3.7, it implies that access control is
            #   disabled, which defeats the purpose of this driver --
            # so to avoid these possiblitiies, we throw an error in this case.
            msg = (_("Option %(option)s is not defined on gluster volume. "
                     "Volume: %(volname)s") %
                   {'volname': gluster_mgr.volume,
                    'option': AUTH_SSL_ALLOW})
            LOG.error(msg)
            raise exception.GlusterfsException(msg)

        gluster_actions = []
        if gluster_mgr_parent:
            # The clone of the snapshot, a new volume, retains the authorized
            # access list of the snapshotted volume/share, which includes TLS
            # identities of the backend servers, Manila hosts and clients.
            # Retain the identities of the GlusterFS servers and Manila host,
            # and exclude those of the clients in the authorized access list of
            # the new volume. The TLS identities of GlusterFS servers are
            # determined as those that are prefixed by 'glusterfs-server'.
            # And the TLS identity of the Manila host is identified as the
            # one that has 'manila-host' as the prefix.
            # Wrt. GlusterFS' parsing of auth.ssl-allow, please see code from
            # https://github.com/gluster/glusterfs/blob/v3.6.2/
            # xlators/protocol/auth/login/src/login.c#L80
            # until end of gf_auth() function
            old_access_list = re.split('[ ,]', ssl_allow_opt)
            glusterfs_server_CN_pattern = '\Aglusterfs-server'
            manila_host_CN_pattern = '\Amanila-host'
            regex = re.compile(
                '%(pattern1)s|%(pattern2)s' % {
                    'pattern1': glusterfs_server_CN_pattern,
                    'pattern2': manila_host_CN_pattern})
            access_to = ','.join(filter(regex.match, old_access_list))
            gluster_actions.append((AUTH_SSL_ALLOW, access_to))

        for option, value in (
            (NFS_EXPORT_VOL, False), (CLIENT_SSL, True), (SERVER_SSL, True)
        ):
            gluster_actions.append((option, value))

        for action in gluster_actions:
            gluster_mgr.set_vol_option(*action)

        gluster_mgr.set_vol_option(DYNAMIC_AUTH, True, ignore_failure=True)

        # SSL enablement requires a fresh volume start
        # to take effect
        if gluster_mgr_parent:
            # in this case the volume is not started
            # yet (will only be started after this func
            # returns), so we have nothing to do here
            pass
        else:
            common._restart_gluster_vol(gluster_mgr)

        return gluster_mgr.export
    def _setup_via_manager(self, share_mgr, share_mgr_parent=None):
        # Enable gluster volumes for SSL access only.

        gluster_mgr = share_mgr["manager"]
        gluster_mgr_parent = (share_mgr_parent or {}).get("manager", None)

        ssl_allow_opt = (gluster_mgr_parent if gluster_mgr_parent else gluster_mgr).get_gluster_vol_option(
            AUTH_SSL_ALLOW
        )
        if not ssl_allow_opt:
            # Not having AUTH_SSL_ALLOW set is a problematic edge case.
            # - In GlusterFS 3.6, it implies that access is allowed to
            #   noone, including intra-service access, which causes
            #   problems internally in GlusterFS
            # - In GlusterFS 3.7, it implies that access control is
            #   disabled, which defeats the purpose of this driver --
            # so to avoid these possiblitiies, we throw an error in this case.
            msg = _("Option %(option)s is not defined on gluster volume. " "Volume: %(volname)s") % {
                "volname": gluster_mgr.volume,
                "option": AUTH_SSL_ALLOW,
            }
            LOG.error(msg)
            raise exception.GlusterfsException(msg)

        gluster_actions = []
        if gluster_mgr_parent:
            # The clone of the snapshot, a new volume, retains the authorized
            # access list of the snapshotted volume/share, which includes TLS
            # identities of the backend servers, Manila hosts and clients.
            # Retain the identities of the GlusterFS servers and Manila host,
            # and exclude those of the clients in the authorized access list of
            # the new volume. The TLS identities of GlusterFS servers are
            # determined as those that are prefixed by 'glusterfs-server'.
            # And the TLS identity of the Manila host is identified as the
            # one that has 'manila-host' as the prefix.
            # Wrt. GlusterFS' parsing of auth.ssl-allow, please see code from
            # https://github.com/gluster/glusterfs/blob/v3.6.2/
            # xlators/protocol/auth/login/src/login.c#L80
            # until end of gf_auth() function
            old_access_list = re.split("[ ,]", ssl_allow_opt)
            glusterfs_server_CN_pattern = "\Aglusterfs-server"
            manila_host_CN_pattern = "\Amanila-host"
            regex = re.compile(
                "%(pattern1)s|%(pattern2)s"
                % {"pattern1": glusterfs_server_CN_pattern, "pattern2": manila_host_CN_pattern}
            )
            access_to = ",".join(filter(regex.match, old_access_list))
            gluster_actions.append((AUTH_SSL_ALLOW, access_to))

        for option, value in ((NFS_EXPORT_VOL, "off"), (CLIENT_SSL, "on"), (SERVER_SSL, "on")):
            gluster_actions.append((option, value))

        for action in gluster_actions:
            gluster_mgr.gluster_call(
                "volume", "set", gluster_mgr.volume, *action, log=_LE("Setting up GlusterFS volume")
            )

        try:
            gluster_mgr.gluster_call("volume", "set", gluster_mgr.volume, DYNAMIC_AUTH, "on", raw_error=True)
        except exception.ProcessExecutionError as exc:
            if exc.exit_code == 1:
                # 'dynamic-auth' is not supported by gluster backend,
                # that's OK
                pass
            else:
                msg = _(
                    "Error in gluster volume set during volume "
                    "setup. volume: %(volname)s, option: %(option)s, "
                    "value: %(value)s, error: %(error)s"
                ) % {"volname": gluster_mgr.volume, "option": option, "value": value, "error": exc.stderr}
                LOG.error(msg)
                raise exception.GlusterfsException(msg)

        # SSL enablement requires a fresh volume start
        # to take effect
        if gluster_mgr_parent:
            # in this case the volume is not started
            # yet (will only be started after this func
            # returns), so we have nothing to do here
            pass
        else:
            common._restart_gluster_vol(gluster_mgr)

        return gluster_mgr.export
Exemple #17
0
    def _setup_via_manager(self, share_mgr, share_mgr_parent=None):
        # Enable gluster volumes for SSL access only.

        gluster_mgr = share_mgr['manager']
        gluster_mgr_parent = (share_mgr_parent or {}).get('manager', None)

        ssl_allow_opt = (gluster_mgr_parent if gluster_mgr_parent else
                         gluster_mgr).get_gluster_vol_option(AUTH_SSL_ALLOW)
        if not ssl_allow_opt:
            # Not having AUTH_SSL_ALLOW set is a problematic edge case.
            # - In GlusterFS 3.6, it implies that access is allowed to
            #   noone, including intra-service access, which causes
            #   problems internally in GlusterFS
            # - In GlusterFS 3.7, it implies that access control is
            #   disabled, which defeats the purpose of this driver --
            # so to avoid these possiblitiies, we throw an error in this case.
            msg = (_("Option %(option)s is not defined on gluster volume. "
                     "Volume: %(volname)s") % {
                         'volname': gluster_mgr.volume,
                         'option': AUTH_SSL_ALLOW
                     })
            LOG.error(msg)
            raise exception.GlusterfsException(msg)

        gluster_actions = []
        if gluster_mgr_parent:
            # The clone of the snapshot, a new volume, retains the authorized
            # access list of the snapshotted volume/share, which includes TLS
            # identities of the backend servers, Manila hosts and clients.
            # Retain the identities of the GlusterFS servers and Manila host,
            # and exclude those of the clients in the authorized access list of
            # the new volume. The TLS identities of GlusterFS servers are
            # determined as those that are prefixed by 'glusterfs-server'.
            # And the TLS identity of the Manila host is identified as the
            # one that has 'manila-host' as the prefix.
            # Wrt. GlusterFS' parsing of auth.ssl-allow, please see code from
            # https://github.com/gluster/glusterfs/blob/v3.6.2/
            # xlators/protocol/auth/login/src/login.c#L80
            # until end of gf_auth() function
            old_access_list = re.split('[ ,]', ssl_allow_opt)
            glusterfs_server_CN_pattern = '\Aglusterfs-server'
            manila_host_CN_pattern = '\Amanila-host'
            regex = re.compile(
                '%(pattern1)s|%(pattern2)s' % {
                    'pattern1': glusterfs_server_CN_pattern,
                    'pattern2': manila_host_CN_pattern
                })
            access_to = ','.join(filter(regex.match, old_access_list))
            gluster_actions.append((AUTH_SSL_ALLOW, access_to))

        for option, value in ((NFS_EXPORT_VOL, 'off'), (CLIENT_SSL, 'on'),
                              (SERVER_SSL, 'on'), (DYNAMIC_AUTH, 'on')):
            gluster_actions.append((option, value))

        for action in gluster_actions:
            try:
                gluster_mgr.gluster_call('volume', 'set', gluster_mgr.volume,
                                         *action)
            except exception.ProcessExecutionError as exc:
                if action[0] == DYNAMIC_AUTH and exc.exit_code == 1:
                    # 'dynamic-auth' is not supported by gluster backend,
                    # that's OK
                    pass
                else:
                    msg = (_("Error in gluster volume set during volume "
                             "setup. volume: %(volname)s, option: %(option)s, "
                             "value: %(value)s, error: %(error)s") % {
                                 'volname': gluster_mgr.volume,
                                 'option': option,
                                 'value': value,
                                 'error': exc.stderr
                             })
                    LOG.error(msg)
                    raise exception.GlusterfsException(msg)

        # SSL enablement requires a fresh volume start
        # to take effect
        if gluster_mgr_parent:
            # in this case the volume is not started
            # yet (will only be started after this func
            # returns), so we have nothing to do here
            pass
        else:
            common._restart_gluster_vol(gluster_mgr)

        return gluster_mgr.export
Exemple #18
0
    def _deny_access_via_manager(self,
                                 gluster_mgr,
                                 context,
                                 share,
                                 access,
                                 share_server=None):
        """Deny access to a share that's using cert based auth.

        Remove the SSL CN (Common Name) that's allowed to access the server.
        """

        if access['access_type'] != ACCESS_TYPE_CERT:
            raise exception.InvalidShareAccess(
                _("Only 'cert' access type "
                  "allowed for access "
                  "removal."))

        ssl_allow_opt = gluster_mgr.get_gluster_vol_option(AUTH_SSL_ALLOW)
        ssl_allow = re.split('[ ,]', ssl_allow_opt)
        access_to = access['access_to']
        if access_to not in ssl_allow:
            LOG.warning(
                _LW("Access to %(share)s at %(export)s is already "
                    "denied for %(access_to)s. GlusterFS volume "
                    "options might have been changed externally."), {
                        'share': share['id'],
                        'export': gluster_mgr.qualified,
                        'access_to': access_to
                    })
            return

        ssl_allow.remove(access_to)
        ssl_allow_opt = ','.join(ssl_allow)
        try:
            gluster_mgr.gluster_call('volume', 'set', gluster_mgr.volume,
                                     AUTH_SSL_ALLOW, ssl_allow_opt)
        except exception.ProcessExecutionError as exc:
            msg = (_("Error in gluster volume set during deny access. "
                     "Volume: %(volname)s, Option: %(option)s, "
                     "access_to: %(access_to)s, Error: %(error)s") % {
                         'volname': gluster_mgr.volume,
                         'option': AUTH_SSL_ALLOW,
                         'access_to': access_to,
                         'error': exc.stderr
                     })
            LOG.error(msg)
            raise exception.GlusterfsException(msg)

        try:
            dynauth = gluster_mgr.get_gluster_vol_option(DYNAMIC_AUTH) or 'off'
        except exception.ProcessExecutionError as exc:
            msg = (_("Error in querying gluster volume. "
                     "Volume: %(volname)s, Option: %(option)s, "
                     "Error: %(error)s") % {
                         'volname': gluster_mgr.volume,
                         'option': DYNAMIC_AUTH,
                         'error': exc.stderr
                     })
            LOG.error(msg)
            raise exception.GlusterfsException(msg)
        # TODO(csaba): boolean option processing shoud be done in common
        if dynauth.lower() not in ('on', '1', 'true', 'yes', 'enable'):
            common._restart_gluster_vol(gluster_mgr)