示例#1
0
    def __init__(self,
                 dbGaP,
                 DB,
                 project_mapping,
                 storage_credentials=None,
                 db_session=None,
                 sync_from_dir=None):
        '''
        Syncs ACL files from dbGap to auth database and storage backends
        Args:
            dbGaP: a dict containing creds to access dbgap sftp
            DB: database connection string
            project_mapping: a dict containing how dbgap ids map to projects
            storage_credentials: a dict containing creds for storage backends
            sync_from_dir: path to an alternative dir to sync from instead of
                           dbGaP
        '''
        self.sync_from_dir = sync_from_dir
        if sync_from_dir is None:
            self.sftp = dbGaP['sftp']
            self.dbgap_key = dbGaP['decrypt_key']
        self.session = db_session
        self.driver = SQLAlchemyDriver(DB)
        self._projects = dict()
        self.project_mapping = project_mapping
        self.logger = get_logger('dbgap_syncer')

        if storage_credentials:
            self.storage_manager = StorageManager(storage_credentials,
                                                  logger=self.logger)
示例#2
0
def delete_client_action(DB, client_name):
    try:
        cirrus_config.update(**config["CIRRUS_CFG"])
    except AttributeError:
        # no cirrus config, continue anyway. we don't have client service accounts
        # to delete
        pass

    try:
        driver = SQLAlchemyDriver(DB)
        with driver.session as current_session:
            if (
                not current_session.query(Client)
                .filter(Client.name == client_name)
                .first()
            ):
                raise Exception("client {} does not exist".format(client_name))

            clients = (
                current_session.query(Client).filter(Client.name == client_name).all()
            )

            for client in clients:
                _remove_client_service_accounts(current_session, client)
                current_session.delete(client)
            current_session.commit()

        logger.info("Client {} deleted".format(client_name))
    except Exception as e:
        logger.error(str(e))
示例#3
0
    def create_refresh_token(self):
        """
        Create a new refresh token and add its entry to the database.

        Return:
            JWTResult: the refresh token result
        """
        driver = SQLAlchemyDriver(self.db)
        with driver.session as current_session:
            user = query_for_user(session=current_session, username=self.username)

            if not user:
                raise EnvironmentError(
                    "no user found with given username: "******"jti"],
                    userid=user.id,
                    expires=jwt_result.claims["exp"],
                )
            )

            return jwt_result
示例#4
0
def app_sessions(app):
    app.url_map.strict_slashes = False
    app.db = SQLAlchemyDriver(app.config["DB"])
    migrate(app.db)
    session = flask_scoped_session(app.db.Session, app)  # noqa
    app.storage_manager = StorageManager(
        app.config["STORAGE_CREDENTIALS"], logger=app.logger
    )
    enabled_idp_ids = app.config["ENABLED_IDENTITY_PROVIDERS"]["providers"].keys()
    # Add OIDC client for Google if configured.
    configured_google = (
        "OPENID_CONNECT" in app.config and "google" in app.config["OPENID_CONNECT"]
    )
    if configured_google:
        app.google_client = GoogleClient(
            app.config["OPENID_CONNECT"]["google"],
            HTTP_PROXY=app.config.get("HTTP_PROXY"),
            logger=app.logger,
        )
    # Add OIDC client for multi-tenant fence if configured.
    configured_fence = (
        "OPENID_CONNECT" in app.config
        and "fence" in app.config["OPENID_CONNECT"]
        and "fence" in enabled_idp_ids
    )
    if configured_fence:
        app.fence_client = OAuthClient(**app.config["OPENID_CONNECT"]["fence"])
    app.session_interface = UserSessionInterface()
    if app.config.get("ARBORIST"):
        app.arborist = ArboristClient(arborist_base_url=app.config["ARBORIST"])
