Example #1
0
    def _credential_init(self):
        logger.info('Bootstrapping credentials')

        # credential bootstrap
        self.global_configuration['system_user_auth'] = (None, None)

        if self.require_system_user:
            gotauth = False
            max_retries = 60
            for count in range(1, max_retries):
                try:
                    with session_scope() as dbsession:
                        mgr = manager_factory.for_session(dbsession)
                        self.global_configuration['system_user_auth'] = mgr.get_system_credentials()

                    if self.global_configuration['system_user_auth'] != (None, None):
                        gotauth = True
                        break
                    else:
                        logger.error('cannot get system user auth credentials yet, retrying (' + str(count) + ' / ' + str(max_retries) + ')')
                        time.sleep(5)
                except Exception as err:
                    logger.exception('cannot get system-user auth credentials - service may not have system level access')
                    self.global_configuration['system_user_auth'] = (None, None)
                    gotauth = False

            if not gotauth:
                raise Exception('service requires system user auth to start')

        logger.info('Credential initialization complete')
Example #2
0
def list_user_credentials(accountname, username):
    """
    GET /accounts/{accountname}/users/{username}/credentials

    :param username:
    :return:
    """

    try:
        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            usr = verify_user(username, accountname, mgr)
            cred = usr["credentials"].get(UserAccessCredentialTypes.password)
            if cred is None:
                return [], 200
            else:
                cred = credential_db_to_msg(cred)
                return [cred], 200
    except UserNotFoundError as ex:
        return make_response_error("User not found", in_httpcode=404), 404
    except AccountNotFoundError as ex:
        return make_response_error("Account not found", in_httpcode=404), 404
    except Exception as ex:
        logger.exception("Api Error")
        return make_response_error(errmsg=str(ex), in_httpcode=500), 500
Example #3
0
def delete_user(accountname, username):
    """
    DELETE /accounts/{accountname}/users/{username}

    :param accountname:
    :param username: the user to delete
    :return:
    """

    try:
        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            verify_user(username, accountname, mgr)

            if ApiRequestContextProxy.identity().username == username:
                return make_response_error(
                    'Cannot delete credential used for authentication of the request',
                    in_httpcode=400), 400

            if mgr.delete_user(username):
                return None, 204
            else:
                return make_response_error(
                    'Failed to delete user: {}'.format(username),
                    in_httpcode=500), 500
    except (UserNotFoundError, AccountNotFoundError):
        return make_response_error('User not found', in_httpcode=404), 404
    except Exception as e:
        logger.exception('API Error')
        return make_response_error(
            'Internal error deleting user {}'.format(username),
            in_httpcode=500), 500
Example #4
0
def user_account_upgrades_007_008():
    logger.info('Upgrading user accounts for multi-user support')

    from anchore_engine.db import session_scope, legacy_db_users
    from anchore_engine.subsys.identities import manager_factory, AccountStates
    from anchore_engine.configuration.localconfig import SYSTEM_ACCOUNT_NAME, ADMIN_ACCOUNT_NAME

    with session_scope() as session:
        mgr = manager_factory.for_session(session)
        for user in legacy_db_users.get_all():

            if user['userId'] == ADMIN_ACCOUNT_NAME:
                account_type = identities.AccountTypes.admin
            elif user['userId'] == SYSTEM_ACCOUNT_NAME:
                account_type = identities.AccountTypes.service
            else:
                account_type = identities.AccountTypes.user

            logger.info('Migrating user: {} to new account with name {}, type {}, is_active {}'.format(user['userId'], user['userId'], account_type, user['active']))
            accnt = mgr.create_account(account_name=user['userId'], email=user['email'], account_type=account_type)
            if not user['active']:
                mgr.update_account_state(accnt['name'], AccountStates.disabled)

            logger.info('Creating new user record in new account {} with username {}'.format(user['userId'], user['userId']))
            mgr.create_user(account_name=user['userId'], username=user['userId'], password=user['password'])

            logger.info('Deleting old user record')
            legacy_db_users.delete(user['userId'], session)

    logger.info('User account upgrade complete')
Example #5
0
def create_user(accountname, user):
    """
    POST /accounts/{accountname}/users

    :param accountname:
    :param user:
    :return:
    """

    try:
        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            verify_account(accountname, mgr)
            usr = mgr.create_user(
                account_name=accountname,
                username=user['username'],
                creator_name=ApiRequestContextProxy.identity().username,
                password=user['password'])
            return user_db_to_msg(usr), 200
    except UserAlreadyExistsError as ex:
        return make_response_error('User already exists', in_httpcode=400), 400
    except AccountNotFoundError as ex:
        return make_response_error('Account not found', in_httpcode=404), 404
    except Exception as e:
        logger.exception('API Error')
        return make_response_error(
            'Internal error deleting account {}'.format(accountname)), 500
