コード例 #1
0
ファイル: keycloak.py プロジェクト: shubhamdang/mistral
    def send_request_to_auth_server(self, url, access_token=None):
        certfile = CONF.keycloak_oidc.certfile
        keyfile = CONF.keycloak_oidc.keyfile
        cafile = CONF.keycloak_oidc.cafile or self.get_system_ca_file()
        insecure = CONF.keycloak_oidc.insecure

        verify = None

        if parse.urlparse(url).scheme == "https":
            verify = False if insecure else cafile

        cert = (certfile, keyfile) if certfile and keyfile else None

        headers = {}

        if access_token:
            headers["Authorization"] = "Bearer %s" % access_token

        try:
            resp = requests.get(
                url,
                headers=headers,
                verify=verify,
                cert=cert
            )
        except requests.ConnectionError:
            msg = _(
                "Can't connect to the keycloak server with address '%s'."
            ) % url

            LOG.exception(msg)

            raise exc.MistralException(message=msg)

        if resp.status_code == 401:
            LOG.warning(
                "HTTP response from OIDC provider:"
                " [%s] with WWW-Authenticate: [%s]",
                pprint.pformat(resp.text),
                resp.headers.get("WWW-Authenticate")
            )
        else:
            LOG.debug(
                "HTTP response from the OIDC provider: %s",
                pprint.pformat(resp.json())
            )

        resp.raise_for_status()

        return resp.json()
コード例 #2
0
ファイル: config.py プロジェクト: kurtenbachkyle/mistral
from oslo_config import cfg
from oslo_log import log
from oslo_middleware import cors
from osprofiler import opts as profiler

from mistral import version

from mistral._i18n import _
from mistral.workflow import states

# Options under default group.
launch_opt = cfg.ListOpt(
    'server',
    default=['all'],
    help=_('Specifies which mistral server to start by the launch script. '
           'Valid options are all or any combination of '
           'api, engine, and executor.'))

wf_trace_log_name_opt = cfg.StrOpt(
    'workflow_trace_log_name',
    default='workflow_trace',
    help=_('Logger name for pretty workflow trace output.'))

use_debugger_opt = cfg.BoolOpt(
    'use-debugger',
    default=False,
    help=_('Enables debugger. Note that using this option changes how the '
           'eventlet library is used to support async IO. This could result '
           'in failures that do not occur under normal operation. '
           'Use at your own risk.'))
コード例 #3
0
from oslo_config import cfg
from oslo_log import log
from oslo_middleware import cors
from osprofiler import opts as profiler

from mistral import version

from mistral._i18n import _

# Options under default group.
launch_opt = cfg.ListOpt(
    'server',
    default=['all'],
    help=_('Specifies which mistral server to start by the launch script. '
           'Valid options are all or any combination of '
           'api, engine, and executor.'))

wf_trace_log_name_opt = cfg.StrOpt(
    'workflow_trace_log_name',
    default='workflow_trace',
    help=_('Logger name for pretty workflow trace output.'))

use_debugger_opt = cfg.BoolOpt(
    'use-debugger',
    default=False,
    help=_('Enables debugger. Note that using this option changes how the '
           'eventlet library is used to support async IO. This could result '
           'in failures that do not occur under normal operation. '
           'Use at your own risk.'))