示例#5
0
def delete_expired_service_accounts(DB):
    """
    Delete all expired service accounts.
    """
    cirrus_config.update(**config["CIRRUS_CFG"])

    driver = SQLAlchemyDriver(DB)
    with driver.session as session:
        current_time = int(time.time())
        records_to_delete = (
            session.query(ServiceAccountToGoogleBucketAccessGroup)
            .filter(ServiceAccountToGoogleBucketAccessGroup.expires < current_time)
            .all()
        )
        if len(records_to_delete):
            with GoogleCloudManager() as manager:
                for record in records_to_delete:
                    try:
                        manager.remove_member_from_group(
                            record.service_account.email, record.access_group.email
                        )
                        session.delete(record)
                        logger.info(
                            "Removed expired service account: {}".format(
                                record.service_account.email
                            )
                        )
                    except Exception as e:
                        logger.error(
                            "ERROR: Could not delete service account {}. Details: {}".format(
                                record.service_account.email, e
                            )
                        )

                session.commit()
示例#6
0
def db_init(app):
    app.logger.info('Initializing PsqlGraph driver')
    app.db = PsqlGraphDriver(
        host=app.config['PSQLGRAPH']['host'],
        user=app.config['PSQLGRAPH']['user'],
        password=app.config['PSQLGRAPH']['password'],
        database=app.config['PSQLGRAPH']['database'],
        set_flush_timestamps=True,
    )

    app.userdb = SQLAlchemyDriver(app.config['PSQL_USER_DB_CONNECTION'])
    flask_scoped_session(app.userdb.Session, app)

    app.oauth2 = OAuth2Client(**app.config['OAUTH2'])

    app.logger.info('Initializing Signpost driver')
    app.signpost = SignpostClient(
        app.config['SIGNPOST']['host'],
        version=app.config['SIGNPOST']['version'],
        auth=app.config['SIGNPOST']['auth'])
    try:
        app.logger.info('Initializing Auth driver')
        app.auth = AuthDriver(app.config["AUTH_ADMIN_CREDS"], app.config["INTERNAL_AUTH"])
    except Exception:
        app.logger.exception("Couldn't initialize auth, continuing anyway")
示例#7
0
def link_external_bucket(db, name):

    """
    Link with bucket owned by an external party. This will create the bucket
    in fence database and create a google group to access the bucket in both
    Google and fence database.
    The external party will need to add the google group read access to bucket
    afterwards.
    """

    cirrus_config.update(**config["CIRRUS_CFG"])

    google_project_id = cirrus_config.GOOGLE_PROJECT_ID

    db = SQLAlchemyDriver(db)
    with db.session as current_session:
        google_cloud_provider = _get_or_create_google_provider(current_session)

        bucket_db_entry = Bucket(name=name, provider_id=google_cloud_provider.id)
        current_session.add(bucket_db_entry)
        current_session.commit()
        privileges = ["read"]

        access_group = _create_google_bucket_access_group(
            current_session, name, bucket_db_entry.id, google_project_id, privileges
        )

    logger.info("bucket access group email: {}".format(access_group.email))
    return access_group.email
示例#8
0
def google_list_authz_groups(db):
    """
    Builds a list of Google authorization information which includes
    the Google Bucket Access Group emails, Bucket(s) they're associated with, and
    underlying Fence Project auth_id that provides access to that Bucket/Group

    db (string): database instance
    """
    driver = SQLAlchemyDriver(db)

    with driver.session as db_session:
        google_authz = (
            db_session.query(
                GoogleBucketAccessGroup.email,
                Bucket.name,
                Project.auth_id,
                ProjectToBucket,
            )
            .join(Project, ProjectToBucket.project_id == Project.id)
            .join(Bucket, ProjectToBucket.bucket_id == Bucket.id)
            .join(
                GoogleBucketAccessGroup, GoogleBucketAccessGroup.bucket_id == Bucket.id
            )
        ).all()

        print("GoogleBucketAccessGroup.email, Bucket.name, Project.auth_id")
        for item in google_authz:
            print(", ".join(item[:-1]))

        return google_authz