Example #6
0
def activate_account(accountname):
    """
    POST /accounts/{accountname}/activate

    idempotently activate an account

    :param accountname: str account name to activate
    :return: account json object
    """

    try:
        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            verify_account(accountname, mgr)

            result = mgr.activate_account(accountname)
            if result:
                return account_db_to_status_msg(result), 200
            else:
                return make_response_error('Error updating account state'), 500
    except AccountNotFoundError as ex:
        return make_response_error('Account not found', in_httpcode=404), 404
    except Exception as e:
        logger.exception('API Error')
        return make_response_error('Error activating account',
                                   in_httpcode=500), 500
Example #7
0
def list_users(accountname):
    """
    GET /accounts/{accountname}/users

    :param account:
    :return:
    """

    try:

        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            verify_account(accountname, mgr)

            users = mgr.list_users(accountname)
            if users is None:
                return make_response_error("No such account",
                                           in_httpcode=404), 404

            response = list(map(user_db_to_msg, users))
            return response, 200
    except AccountNotFoundError as ex:
        return make_response_error("Account not found", in_httpcode=404), 404
    except Exception as e:
        logger.exception("API Error")
        return make_response_error("Error listing account users",
                                   in_httpcode=500), 500
Example #8
0
def update_account_state(accountname, desired_state):
    """
    POST /accounts/{accountname}/state

    Body: {"state": "enabled"|"disabled"}

    :param accountname: str account name to update
    :param desired_state: json object for desired state to set
    :return: account json object
    """

    try:
        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            verify_account(accountname, mgr)
            result = mgr.update_account_state(
                accountname, AccountStates(desired_state.get("state")))
            if result:
                return account_db_to_status_msg(result), 200
            else:
                return make_response_error("Error updating account state"), 500
    except (InvalidStateError, DisableAdminAccountError) as ex:
        return make_response_error(str(ex), in_httpcode=400), 400
    except AccountNotFoundError as ex:
        return make_response_error("Account not found", in_httpcode=404), 404
    except Exception as e:
        logger.exception("API Error")
        return make_response_error("Error updating account state",
                                   in_httpcode=500), 500
Example #9
0
def create_user_credential(accountname, username, credential):
    """
    POST /accounts/{accountname}/users/{username}/credentials
    :param accountname: str account id for account account record
    :param username: str username
    :param credential: json object of the credential type
    :return: credential json object
    """

    try:
        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            usr = mgr.get_user(username)
            if not usr or usr['account_name'] != accountname:
                return make_response_error('Username not found in account'), 404

            # For now, only support passwords via the api
            if credential['type'] != 'password':
                return make_response_error('Invalid credential type'), 400

            if not credential.get('value'):
                return make_response_error('Invalid credential value, must be non-null and non-empty'), 400

            try:
                cred_type = UserAccessCredentialTypes(credential['type'])
            except:
                return make_response_error(errmsg='Invalid credential type'), 400

            cred = mgr.add_user_credential(session, creator_name=ApiRequestContextProxy.user(), username=username, credential_type=cred_type, value=credential['value'])

            return credential_db_to_msg(cred), 200
    except Exception as ex:
        logger.exception('API Error')
        return make_response_error(errmsg=str(ex)), 500
Example #10
0
def delete_user(accountname, username):
    """
    DELETE /accounts/{accountname}/users/{username}

    :param accountname:
    :param username: the user to delete
    :return:
    """

    try:
        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            usr = verify_user(username, accountname, mgr)
            if not can_delete_user(usr):
                return make_response_error('User not allowed to be deleted due to system constraints', in_httpcode=400), 400
            elif ApiRequestContextProxy.identity().username == username:
                return make_response_error('Cannot delete credential used for authentication of the request', in_httpcode=400), 400
            else:
                if mgr.delete_user(username):
                    # Flush from authz system if necessary, will rollback if this fails, but rely on the db state checks first to gate this
                    authorizer.notify(NotificationTypes.principal_deleted, username)

                    return None, 204
                else:
                    return make_response_error('Failed to delete user: {}'.format(username), in_httpcode=500), 500
    except (UserNotFoundError, AccountNotFoundError):
        return make_response_error('User not found', in_httpcode=404), 404
    except Exception as e:
        logger.exception('API Error')
        return make_response_error('Internal error deleting user {}'.format(username), in_httpcode=500), 500
