示例#1
0
    def test_login_handler(self):
        sso = SSO(app=self.app)

        @sso.login_handler
        def _callback(attr):
            od = OrderedDict()
            for k, v in sorted(attr.items()):
                od[k] = v
            return six.b('{0}'.format(od))

        @contextmanager
        def request_environ_set(app, data):

            def handler(sender, **kwargs):
                for (k, v) in data.items():
                    request.environ[k] = v

            with request_started.connected_to(handler, app):
                yield

        def run(conf, data, expected_data):
            self.app.config['SSO_ATTRIBUTE_MAP'] = conf
            with request_environ_set(self.app, data):
                with self.app.test_client() as c:
                    resp = c.get(self.app.config['SSO_LOGIN_URL'])
                    od = OrderedDict()
                    for k, v in sorted(expected_data.items()):
                        od[k] = v
                    self.assertEqual(resp.data,
                                     six.b('{0}'.format(od)))

        conf = {'HTTP_AJP_SHIB_EPPN': (True, 'eppn'), 'HTTP_AJP_SHIB_MAIL': (False, 'mail')}
        data = {'HTTP_AJP_SHIB_EPPN': '*****@*****.**'}
        expected_data = {'eppn': '*****@*****.**', 'mail': None}

        run(conf, data, expected_data)

        conf = {'HTTP_AJP_SHIB_EPPN': (True, 'eppn'), 'HTTP_AJP_SHIB_MAIL': (False, 'mail')}
        data = {'HTTP_AJP_SHIB_EPPN': None}
        expected_data = {'eppn': None, 'mail': None}

        @sso.login_handler
        def _callback_redef(attr):
            assert False

        @sso.login_error_handler
        def _callback_error(attr):
            od = OrderedDict()
            for k, v in sorted(attr.items()):
                od[k] = v
            return '{0}'.format(od)

        run(conf, data, expected_data)
示例#2
0
    def test_login_handler(self):
        sso = SSO(app=self.app)

        @sso.login_handler
        def _callback(attr):
            return '{0}'.format(attr)

        @contextmanager
        def request_environ_set(app, data):
            def handler(sender, **kwargs):
                for (k, v) in data.items():
                    request.environ[k] = v

            with request_started.connected_to(handler, app):
                yield

        def run(conf, data, expected_data):
            self.app.config['SSO_ATTRIBUTE_MAP'] = conf
            with request_environ_set(self.app, data):
                with self.app.test_client() as c:
                    resp = c.get(self.app.config['SSO_LOGIN_URL'])
                    assert literal_eval(resp.data.decode('utf-8')) \
                        == expected_data

        conf = {'FOO': (True, 'bar'), 'BAZ': (False, 'baa')}
        data = {'FOO': 'foo'}
        expected_data = {'bar': 'foo', 'baa': None}

        run(conf, data, expected_data)

        conf = {'FOO': (True, 'bar'), 'BAZ': (True, 'baa')}
        data = {'FOO': 'foo', 'BAZ': 'baz'}
        expected_data = {'bar': 'foo', 'baa': 'baz'}

        run(conf, data, expected_data)

        conf = {'FOO': (True, 'bar'), 'BAZ': (False, 'baa')}
        data = {'FOO': 'foo', 'BAZ': 6}
        expected_data = {'bar': 'foo', 'baa': 6}

        run(conf, data, expected_data)
示例#3
0
    def test_invalid_attribute_map(self):
        SSO(app=self.app)

        @contextmanager
        def request_environ_set(app, data):
            def handler(sender, **kwargs):
                for (k, v) in data.items():
                    request.environ[k] = v

            with request_started.connected_to(handler, app):
                yield

        conf = {'FOO': (True, 'bar'), 'BAZ': (True, 'baa')}
        data = {'FOO': 'foo'}

        self.app.config['SSO_ATTRIBUTE_MAP'] = conf
        with request_environ_set(self.app, data):
            with self.app.test_client() as c:
                try:
                    c.get(self.app.config['SSO_LOGIN_URL'])
                    assert False
                except SSOAttributeError:
                    assert True
示例#4
0
 def test_creation_init(self):
     assert 'sso' not in self.app.extensions
     r = SSO()
     r.init_app(app=self.app)
     assert isinstance(self.app.extensions['sso'], SSO)
示例#5
0
app.register_blueprint(plugins)
app.register_blueprint(users)
app.register_blueprint(groups)
app.register_blueprint(instances)
app.register_blueprint(activations)
app.register_blueprint(firstuser)
app.register_blueprint(myip)
app.register_blueprint(sessions)
app.register_blueprint(variables)
app.register_blueprint(quota)
app.register_blueprint(locks)
app.register_blueprint(import_export)
app.register_blueprint(stats)