示例#9
0
def create_client(
    username,
    urls,
    DB,
    name="",
    description="",
    auto_approve=False,
    is_admin=False,
    grant_types=None,
    confidential=True,
    arborist=None,
    policies=None,
    allowed_scopes=None,
):
    client_id = random_str(40)
    if arborist is not None:
        arborist.create_client(client_id, policies)
    grant_types = grant_types
    driver = SQLAlchemyDriver(DB)
    client_secret = None
    hashed_secret = None
    if confidential:
        client_secret = random_str(55)
        hashed_secret = bcrypt.hashpw(client_secret.encode("utf-8"),
                                      bcrypt.gensalt()).decode("utf-8")
    auth_method = "client_secret_basic" if confidential else "none"
    allowed_scopes = allowed_scopes or config["CLIENT_ALLOWED_SCOPES"]
    if not set(allowed_scopes).issubset(set(config["CLIENT_ALLOWED_SCOPES"])):
        raise ValueError("Each allowed scope must be one of: {}".format(
            config["CLIENT_ALLOWED_SCOPES"]))
    if "openid" not in allowed_scopes:
        allowed_scopes.append("openid")
        logger.warning(
            'Adding required "openid" scope to list of allowed scopes.')
    with driver.session as s:
        user = query_for_user(session=s, username=username)

        if not user:
            user = User(username=username, is_admin=is_admin)
            s.add(user)
        if s.query(Client).filter(Client.name == name).first():
            if arborist is not None:
                arborist.delete_client(client_id)
            raise Exception("client {} already exists".format(name))
        client = Client(
            client_id=client_id,
            client_secret=hashed_secret,
            user=user,
            redirect_uris=urls,
            _allowed_scopes=" ".join(allowed_scopes),
            description=description,
            name=name,
            auto_approve=auto_approve,
            grant_types=grant_types,
            is_confidential=confidential,
            token_endpoint_auth_method=auth_method,
        )
        s.add(client)
        s.commit()
    return client_id, client_secret
示例#10
0
def create_client_action_wrapper(
    to_test,
    db=None,
    client_name="exampleapp",
    username="******",
    urls=["https://betawebapp.example/fence", "https://webapp.example/fence"],
    grant_types=["authorization_code", "refresh_token", "implicit"],
    **kwargs,
):
    """
    Wraps create_client_action function and cleans up the client and user that
    are created in the database by create_client_action.
    """
    db = db or config["DB"]
    create_client_action(
        db,
        client=client_name,
        username=username,
        urls=urls,
        grant_types=grant_types,
        **kwargs,
    )
    to_test()
    driver = SQLAlchemyDriver(db)
    with driver.session as session:
        client = session.query(Client).filter_by(name=client_name).first()
        user = session.query(User).filter_by(username=username).first()
        if client is not None:
            session.delete(client)
        if user is not None:
            session.delete(user)
        session.commit()
示例#11
0
def modify_client_action(
    DB,
    client=None,
    delete_urls=False,
    urls=None,
    name=None,
    description=None,
    set_auto_approve=False,
    unset_auto_approve=False,
):
    driver = SQLAlchemyDriver(DB)
    with driver.session as s:
        client = s.query(Client).filter(Client.name == client).first()
        if not client:
            raise Exception("client {} does not exist".format(client))
        if urls:
            client._redirect_uris = urls
            print("Changing urls to {}".format(urls))
        if delete_urls:
            client._redirect_uris = None
            print("Deleting urls")
        if set_auto_approve:
            client.auto_approve = True
            print("Auto approve set to True")
        if unset_auto_approve:
            client.auto_approve = False
            print("Auto approve set to False")
        if name:
            client.name = name
            print("Updating name to {}".format(name))
        if description:
            client.description = description
            print("Updating description to {}".format(description))
        s.commit()
示例#12
0
def delete_client_action(DB, client_name):
    import fence.settings

    try:
        cirrus_config.update(**fence.settings.CIRRUS_CFG)
    except AttributeError:
        # no cirrus config, continue anyway. we don't have client service accounts
        # to delete
        pass

    try:
        driver = SQLAlchemyDriver(DB)
        with driver.session as current_session:
            if (not current_session.query(Client).filter(
                    Client.name == client_name).first()):
                raise Exception("client {} does not exist".format(client_name))

            clients = current_session.query(Client).filter(
                Client.name == client_name)

            for client in clients:
                _remove_client_service_accounts(current_session, client)
            clients.delete()
            current_session.commit()

        print("Client {} deleted".format(client_name))
    except Exception as e:
        print(e.message)