Example #11
0
def delete_user(accountname, username):
    """
    DELETE /accounts/{accountname}/users/{username}

    :param accountname:
    :param username: the user to delete
    :return:
    """

    try:
        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            if request.authorization.accountname == accountname:
                return make_response_error('Cannot delete credential used for authentication of the request'), 400

            user = mgr.get_user(username)
            if user['account_name'] != accountname:
                return make_response_error('username {} not valid for account {}'.format(username, accountname)), 404

            if mgr.delete_user(username):
                return '', 200
            else:
                return make_response_error('Failed to delete credential: {}'.format(accountname)), 500
    except Exception as ex:
        logger.exception('API Error')
        return make_response_error(errmsg=str(ex)), 500
Example #12
0
def list_accounts(state=None):
    """
    GET /accounts

    :param active:
    :return:
    """

    try:
        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            if state is not None:
                try:
                    state = AccountStates(state)
                except:
                    return (
                        make_response_error(
                            "Bad Request: state {} not a valid value",
                            in_httpcode=400),
                        400,
                    )

            response = mgr.list_accounts(with_state=state)

            return list(map(account_db_to_msg, response)), 200
    except Exception as ex:
        logger.exception("API Error")
        return make_response_error("Error listing accounts",
                                   in_httpcode=500), 500
Example #13
0
def create_account(account):
    """
    POST /accounts

    :param account:
    :return:
    """

    try:
        if account.get('type') != AccountTypes.user.value:
            return make_response_error(
                'Invalid account type: {}. Only valid value is "user"'.format(
                    account.get('type')),
                in_httpcode=400), 400

        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            resp = mgr.create_account(
                account_name=account['name'],
                account_type=account.get('type', AccountTypes.user.value),
                email=account.get('email'),
                creator=ApiRequestContextProxy.identity().username)
        return account_db_to_msg(resp), 200
    except AccountAlreadyExistsError as ex:
        return make_response_error(errmsg='Account already exists',
                                   in_httpcode=400), 400
    except Exception as ex:
        logger.exception('Unexpected Error creating account')
        return make_response_error('Error creating account',
                                   in_httpcode=500), 500
Example #14
0
def delete_user_credential(accountname, username, credential_type):
    """
    DELETE /accounts/{accountname}/users/{username}/credentials?credential_type=password
    :param username:
    :param credential_type:
    :return:
    """

    if not credential_type:
        return make_response_error('credential type must be specified',
                                   in_httpcode=400), 400

    try:
        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            usr = verify_user(username, accountname, mgr)
            if credential_type != 'password':
                return make_response_error('Invalid credential type',
                                           in_httpcode=400), 400

            if username == ApiRequestContextProxy.identity().username:
                return make_response_error(
                    'Cannot delete credential of authenticated user',
                    in_httpcode=400), 400

            resp = mgr.delete_user_credential(username, credential_type)
            return None, 204
    except UserNotFoundError as ex:
        return make_response_error('User not found', in_httpcode=404), 404
    except AccountNotFoundError as ex:
        return make_response_error('Account not found', in_httpcode=404), 404
    except Exception as ex:
        logger.exception('Api Error')
        return make_response_error(errmsg=str(ex), in_httpcode=500), 500
Example #15
0
def create_user(accountname, user):
    """
    POST /accounts/{accountname}/users

    :param accountname:
    :param user:
    :return:
    """

    try:

        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            verify_account(accountname, mgr)

            try:
                usr = mgr.create_user(account_name=accountname,
                                      username=user['username'],
                                      password=user['password'])
            except ValueError as ex:
                return make_response_error('Validation failed: {}'.format(ex),
                                           in_httpcode=400), 400

            # Flush from authz system if necessary, will rollback if this fails, but rely on the db state checks first to gate this
            authorizer.notify(NotificationTypes.principal_created,
                              usr['username'])

            return user_db_to_msg(usr), 200
    except UserAlreadyExistsError as ex:
        return make_response_error('User already exists', in_httpcode=400), 400
    except AccountNotFoundError as ex:
        return make_response_error('Account not found', in_httpcode=404), 404
    except Exception as e:
        logger.exception('API Error')
        return make_response_error('Internal error adding user'), 500