コード例 #4
0
ファイル: keycloak.py プロジェクト: wookiist/mistral
    def authenticate(self, req):
        certfile = CONF.keycloak_oidc.certfile
        keyfile = CONF.keycloak_oidc.keyfile
        cafile = CONF.keycloak_oidc.cafile or self.get_system_ca_file()
        insecure = CONF.keycloak_oidc.insecure

        if 'X-Auth-Token' not in req.headers:
            msg = _("Auth token must be provided in 'X-Auth-Token' header.")
            LOG.error(msg)
            raise exc.UnauthorizedException(message=msg)
        access_token = req.headers.get('X-Auth-Token')

        try:
            decoded = jwt.decode(access_token,
                                 algorithms=['RS256'],
                                 verify=False)
        except Exception as e:
            msg = _("Token can't be decoded because of wrong format %s")\
                % str(e)
            LOG.error(msg)
            raise exc.UnauthorizedException(message=msg)

        # Get user realm from parsed token
        # Format is "iss": "http://<host>:<port>/auth/realms/<realm_name>",
        __, __, realm_name = decoded['iss'].strip().rpartition('/realms/')

        # Get roles from from parsed token
        roles = ','.join(decoded['realm_access']['roles']) \
            if 'realm_access' in decoded else ''

        # NOTE(rakhmerov): There's a special endpoint for introspecting
        # access tokens described in OpenID Connect specification but it's
        # available in KeyCloak starting only with version 1.8.Final so we have
        # to use user info endpoint which also takes exactly one parameter
        # (access token) and replies with error if token is invalid.
        user_info_endpoint = ("%s/realms/%s/protocol/openid-connect/userinfo" %
                              (CONF.keycloak_oidc.auth_url, realm_name))

        verify = None
        if urllib.parse.urlparse(user_info_endpoint).scheme == "https":
            verify = False if insecure else cafile

        cert = (certfile, keyfile) if certfile and keyfile else None

        try:
            resp = requests.get(
                user_info_endpoint,
                headers={"Authorization": "Bearer %s" % access_token},
                verify=verify,
                cert=cert)
        except requests.ConnectionError:
            msg = _("Can't connect to keycloak server with address '%s'."
                    ) % CONF.keycloak_oidc.auth_url
            LOG.error(msg)
            raise exc.MistralException(message=msg)

        if resp.status_code == 401:
            LOG.warning(
                "HTTP response from OIDC provider:"
                " [%s] with WWW-Authenticate: [%s]", pprint.pformat(resp.text),
                resp.headers.get("WWW-Authenticate"))
        else:
            LOG.debug("HTTP response from OIDC provider: %s",
                      pprint.pformat(resp.text))

        resp.raise_for_status()

        LOG.debug("HTTP response from OIDC provider: %s",
                  pprint.pformat(resp.json()))

        req.headers["X-Identity-Status"] = "Confirmed"
        req.headers["X-Project-Id"] = realm_name
        req.headers["X-Roles"] = roles
コード例 #5
0
    def authenticate(self, req):
        if 'X-Auth-Token' not in req.headers:
            msg = _("Auth token must be provided in 'X-Auth-Token' header.")

            LOG.error(msg)

            raise exc.UnauthorizedException(message=msg)

        access_token = req.headers.get('X-Auth-Token')

        try:
            decoded = jwt.decode(access_token,
                                 algorithms=['RS256'],
                                 verify=False)
        except Exception as e:
            msg = _("Token can't be decoded because of wrong format %s")\
                % str(e)

            LOG.error(msg)

            raise exc.UnauthorizedException(message=msg)

        # Get user realm from parsed token
        # Format is "iss": "http://<host>:<port>/auth/realms/<realm_name>",
        __, __, realm_name = decoded['iss'].strip().rpartition('/realms/')
        audience = decoded.get('aud')

        # Get roles from parsed token
        roles = ','.join(decoded['realm_access']['roles']) \
            if 'realm_access' in decoded else ''

        # NOTE(rakhmerov): There's a special endpoint for introspecting
        # access tokens described in OpenID Connect specification but it's
        # available in KeyCloak starting only with version 1.8.Final so we have
        # to use user info endpoint which also takes exactly one parameter
        # (access token) and replies with error if token is invalid.
        user_info_endpoint_url = CONF.keycloak_oidc.user_info_endpoint_url

        if user_info_endpoint_url.startswith(('http://', 'https://')):
            self.send_request_to_auth_server(url=user_info_endpoint_url,
                                             access_token=access_token)
        else:
            public_key = self.get_public_key(realm_name)

            keycloak_iss = None

            try:
                if CONF.keycloak_oidc.keycloak_iss:
                    keycloak_iss = CONF.keycloak_oidc.keycloak_iss % realm_name

                jwt.decode(access_token,
                           public_key,
                           audience=audience,
                           issuer=keycloak_iss,
                           algorithms=['RS256'],
                           verify=True)
            except Exception:
                LOG.exception('The request access token is invalid.')

                raise exc.UnauthorizedException()

        req.headers["X-Identity-Status"] = "Confirmed"
        req.headers["X-Project-Id"] = realm_name
        req.headers["X-Roles"] = roles
コード例 #6
0
from oslo_config import cfg
from oslo_log import log
from oslo_middleware import cors
from osprofiler import opts as profiler

from mistral import version

from mistral._i18n import _

# Options under default group.
launch_opt = cfg.ListOpt(
    'server',
    default=['all'],
    help=_('Specifies which mistral server to start by the launch script. '
           'Valid options are all or any combination of '
           'api, engine, and executor.'))

wf_trace_log_name_opt = cfg.StrOpt(
    'workflow_trace_log_name',
    default='workflow_trace',
    help=_('Logger name for pretty workflow trace output.'))