示例#13
0
def force_update_google_link(DB, username, google_email):
    """
    WARNING: This function circumvents Google Auth flow, and should only be
    used for internal testing!
    WARNING: This function assumes that a user already has a proxy group!

    Adds user's google account to proxy group and/or updates expiration for
    that google account's access.
    WARNING: This assumes that provided arguments represent valid information.
             This BLINDLY adds without verification. Do verification
             before this.
    Specifically, this ASSUMES that the proxy group provided belongs to the
    given user and that the user has ALREADY authenticated to prove the
    provided google_email is also their's.

    Args:
        DB
        username (str): Username to link with
        google_email (str): Google email to link to

    Raises:
        NotFound: Linked Google account not found
        Unauthorized: Couldn't determine user

    Returns:
        Expiration time of the newly updated google account's access
    """
    import fence.settings

    cirrus_config.update(**fence.settings.CIRRUS_CFG)

    db = SQLAlchemyDriver(DB)
    with db.session as session:
        user_account = session.query(User).filter(
            User.username == username).first()
        if user_account:
            user_id = user_account.id
            proxy_group_id = user_account.google_proxy_group_id
        else:
            raise Unauthorized("Could not determine authed user "
                               "from session. Unable to link Google account.")

        user_google_account = (session.query(UserGoogleAccount).filter(
            UserGoogleAccount.email == google_email).first())
        if not user_google_account:
            user_google_account = add_new_user_google_account(
                user_id, google_email, session)

        now = int(time.time())
        expiration = now + GOOGLE_ACCOUNT_ACCESS_EXPIRES_IN

        force_update_user_google_account_expiration(user_google_account,
                                                    proxy_group_id,
                                                    google_email, expiration,
                                                    session)

        session.commit()

        return expiration
示例#14
0
def admin(app, request, pg_driver_clean):
    private_key = utils.read_file('resources/keys/test_private_key.pem')

    user_driver = SQLAlchemyDriver(PSQL_USER_DB_CONNECTION)
    with user_driver.session as s:
        user = s.query(usermd.User).filter_by(username='******').first()
        token = encoded_jwt(private_key, user)
        return {'Authorization': 'bearer ' + token}
示例#15
0
def list_client_action(db):
    try:
        driver = SQLAlchemyDriver(db)
        with driver.session as s:
            for row in s.query(Client).all():
                pprint.pprint(row.__dict__)
    except Exception as e:
        logger.error(str(e))
示例#16
0
def create_sample_data(DB, yaml_file_path):
    with open(yaml_file_path, "r") as f:
        data = safe_load(f)

    db = SQLAlchemyDriver(DB)
    with db.session as s:
        create_cloud_providers(s, data)
        create_projects(s, data)
        create_group(s, data)
        create_users_with_group(DB, s, data)
示例#17
0
def delete_users(DB, usernames):
    driver = SQLAlchemyDriver(DB)
    with driver.session as session:
        # NOTE that calling ``.delete()`` on the query itself will not follow
        # cascade deletion rules set up in any relationships.
        lowercase_usernames = [x.lower() for x in usernames]
        users_to_delete = (session.query(User).filter(
            func.lower(User.username).in_(lowercase_usernames)).all())
        for user in users_to_delete:
            session.delete(user)
        session.commit()
示例#18
0
def remove_expired_google_service_account_keys(db):
    import fence.settings

    cirrus_config.update(**fence.settings.CIRRUS_CFG)

    db = SQLAlchemyDriver(db)
    with db.session as current_session:
        client_service_accounts = current_session.query(
            GoogleServiceAccount,
            Client).filter(GoogleServiceAccount.client_id == Client.client_id)

        current_time = int(time.time())
        print("Current time: {}\n".format(current_time))

        expired_sa_keys_for_users = current_session.query(
            GoogleServiceAccountKey).filter(
                GoogleServiceAccountKey.expires <= current_time)

        # handle service accounts with default max expiration
        for service_account, client in client_service_accounts:
            with GoogleCloudManager() as g_mgr:
                g_mgr.handle_expired_service_account_keys(
                    service_account.google_unique_id)

            # handle service accounts with custom expiration
            for expired_user_key in expired_sa_keys_for_users:
                sa = (current_session.query(GoogleServiceAccount).filter(
                    GoogleServiceAccount.id ==
                    expired_user_key.service_account_id).first())
                response = g_mgr.delete_service_account_key(
                    account=sa.google_unique_id,
                    key_name=expired_user_key.key_id)
                response_error_code = response.get("error", {}).get("code")

                if not response_error_code:
                    current_session.delete(expired_user_key)
                    print(
                        "INFO: Removed expired service account key {} "
                        "for service account {} (owned by user with id {}).\n".
                        format(expired_user_key.key_id, sa.email, sa.user_id))
                elif response_error_code == 404:
                    print(
                        "INFO: Service account key {} for service account {} "
                        "(owned by user with id {}) does not exist in Google. "
                        "Removing from database...\n".format(
                            expired_user_key.key_id, sa.email, sa.user_id))
                    current_session.delete(expired_user_key)
                else:
                    print("ERROR: Google returned an error when attempting to "
                          "remove service account key {} "
                          "for service account {} (owned by user with id {}). "
                          "Error:\n{}\n".format(expired_user_key.key_id,
                                                sa.email, sa.user_id,
                                                response))