Example #16
0
def create_account(account):
    """
    POST /accounts

    :param account:
    :return:
    """

    try:
        try:
            can_create_account(account)
        except ValueError as ex:
            return make_response_error('Invalid account request: {}'.format(
                ex.args[0]),
                                       in_httpcode=400), 400
        except Exception as ex:
            logger.exception('Unexpected exception in account validation')
            return make_response_error('Invalid account request',
                                       in_httpcode=400), 400

        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            try:
                resp = mgr.create_account(account_name=account['name'],
                                          account_type=account.get(
                                              'type', AccountTypes.user.value),
                                          email=account.get('email'))
            except ValueError as ex:
                return make_response_error('Validation failed: {}'.format(ex),
                                           in_httpcode=400), 400

            authorizer.notify(NotificationTypes.domain_created,
                              account['name'])

            # Initialize account stuff
            try:
                _init_policy(account['name'], config=get_config())
            except Exception:
                logger.exception(
                    'Could not initialize policy bundle for new account: {}'.
                    format(account['name']))
                raise

        return account_db_to_msg(resp), 200
    except AccountAlreadyExistsError as ex:
        return make_response_error(errmsg='Account already exists',
                                   in_httpcode=400), 400
    except Exception as ex:
        logger.exception('Unexpected Error creating account')
        return make_response_error('Error creating account',
                                   in_httpcode=500), 500
Example #17
0
def delete_account(accountname):
    """
    DELETE /account/{accountname}

    :param accountname:
    :return:
    """

    try:

        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            account = verify_account(accountname, mgr)
            if not can_delete_account(account):
                return (
                    make_response_error("Account cannot be deleted",
                                        in_httpcode=400),
                    400,
                )
            else:
                account = mgr.update_account_state(accountname,
                                                   AccountStates.deleting)

                # Flush from authz system if necessary
                authorizer.notify(NotificationTypes.domain_deleted,
                                  accountname)

                users = mgr.list_users(accountname)
                for user in users:
                    # Flush users
                    logger.debug(
                        "Deleting account user {} on authz system if using plugin"
                        .format(user["username"]))
                    authorizer.notify(NotificationTypes.principal_deleted,
                                      user["username"])

                    logger.debug("Deleting account user: {}".format(
                        user["username"]))
                    mgr.delete_user(user["username"])

            return account_db_to_status_msg(account), 200
    except InvalidStateError as ex:
        return make_response_error(str(ex), in_httpcode=400), 400
    except AccountNotFoundError as ex:
        return make_response_error("Account not found", in_httpcode=404), 404
    except Exception as e:
        logger.exception("API Error")
        return make_response_error("Error deleting account",
                                   in_httpcode=500), 500
Example #18
0
def get_users_account():
    """
    GET /account

    :return:
    """

    try:
        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            account = mgr.get_account(ApiRequestContextProxy.namespace())
            return account_db_to_msg(account), 200
    except Exception as ex:
        logger.exception("API Error")
        return make_response_error(errmsg=str(ex)), 500
Example #19
0
def delete_user_credential(accountname, username, credential_type, uuid):
    """
    DELETE /accounts/{accountname}/users/{username}/credentials?uuid
    :param username:
    :param credential_type:
    :return:
    """
    try:
        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            resp = mgr.delete_user_credential(username, credential_type)
            return resp, 200
    except Exception as ex:
        logger.exception('API Error')
        return make_response_error(errmsg=str(ex)), 500
Example #20
0
def create_user_credential(accountname, username, credential):
    """
    POST /accounts/{accountname}/users/{username}/credentials
    :param accountname: str account id for account account record
    :param username: str username
    :param credential: json object of the credential type
    :return: credential json object
    """

    try:
        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            user = verify_user(username, accountname, mgr)

            if user['type'] != UserTypes.native:
                return make_response_error(
                    "Users with type other than 'native' cannot have password credentials",
                    in_httpcode=400), 400

            # For now, only support passwords via the api
            if credential['type'] != 'password':
                return make_response_error('Invalid credential type',
                                           in_httpcode=404), 404

            if not credential.get('value'):
                return make_response_error(
                    'Invalid credential value, must be non-null and non-empty',
                    in_httpcode=400), 400

            try:
                cred_type = UserAccessCredentialTypes(credential['type'])
            except:
                return make_response_error(errmsg='Invalid credential type',
                                           in_httpcode=400), 400

            cred = mgr.add_user_credential(username=username,
                                           credential_type=cred_type,
                                           value=credential['value'])

            return credential_db_to_msg(cred), 200
    except UserNotFoundError as ex:
        return make_response_error('User not found', in_httpcode=404), 404
    except AccountNotFoundError as ex:
        return make_response_error('Account not found', in_httpcode=404), 404
    except Exception as e:
        logger.exception('API Error')
        return make_response_error(
            'Internal error creating credential {}'.format(accountname)), 500