if app.config['ENABLE_SHIBBOLETH_LOGIN']:
    sso = SSO(app=app)

    @sso.login_handler
    def login(user_info):
        eppn = user_info['eppn']
        user = User.query.filter_by(email=eppn).first()
        if not user:
            user = create_user(eppn, password=uuid.uuid4().hex)
        if not user.is_active:
            user.is_active = True
            db.session.commit()
        if user.is_blocked:
            error_description = 'You have been blocked, contact your administrator'
            return render_template('error.html',
                                   error_title='User Blocked',
                                   error_description=error_description)
示例#6
0
文件: __init__.py 项目: CESNET/exafs
db = SQLAlchemy()
csrf = CSRFProtect(app)

# Map SSO attributes from ADFS to session keys under session['user']
#: Default attribute map
SSO_ATTRIBUTE_MAP = {
    'eppn': (True, 'eppn'),
    'cn': (False, 'cn'),
}

app.config.setdefault('VERSION', __version__)
app.config.setdefault('SSO_ATTRIBUTE_MAP', SSO_ATTRIBUTE_MAP)
app.config.setdefault('SSO_LOGIN_URL', '/login')

# This attaches the *flask_sso* login handler to the SSO_LOGIN_URL,
ext = SSO(app=app)

from flowapp import models, constants, validators
from .views.admin import admin
from .views.rules import rules
from .views.api_v1 import api as api_v1
from .views.api_v2 import api as api_v2
from .views.api_v3 import api as api_v3
from .views.api_keys import api_keys
from .auth import auth_required
from .views.dashboard import dashboard

# no need for csrf on api because we use JWT
csrf.exempt(api_v1)
csrf.exempt(api_v2)
示例#7
0
 def test_default_config(self):
     SSO(app=self.app)
     for k in dir(default_config):
         if k.startswith('SSO_'):
             assert self.app.config.get(k) == getattr(default_config, k)
示例#8
0
 def test_creation_init(self):
     assert 'sso' not in self.app.extensions
     r = SSO()
     r.init_app(app=self.app)
     assert isinstance(self.app.extensions['sso'], SSO)
示例#9
0
 def test_double_creation(self):
     SSO(app=self.app)
     self.assertRaises(RuntimeError, SSO, app=self.app)
示例#10
0
 def test_creation_old_flask(self):
     # Simulate old Flask (pre 0.9)
     del self.app.extensions
     SSO(app=self.app)
     assert isinstance(self.app.extensions['sso'], SSO)
示例#11
0
 def test_creation(self):
     assert 'sso' not in self.app.extensions
     SSO(app=self.app)
     assert isinstance(self.app.extensions['sso'], SSO)
示例#12
0
    def test_login_error_handler(self):
        sso = SSO(app=self.app)

        @sso.login_handler
        def _callback(attr):
            return '{0}'.format(attr)

        @sso.login_error_handler
        def _callback_error(attr):
            return '{0}'.format(attr)

        @contextmanager
        def request_environ_set(app, data):
            def handler(sender, **kwargs):
                for (k, v) in data.items():
                    request.environ[k] = v

            with request_started.connected_to(handler, app):
                yield

        def run(conf, data, expected_data):
            self.app.config['SSO_ATTRIBUTE_MAP'] = conf
            with request_environ_set(self.app, data):
                with self.app.test_client() as c:
                    resp = c.get(self.app.config['SSO_LOGIN_URL'])
                    self.assertEqual(resp.data.decode('utf-8'),
                                     '{0}'.format(expected_data))

        conf = {'FOO': (True, 'bar'), 'BAZ': (False, 'baa')}
        data = {'FOO': 'foo'}
        expected_data = {'bar': 'foo', 'baa': None}

        run(conf, data, expected_data)

        conf = {'FOO': (True, 'bar'), 'BAZ': (True, 'baa')}
        data = {'FOO': 'foo', 'BAZ': 'baz'}
        expected_data = {'bar': 'foo', 'baa': 'baz'}

        run(conf, data, expected_data)

        conf = {'FOO': (True, 'bar'), 'BAZ': (False, 'baa')}
        data = {'FOO': 'foo', 'BAZ': 6}
        expected_data = {'bar': 'foo', 'baa': 6}

        run(conf, data, expected_data)

        conf = {'FOO': (True, 'bar'), 'BAZ': (False, 'baa')}
        data = {'FOO': None, 'BAZ': 6}
        expected_data = {'bar': None, 'baa': 6}

        run(conf, data, expected_data)

        # login handler will not be called when required attributes are missing
        @sso.login_handler
        def _callback_(attr):
            assert False

        conf = {'FOO': (True, 'bar'), 'BAZ': (False, 'baa')}
        data = {'FOO': None, 'BAZ': 6}
        expected_data = {'bar': None, 'baa': 6}

        run(conf, data, expected_data)

        # login error handler will not be called when required attributes are
        # present

        @sso.login_handler
        def _callback__(attr):
            return '{0}'.format(attr)

        @sso.login_error_handler
        def _callback_error_(attr):
            assert False

        conf = {'FOO': (True, 'bar'), 'BAZ': (False, 'baa')}
        data = {'FOO': 'foo', 'BAZ': 6}
        expected_data = {'bar': 'foo', 'baa': 6}

        run(conf, data, expected_data)