示例#19
0
def modify_client_action(
    DB,
    client=None,
    delete_urls=False,
    urls=None,
    name=None,
    description=None,
    set_auto_approve=False,
    unset_auto_approve=False,
    arborist=None,
    policies=None,
    allowed_scopes=None,
    append=False,
):
    driver = SQLAlchemyDriver(DB)
    with driver.session as s:
        client = s.query(Client).filter(Client.name == client).first()
        if not client:
            raise Exception("client {} does not exist".format(client))
        if urls:
            if append:
                client.redirect_uris += urls
                logger.info("Adding {} to urls".format(urls))
            else:
                client.redirect_uris = urls
                logger.info("Changing urls to {}".format(urls))
        if delete_urls:
            client.redirect_uris = []
            logger.info("Deleting urls")
        if set_auto_approve:
            client.auto_approve = True
            logger.info("Auto approve set to True")
        if unset_auto_approve:
            client.auto_approve = False
            logger.info("Auto approve set to False")
        if name:
            client.name = name
            logger.info("Updating name to {}".format(name))
        if description:
            client.description = description
            logger.info("Updating description to {}".format(description))
        if allowed_scopes:
            if append:
                new_scopes = client._allowed_scopes.split() + allowed_scopes
                client._allowed_scopes = " ".join(new_scopes)
                logger.info(
                    "Adding {} to allowed_scopes".format(allowed_scopes))
            else:
                client._allowed_scopes = " ".join(allowed_scopes)
                logger.info(
                    "Updating allowed_scopes to {}".format(allowed_scopes))
        s.commit()
    if arborist is not None and policies:
        arborist.update_client(client.client_id, policies)
示例#20
0
def user_setup():
    key = Fernet(HMAC_ENCRYPTION_KEY)
    return SQLAlchemyDriver(PSQL_USER_DB_CONNECTION)
    user_driver = SQLAlchemyDriver(PSQL_USER_DB_CONNECTION)
    with user_driver.session as s:
        for username in [
                'admin', 'unauthorized', 'submitter', 'member', 'test'
        ]:
            user = usermd.User(username=username,
                               is_admin=(username == 'admin'))
            keypair = usermd.HMACKeyPair(access_key=username + 'accesskey',
                                         secret_key=key.encrypt(username),
                                         expire=1000000,
                                         user=user)
            s.add(user)
            s.add(keypair)
        users = s.query(usermd.User).all()
        test_user = s.query(
            usermd.User).filter(usermd.User.username == 'test').first()
        test_user.is_admin = True
        projects = ['phs000218', 'phs000235', 'phs000178']
        admin = s.query(
            usermd.User).filter(usermd.User.username == 'admin').first()
        admin.is_admin = True
        user = s.query(
            usermd.User).filter(usermd.User.username == 'submitter').first()
        member = s.query(
            usermd.User).filter(usermd.User.username == 'member').first()
        for phsid in projects:
            p = usermd.Project(name=phsid, auth_id=phsid)
            ua = usermd.AccessPrivilege(user=user,
                                        project=p,
                                        privilege=roles.values())
            s.add(ua)
            ua = usermd.AccessPrivilege(user=member,
                                        project=p,
                                        privilege=['_member_'])
            s.add(ua)

    return user_driver