use_debugger_opt = cfg.BoolOpt(
    'use-debugger',
    default=False,
    help=_('Enables debugger. Note that using this option changes how the '
           'eventlet library is used to support async IO. This could result '
           'in failures that do not occur under normal operation. '
           'Use at your own risk.'))
コード例 #7
0
ファイル: keycloak.py プロジェクト: openstack/mistral
    def authenticate(self, req):
        certfile = CONF.keycloak_oidc.certfile
        keyfile = CONF.keycloak_oidc.keyfile
        cafile = CONF.keycloak_oidc.cafile or self.get_system_ca_file()
        insecure = CONF.keycloak_oidc.insecure

        if 'X-Auth-Token' not in req.headers:
            msg = _("Auth token must be provided in 'X-Auth-Token' header.")
            LOG.error(msg)
            raise exc.UnauthorizedException(message=msg)
        access_token = req.headers.get('X-Auth-Token')

        try:
            decoded = jwt.decode(access_token, algorithms=['RS256'],
                                 verify=False)
        except Exception as e:
            msg = _("Token can't be decoded because of wrong format %s")\
                % str(e)
            LOG.error(msg)
            raise exc.UnauthorizedException(message=msg)

        # Get user realm from parsed token
        # Format is "iss": "http://<host>:<port>/auth/realms/<realm_name>",
        __, __, realm_name = decoded['iss'].strip().rpartition('/realms/')

        # Get roles from from parsed token
        roles = ','.join(decoded['realm_access']['roles']) \
            if 'realm_access' in decoded else ''

        # NOTE(rakhmerov): There's a special endpoint for introspecting
        # access tokens described in OpenID Connect specification but it's
        # available in KeyCloak starting only with version 1.8.Final so we have
        # to use user info endpoint which also takes exactly one parameter
        # (access token) and replies with error if token is invalid.
        user_info_endpoint_url = CONF.keycloak_oidc.user_info_endpoint_url

        if user_info_endpoint_url.startswith(('http://', 'https://')):
            user_info_endpoint = user_info_endpoint_url
        else:
            user_info_endpoint = (
                ("%s" + user_info_endpoint_url) %
                (CONF.keycloak_oidc.auth_url, realm_name))

        verify = None
        if urllib.parse.urlparse(user_info_endpoint).scheme == "https":
            verify = False if insecure else cafile

        cert = (certfile, keyfile) if certfile and keyfile else None

        try:
            resp = requests.get(
                user_info_endpoint,
                headers={"Authorization": "Bearer %s" % access_token},
                verify=verify,
                cert=cert
            )
        except requests.ConnectionError:
            msg = _("Can't connect to keycloak server with address '%s'."
                    ) % CONF.keycloak_oidc.auth_url
            LOG.error(msg)
            raise exc.MistralException(message=msg)

        if resp.status_code == 401:
            LOG.warning("HTTP response from OIDC provider:"
                        " [%s] with WWW-Authenticate: [%s]",
                        pprint.pformat(resp.text),
                        resp.headers.get("WWW-Authenticate"))
        else:
            LOG.debug("HTTP response from OIDC provider: %s",
                      pprint.pformat(resp.text))

        resp.raise_for_status()

        LOG.debug(
            "HTTP response from OIDC provider: %s",
            pprint.pformat(resp.json())
        )

        req.headers["X-Identity-Status"] = "Confirmed"
        req.headers["X-Project-Id"] = realm_name
        req.headers["X-Roles"] = roles
コード例 #8
0
ファイル: config.py プロジェクト: openstack/mistral
from keystoneauth1 import loading
from oslo_config import cfg
from oslo_log import log
from oslo_middleware import cors
from osprofiler import opts as profiler

from mistral import version

from mistral._i18n import _

# Options under default group.
launch_opt = cfg.ListOpt(
    'server',
    default=['all'],
    help=_('Specifies which mistral server to start by the launch script. '
           'Valid options are all or any combination of '
           'api, engine, and executor.')
)

wf_trace_log_name_opt = cfg.StrOpt(
    'workflow_trace_log_name',
    default='workflow_trace',
    help=_('Logger name for pretty workflow trace output.')
)

use_debugger_opt = cfg.BoolOpt(
    'use-debugger',
    default=False,
    help=_('Enables debugger. Note that using this option changes how the '
           'eventlet library is used to support async IO. This could result '
           'in failures that do not occur under normal operation. '