示例#13
0
    re.compile(r'building-[\d]+'),
    re.compile(r'Users by Home CERNHOME[A-Z]'),
)

#: Default attribute map
SSO_ATTRIBUTE_MAP = {
    'ADFS_AUTHLEVEL': (False, 'authlevel'),
    'ADFS_GROUP': (True, 'group'),
    'ADFS_LOGIN': (True, 'nickname'),
    'ADFS_ROLE': (False, 'role'),
    'ADFS_EMAIL': (True, 'email'),
    'ADFS_IDENTITYCLASS': (False, 'external'),
    'HTTP_SHIB_AUTHENTICATION_METHOD': (False, 'authmethod'),
}

sso = SSO()


def setup_app(app):
    """Setup SSO extension."""
    app.config['CFG_EXTERNAL_AUTH_USING_SSO'] = True
    app.config.setdefault('SSO_ATTRIBUTE_MAP', SSO_ATTRIBUTE_MAP)
    sso.init_app(app)

    def fetch_groups(groups):
        groups = groups.split(
            app.config.get('CFG_EXTERNAL_AUTH_SSO_GROUPS_SEPARATOR', ';'))
        # Filtering out uncomfortable groups
        groups = [
            group for group in groups
            if group not in app.config.get('CFG_EXTERNAL_AUTH_HIDDEN_GROUPS',
示例#14
0
    def init(cls, tracking_mode=False):
        """

        :param tracking_mode:
        :type tracking_mode: bool
        :return:
        :rtype: flask.Flask
        """
        from flask_socketio import SocketIO
        from flask import Flask
        from Config import Environment
        cls._app = Flask(
            Environment.SERVER_DATA['APP_NAME'],
            static_url_path="/file",
            static_folder=Environment.SERVER_DATA['STATIC_PATH'],
            template_folder=Environment.SERVER_DATA['TEMPLATE_PATH'])
        if 'CORS' in Environment.Logins:
            from flask_cors import CORS
            cls._app.config["CORS_ALLOW_HEADERS"] = Environment.SERVER_DATA[
                'CORS']['ALLOW_HEADERS']
            cls._app.config["CORS_ALWAYS_SEND"] = Environment.SERVER_DATA[
                'CORS']['ALWAYS_SEND']
            cls._app.config[
                "CORS_AUTOMATIC_OPTIONS"] = Environment.SERVER_DATA['CORS'][
                    'AUTOMATIC_OPTIONS']
            cls._app.config["CORS_EXPOSE_HEADERS"] = Environment.SERVER_DATA[
                'CORS']['EXPOSE_HEADERS']
            cls._app.config[
                "CORS_INTERCEPT_EXCEPTIONS"] = Environment.SERVER_DATA['CORS'][
                    'INTERCEPT_EXCEPTIONS']
            cls._app.config["CORS_MAX_AGE"] = Environment.SERVER_DATA['CORS'][
                'MAX_AGE']
            cls._app.config["CORS_METHODS"] = Environment.SERVER_DATA['CORS'][
                'METHODS']
            cls._app.config["CORS_ORIGINS"] = Environment.SERVER_DATA['CORS'][
                'ORIGINS']
            cls._app.config["CORS_RESOURCES"] = r"/*"
            cls._app.config["CORS_SEND_WILDCARD"] = Environment.SERVER_DATA[
                'CORS']['SEND_WILDCARD']
            cls._app.config[
                "CORS_SUPPORTS_CREDENTIALS"] = Environment.SERVER_DATA['CORS'][
                    'SUPPORTS_CREDENTIALS']
            cls._app.config["CORS_VARY_HEADER"] = Environment.SERVER_DATA[
                'CORS']['VARY_HEADER']
            cors = CORS(cls._app,
                        origins=Environment.SERVER_DATA['CORS']['ORIGINS'])
        if 'APP_KEY' in Environment.SERVER_DATA:
            from flask_wtf.csrf import CSRFProtect
            cls._session = Session()
            #cls._app.config['TESTING'] = True
            #cls._app.config['TEMPLATES_AUTO_RELOAD'] = True
            cls._app.config['SECRET_KEY'] = Environment.SERVER_DATA['APP_KEY']
            cls._app.config['SESSION_TYPE'] = Environment.SERVER_DATA[
                'SESSION']
            if Environment.SERVER_DATA['SESSION'] == 'filesystem':
                cls._app.config['SESSION_FILE_DIR'] = Environment.Services[
                    Environment.SERVER_DATA['SESSION']]['PATH']
            if Environment.SERVER_DATA['SESSION'] == 'memcached':
                import pymemcache
                cls._app.config['SESSION_MEMCACHED'] = pymemcache.Client(
                    (Environment.Services[Environment.SERVER_DATA['SESSION']]
                     ['HOST'], Environment.Services[
                         Environment.SERVER_DATA['SESSION']]['PORT']))
            if Environment.SERVER_DATA['SESSION'] == 'redis':
                import redis
                cls._app.config['SESSION_REDIS'] = redis.from_url(
                    "%s://%s:%d/redis" %
                    (Environment.SERVER_DATA['SESSION'], Environment.Services[
                        Environment.SERVER_DATA['SESSION']]['HOST'],
                     Environment.Services[
                         Environment.SERVER_DATA['SESSION']]['PORT']))
            if Environment.SERVER_DATA['SESSION'] == 'sqlalchemy':
                from Database import Database
                cls._app = Database.setup_sessions(cls._app)
            if Environment.SERVER_DATA['SESSION'] == 'mongodb':
                from pymongo import MongoClient
                db_conf = Environment.Databases[
                    Environment.SERVER_DATA['SESSION']]
                cls._app.config['SESSION_MONGODB'] = MongoClient(
                    "%s://%s:%s@%s:%d" %
                    (db_conf['driver'], db_conf['user'], db_conf['password'],
                     db_conf['address'], db_conf['port']))
                cls._app.config['SESSION_MONGODB_DB'] = db_conf['database']
                cls._app.config['SESSION_MONGODB_COLLECT'] = db_conf[
                    'collection']
            cls._session.init_app(cls._app)
            cls._csrf = CSRFProtect()
            cls._csrf.init_app(cls._app)
            if 'SSO' in Environment.Logins:
                from flask_sso import SSO
                cls.sso = SSO()
                cls._app.config['SSO_LOGIN_URL'] = Environment.Logins['SSO'][
                    'LOGIN_URL']
                cls._app.config['SSO_LOGIN_ENDPOINT'] = Environment.Logins[
                    'SSO']['LOGIN_ENDPOINT']
                cls._app.config['SSO_ATTRIBUTE_MAP'] = {
                    item: (value['value'], value['attr'])
                    for item, value in Environment.Logins['SSO']
                    ['ATTRIBUTE_MAP'].items()
                }
                cls.sso.init_app(cls._app)
            if 'OpenID' in Environment.Logins:
                from Utils.Auth.openid import OpenIDConnect
                from flask_openid import OpenID
                cls.openid = OpenIDConnect()
                for key, value in Environment.Logins['OpenID'].items():
                    cls._app.config[key] = value
                cls.openid.init_app(cls._app)
            if 'LDAP' in Environment.Logins:
                if 'LDAP_HOST' not in Environment.Logins[
                        'LDAP'] and 'LDAP_DOMAIN' in Environment.Logins['LDAP']:
                    from activedirectory import Locator
                    ldap = Locator()
                    Environment.Logins['LDAP']['LDAP_HOST'] = ldap.locate_many(
                        Environment.Logins['LDAP']['LDAP_DOMAIN'])[0]
                if 'LDAP_REQUIRED_GROUP' not in Environment.Logins['LDAP']:
                    Environment.Logins['LDAP']['LDAP_REQUIRED_GROUP'] = None
                from Utils.Auth.ldap import LDAP
                for key, val in Environment.Logins['LDAP'].items():
                    cls._app.config[key] = val
                cls.ldap = LDAP(cls._app)
        cls._socket = SocketIO()
        cls._socket.init_app(cls._app)
        return cls._app