示例#21
0
def remove_expired_google_accounts_from_proxy_groups(db):
    cirrus_config.update(**config["CIRRUS_CFG"])

    db = SQLAlchemyDriver(db)
    with db.session as current_session:
        current_time = int(time.time())
        logger.info("Current time: {}".format(current_time))

        expired_accounts = current_session.query(UserGoogleAccountToProxyGroup).filter(
            UserGoogleAccountToProxyGroup.expires <= current_time
        )

        with GoogleCloudManager() as g_mgr:
            for expired_account_access in expired_accounts:
                g_account = (
                    current_session.query(UserGoogleAccount)
                    .filter(
                        UserGoogleAccount.id
                        == expired_account_access.user_google_account_id
                    )
                    .first()
                )
                try:
                    response = g_mgr.remove_member_from_group(
                        member_email=g_account.email,
                        group_id=expired_account_access.proxy_group_id,
                    )
                    response_error_code = response.get("error", {}).get("code")

                    if not response_error_code:
                        current_session.delete(expired_account_access)
                        logger.info(
                            "INFO: Removed {} from proxy group with id {}.\n".format(
                                g_account.email, expired_account_access.proxy_group_id
                            )
                        )
                    else:
                        logger.error(
                            "ERROR: Google returned an error when attempting to "
                            "remove member {} from proxy group {}. Error:\n{}\n".format(
                                g_account.email,
                                expired_account_access.proxy_group_id,
                                response,
                            )
                        )
                except Exception as exc:
                    logger.error(
                        "ERROR: Google returned an error when attempting to "
                        "remove member {} from proxy group {}. Error:\n{}\n".format(
                            g_account.email, expired_account_access.proxy_group_id, exc
                        )
                    )
示例#22
0
    def __init__(
        self,
        dbGaP,
        DB,
        project_mapping,
        storage_credentials=None,
        db_session=None,
        is_sync_from_dbgap_server=False,
        sync_from_local_csv_dir=None,
        sync_from_local_yaml_file=None,
        arborist=None,
    ):
        """
        Syncs ACL files from dbGap to auth database and storage backends
        Args:
            dbGaP: a dict containing creds to access dbgap sftp
            DB: database connection string
            project_mapping: a dict containing how dbgap ids map to projects
            storage_credentials: a dict containing creds for storage backends
            sync_from_dir: path to an alternative dir to sync from instead of
                           dbGaP
            arborist:
                base URL for arborist service if the syncer should also create
                resources in arborist
        """
        self.sync_from_local_csv_dir = sync_from_local_csv_dir
        self.sync_from_local_yaml_file = sync_from_local_yaml_file
        self.is_sync_from_dbgap_server = is_sync_from_dbgap_server
        if is_sync_from_dbgap_server:
            self.server = dbGaP["info"]
            self.protocol = dbGaP["protocol"]
            self.dbgap_key = dbGaP["decrypt_key"]
        self.parse_consent_code = dbGaP.get("parse_consent_code", True)
        self.session = db_session
        self.driver = SQLAlchemyDriver(DB)
        self.project_mapping = project_mapping or {}
        self._projects = dict()
        self.logger = get_logger(
            "user_syncer",
            log_level="debug" if config["DEBUG"] == True else "info")

        self.arborist_client = None
        if arborist:
            self.arborist_client = ArboristClient(arborist_base_url=arborist,
                                                  logger=self.logger)

        if storage_credentials:
            self.storage_manager = StorageManager(storage_credentials,
                                                  logger=self.logger)
示例#23
0
文件: __init__.py 项目: rolinge/fence
def app_sessions(app):
    app.url_map.strict_slashes = False
    app.db = SQLAlchemyDriver(config["DB"])

    # TODO: we will make a more robust migration system external from the application
    #       initialization soon
    if config["ENABLE_DB_MIGRATION"]:
        logger.info("Running database migration...")
        migrate(app.db)
        logger.info("Done running database migration.")
    else:
        logger.info("NOT running database migration.")

    session = flask_scoped_session(app.db.Session, app)  # noqa
    app.session_interface = UserSessionInterface()