Example #21
0
def create_user(accountname, user):
    """
    POST /accounts/{accountname}/users

    :param accountname:
    :param user:
    :return:
    """
    try:
        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            usr = mgr.create_user(account_name=accountname, username=user['username'], creator_name=ApiRequestContextProxy.user(), password=user['password'])
            return user_db_to_msg(usr), 200
    except Exception as ex:
        logger.exception('API Error')
        return make_response_error(errmsg=str(ex)), 500
Example #22
0
def get_test_notification(notification_type, request_inputs):
    """
    Build a test notification payload (format should mirror what's returned by get_webhook_schema)
    :param notification_type: type of notification to send
    :param request_inputs: metadata from request to test webhook
    """

    with db.session_scope() as dbsession:
        mgr = manager_factory.for_session(dbsession)
        notification = notifications.Notification(notification_type,
                                                  request_inputs['userId'],
                                                  mgr.get_account(request_inputs['userId'])['email'])

    logger.debug("Test Notification JSON: {}".format(notification.to_json()))

    return notification
Example #23
0
def get_account(accountname):
    """
    GET /accounts/{accountname}

    :param accountname:
    :return:
    """

    try:
        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            account = mgr.get_account(accountname)
            return account_db_to_msg(account), 200
    except Exception as ex:
        logger.exception('API Error')
        return make_response_error(errmsg=str(ex)), 500
Example #24
0
def internal_client_for(internal_client_cls, userId):
    """
    Return an initialized  internal service client for the given userId (namespace)

    :param cls:
    :param userId:
    :param session:
    :return:
    """

    with session_scope() as session:
        mgr = manager_factory.for_session(session=session)
        credential = mgr.get_system_credentials()

        if credential is None:
            raise Exception('No cached system credentials found')

        return internal_client_cls(credential=credential, as_account=userId)
Example #25
0
def internal_client_for(internal_client_cls, userId):
    """
    Return an initialized  internal service client for the given userId (namespace)

    :param cls:
    :param userId:
    :param session:
    :return:
    """
    mgr = manager_factory.for_session(session=None)
    sysuser, syspass = mgr.get_system_credentials()

    if sysuser is None:
        raise Exception('No cached system credentials found')

    return internal_client_cls(user=sysuser,
                               password=syspass,
                               as_account=userId)
Example #26
0
def deactivate_account(accountname):
    """
    POST /accounts/{accountname}/deactivate
    :param accountname: str account Id to deactivate
    :return: account json object
    """

    try:
        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            result = mgr.deactivate_account(accountname)
            if result:
                return account_db_to_status_msg(result), 200
            else:
                return make_response_error('Error updating account state', ), 500
    except Exception as ex:
        logger.exception('API Error')
        return make_response_error(errmsg=str(ex)), 500
Example #27
0
def get_account(accountname):
    """
    GET /accounts/{accountname}

    :param accountname:
    :return:
    """

    try:
        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            account = verify_account(accountname, mgr)
            return account_db_to_msg(account), 200
    except AccountNotFoundError as ex:
        return make_response_error('Account not found', in_httpcode=404), 404
    except Exception as ex:
        logger.exception('API Error')
        return make_response_error('Error getting account',
                                   in_httpcode=500), 500
Example #28
0
def delete_account(accountname):
    """
    DELETE /account/{accountname}

    :param accountname:
    :return:
    """

    try:
        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            account = verify_account(accountname, mgr)
            resp = mgr.delete_account(accountname)
            return None, 204
    except AccountNotFoundError as ex:
        return make_response_error('Account not found', in_httpcode=404), 404
    except Exception as e:
        logger.exception('API Error')
        return make_response_error('Error deleting account',
                                   in_httpcode=500), 500
Example #29
0
def delete_account(accountname):
    """
    DELETE /account/{accountname}

    :param accountname:
    :return:
    """

    try:
        with session_scope() as session:
            mgr = manager_factory.for_session(session)

            try:
                resp = mgr.delete_account(accountname)
                return '', 200
            except Exception as e:
                return make_response_error('Internal error deleting account {}'.format(accountname), ), 500
    except Exception as ex:
        logger.exception('API Error')
        return make_response_error(errmsg=str(ex)), 500
Example #30
0
def list_users(accountname):
    """
    GET /accounts/{accountname}/users

    :param account:
    :return:
    """

    try:
        with session_scope() as session:
            mgr = manager_factory.for_session(session)
            users = mgr.list_users(accountname)
            if users is None:
                return make_response_error('No such account'), 404

            response = list(map(user_db_to_msg, users))
            return response, 200
    except Exception as ex:
        logger.exception('API Error')
        return make_response_error(errmsg=str(ex)), 500