示例#24
0
def create_client(
    username,
    urls,
    DB,
    name="",
    description="",
    auto_approve=False,
    is_admin=False,
    grant_types=None,
    confidential=True,
):
    grant_types = grant_types
    driver = SQLAlchemyDriver(DB)
    client_id = random_str(40)
    client_secret = None
    hashed_secret = None
    if confidential:
        client_secret = random_str(55)
        hashed_secret = bcrypt.hashpw(client_secret, bcrypt.gensalt())
    auth_method = "client_secret_basic" if confidential else "none"
    with driver.session as s:
        user = query_for_user(session=s, username=username)

        if not user:
            user = User(username=username, is_admin=is_admin)
            s.add(user)
        if s.query(Client).filter(Client.name == name).first():
            raise Exception("client {} already exists".format(name))
        client = Client(
            client_id=client_id,
            client_secret=hashed_secret,
            user=user,
            redirect_uris=urls,
            _allowed_scopes=" ".join(config["CLIENT_ALLOWED_SCOPES"]),
            description=description,
            name=name,
            auto_approve=auto_approve,
            grant_types=grant_types,
            is_confidential=confidential,
            token_endpoint_auth_method=auth_method,
        )
        s.add(client)
        s.commit()
    return client_id, client_secret
示例#25
0
def verify_bucket_access_group(DB):
    """
    Go through all the google group members, remove them from Google group and Google
    user service account if they are not in Fence

    Args:
        DB(str): db connection string

    Returns:
        None

    """
    cirrus_config.update(**config["CIRRUS_CFG"])

    driver = SQLAlchemyDriver(DB)
    with driver.session as session:
        access_groups = session.query(GoogleBucketAccessGroup).all()
        with GoogleCloudManager() as manager:
            for access_group in access_groups:
                try:
                    members = manager.get_group_members(access_group.email)
                    logger.debug(f"google group members response: {members}")
                except GoogleAuthError as e:
                    logger.error("ERROR: Authentication error!!!. Detail {}".format(e))
                    return
                except Exception as e:
                    logger.error(
                        "ERROR: Could not list group members of {}. Detail {}".format(
                            access_group.email, e
                        )
                    )
                    return

                for member in members:
                    if member.get("type") == "GROUP":
                        _verify_google_group_member(session, access_group, member)
                    elif member.get("type") == "USER":
                        _verify_google_service_account_member(
                            session, access_group, member
                        )
示例#26
0
    def create_access_token(self):
        """
        Create a new access token.

        Return:
            JWTResult: result containing the encoded token and claims
        """
        driver = SQLAlchemyDriver(self.db)
        with driver.session as current_session:
            user = (current_session.query(User).filter(
                func.lower(User.username) == self.username.lower()).first())
            if not user:
                raise EnvironmentError("no user found with given username: " +
                                       self.username)
            return generate_signed_access_token(
                self.kid,
                self.private_key,
                user,
                self.expires_in,
                self.scopes,
                iss=self.base_url,
            )
示例#27
0
def app_sessions(app):
    app.url_map.strict_slashes = False
    app.db = SQLAlchemyDriver(app.config['DB'])
    migrate(app.db)
    session = flask_scoped_session(app.db.Session, app)  # noqa
    app.jinja_env.globals['csrf_token'] = generate_csrf_token
    app.storage_manager = StorageManager(
        app.config['STORAGE_CREDENTIALS'],
        logger=app.logger
    )
    enabled_idp_ids = (
        fence.settings
        .ENABLED_IDENTITY_PROVIDERS['providers']
        .keys()
    )
    # Add OIDC client for Google if configured.
    configured_google = (
        'OPENID_CONNECT' in app.config
        and 'google' in app.config['OPENID_CONNECT']
        and 'google' in enabled_idp_ids
    )
    if configured_google:
        app.google_client = GoogleClient(
            app.config['OPENID_CONNECT']['google'],
            HTTP_PROXY=app.config.get('HTTP_PROXY'),
            logger=app.logger
        )
    # Add OIDC client for multi-tenant fence if configured.
    configured_fence = (
        'OPENID_CONNECT' in app.config
        and 'fence' in app.config['OPENID_CONNECT']
        and 'fence' in enabled_idp_ids
    )
    if configured_fence:
        app.fence_client = OAuthClient(**app.config['OPENID_CONNECT']['fence'])
    app.session_interface = UserSessionInterface()
示例#28
0
def app_sessions(app):
    app.url_map.strict_slashes = False
    app.db = SQLAlchemyDriver(config["DB"])
    migrate(app.db)
    session = flask_scoped_session(app.db.Session, app)  # noqa
    app.session_interface = UserSessionInterface()
示例#29
0
def user_teardown():
    user_driver = SQLAlchemyDriver(PSQL_USER_DB_CONNECTION)
    with user_driver.session as session:
        meta = usermd_base.metadata
        for table in reversed(meta.sorted_tables):
            session.execute(table.delete())
示例#30
0
def link_bucket_to_project(db, bucket_id, bucket_provider, project_auth_id):
    """
    Associate a bucket to a specific project (with provided auth_id).

    Args:
        db (TYPE): database
        bucket_id (str): bucket db id or unique name
            WARNING: name uniqueness is only required for Google so it's not
                     a requirement of the db table. You will get an error if
                     there are multiple buckets with the given name. In that
                     case, you'll have to use the bucket's id.
        bucket_provider (str): CloudProvider.name for the bucket
        project_auth_id (str): Project.auth_id to link to bucket
    """
    driver = SQLAlchemyDriver(db)
    with driver.session as current_session:
        cloud_provider = (
            current_session.query(CloudProvider).filter_by(name=bucket_provider).first()
        )
        if not cloud_provider:
            raise NameError(
                'No bucket with provider "{}" exists.'.format(bucket_provider)
            )

        # first try by searching using id
        try:
            bucket_id = int(bucket_id)
            bucket_db_entry = (
                current_session.query(Bucket).filter_by(
                    id=bucket_id, provider_id=cloud_provider.id
                )
            ).first()
        except ValueError:
            # invalid id, must be int
            bucket_db_entry = None

        # nothing found? try searching for single bucket with name bucket_id
        if not bucket_db_entry:
            buckets_by_name = current_session.query(Bucket).filter_by(
                name=bucket_id, provider_id=cloud_provider.id
            )
            # don't get a bucket if the name isn't unique. NOTE: for Google,
            # these have to be globally unique so they'll be unique here.
            buckets_with_name = buckets_by_name.count()
            if buckets_with_name == 1:
                bucket_db_entry = buckets_by_name[0]
            elif buckets_with_name > 1:
                raise NameError(
                    'No bucket with id "{bucket_id}" exists. Tried buckets '
                    'with name "{bucket_id}", but this returned multiple '
                    "buckets. Please specify the id from the db and not just "
                    "the name.".format(bucket_id=bucket_id)
                )
            else:
                # keep bucket_db_entry as None
                pass

        if not bucket_db_entry:
            raise NameError('No bucket with id or name "{}" exists.'.format(bucket_id))

        project_db_entry = (
            current_session.query(Project).filter_by(auth_id=project_auth_id).first()
        )
        if not project_db_entry:
            logger.warning(
                'WARNING: No project with auth_id "{}" exists. Creating...'.format(
                    project_auth_id
                )
            )
            project_db_entry = Project(name=project_auth_id, auth_id=project_auth_id)
            current_session.add(project_db_entry)
            current_session.commit()

        # Add StorageAccess if it doesn't exist for the project
        storage_access = (
            current_session.query(StorageAccess)
            .filter_by(project_id=project_db_entry.id, provider_id=cloud_provider.id)
            .first()
        )
        if not storage_access:
            storage_access = StorageAccess(
                project_id=project_db_entry.id, provider_id=cloud_provider.id
            )
            current_session.add(storage_access)
            current_session.commit()

        project_linkage = (
            current_session.query(ProjectToBucket)
            .filter_by(project_id=project_db_entry.id, bucket_id=bucket_db_entry.id)
            .first()
        )
        if not project_linkage:
            project_linkage = ProjectToBucket(
                project_id=project_db_entry.id,
                bucket_id=bucket_db_entry.id,
                privilege=["owner"],  # TODO What should this be???
            )
            current_session.add(project_linkage)
            current_session.commit()