예제 #1
0
 def run(self):
     grants = keymanager.get_grants()
     try:
         roles = [x for x in iam.roles.all()]
     except ClientError:
         log.error('Failed to fetch IAM roles.')
         return
     services = []
     for service in Service.data_type_date_index.query('service'):
         services.append(service.id)
     for role in roles:
         if role.name in services:
             log.info('Managing grants for {0}.'.format(role.name))
             keymanager._ensure_grants(role, grants)
     log.info('Finished managing grants.')
예제 #2
0
 def run(self):
     grants = keymanager.get_grants()
     try:
         roles = [x for x in iam.roles.all()]
     except ClientError:
         log.error('Failed to fetch IAM roles.')
         return
     services = []
     for service in Service.data_type_date_index.query('service'):
         services.append(service.id)
     for role in roles:
         if role.name in services:
             log.info('Managing grants for {0}.'.format(role.name))
             keymanager._ensure_grants(role, grants)
     log.info('Finished managing grants.')
예제 #3
0
def ensure_grants(id):
    try:
        _service = Service.get(id)
        if _service.data_type != 'service':
            msg = 'id provided is not a service.'
            return jsonify({'error': msg}), 400
    except Service.DoesNotExist:
        msg = 'id provided does not exist.'
        return jsonify({'error': msg}), 400
    try:
        keymanager.ensure_grants(id)
    except keymanager.ServiceCreateGrantError:
        msg = 'Failed to add grants for service.'
        log.error(msg)
        return jsonify({'error': msg}), 400
    try:
        grants = keymanager.grants_exist(id)
    except keymanager.ServiceGetGrantError:
        msg = 'Failed to get grants.'
        return jsonify({'error': msg}), 500
    return jsonify({'id': id, 'grants': grants})
예제 #4
0
파일: v1.py 프로젝트: rsk-project/confidant
def ensure_grants(id):
    try:
        _service = Service.get(id)
        if _service.data_type != 'service':
            msg = 'id provided is not a service.'
            return jsonify({'error': msg}), 400
    except Service.DoesNotExist:
        msg = 'id provided does not exist.'
        return jsonify({'error': msg}), 400
    try:
        keymanager.ensure_grants(id)
    except keymanager.ServiceCreateGrantError:
        msg = 'Failed to add grants for service.'
        log.error(msg)
        return jsonify({'error': msg}), 400
    try:
        grants = keymanager.grants_exist(id)
    except keymanager.ServiceGetGrantError:
        msg = 'Failed to get grants.'
        return jsonify({'error': msg}), 500
    return jsonify({
        'id': id,
        'grants': grants
    })
예제 #5
0
    def decorated(*args, **kwargs):
        if not app.config.get('USE_AUTH'):
            return f(*args, **kwargs)

        auth = request.authorization
        headers = request.headers
        using_basic_kms_auth = (auth and auth.get('username')
                                and auth.get('password') != '')
        using_kms_auth = ('X-Auth-Token' in headers
                          and 'X-Auth-From' in headers)

        # User suppplied basic auth info
        if using_basic_kms_auth or using_kms_auth:
            if using_basic_kms_auth:
                _from = auth['username']
                token = auth['password']
            else:
                _from = headers['X-Auth-From']
                token = headers['X-Auth-Token']
            try:
                with stats.timer('decrypt_token'):
                    payload = keymanager.decrypt_token(token, _from)
                log.debug('Auth request had the following payload:'
                          ' {0}'.format(payload))
                role = 'service'
                msg = 'Authenticated {0} with role {1} via kms auth'
                msg = msg.format(_from, role)
                log.debug(msg)
                if role_has_privilege(role, f.func_name):
                    g.auth_role = role
                    g.username = _from
                    return f(*args, **kwargs)
                else:
                    msg = '{0} is not authorized to access {1}.'
                    msg = msg.format(_from, f.func_name)
                    log.warning(msg)
                    return abort(403)
            except keymanager.TokenDecryptionError:
                msg = 'Access denied for {0}. Authentication Failed.'
                msg = msg.format(_from)
                log.warning(msg)
                return abort(403)
        # If not using kms auth, require google auth.
        else:
            role = 'user'
            if not role_has_privilege(role, f.func_name):
                return abort(403)
            if 'email' in session.get('google_oauth2', []):
                if (app.config['USERS_FILE']
                        and get_logged_in_user_email() not in users):
                    msg = 'User not authorized: {0}'
                    log.warning(msg.format(get_logged_in_user_email()))
                    return abort(403)
                else:
                    g.auth_role = role
                    return f(*args, **kwargs)
            response = make_response()
            if request.is_secure:
                secure_cookie = True
            else:
                secure_cookie = False
            result = _authomatic.login(
                WerkzeugAdapter(request, response),
                'google',
                session=session,
                session_saver=lambda: app.save_session(session, response),
                secure_cookie=secure_cookie)
            if result:
                if result.error:
                    msg = 'Google auth failed with error: {0}'
                    log.error(msg.format(result.error.message))
                    return abort(403)
                if result.user:
                    result.user.update()
                    user = result.user
                    email_suffix = app.config['GOOGLE_AUTH_EMAIL_SUFFIX']
                    if email_suffix and not user.email.endswith(email_suffix):
                        return abort(403)
                    session['google_oauth2'] = {}
                    session['google_oauth2']['email'] = user.email
                    session['google_oauth2']['first_name'] = user.first_name
                    session['google_oauth2']['last_name'] = user.last_name
                    g.auth_role = role
                    # TODO: find a way to save the angular args
                    # authomatic adds url params google auth has stripped the
                    # angular args anyway, so let's just redirect back to the
                    # index.
                    return redirect(url_for('index'))
            return response
        return abort(403)
예제 #6
0
파일: v1.py 프로젝트: rsk-project/confidant
def update_credential(id):
    try:
        _cred = Credential.get(id)
    except Credential.DoesNotExist:
        return jsonify({'error': 'Credential not found.'}), 404
    if _cred.data_type != 'credential':
        msg = 'id provided is not a credential.'
        return jsonify({'error': msg}), 400
    data = request.get_json()
    update = {}
    revision = _cred.revision + 1
    update['name'] = data.get('name', _cred.name)
    if 'enabled' in data:
        if not isinstance(data['enabled'], bool):
            return jsonify({'error': 'Enabled must be a boolean.'}), 400
        update['enabled'] = data['enabled']
    else:
        update['enabled'] = _cred.enabled
    services = _get_services_for_credential(id)
    if 'credential_pairs' in data:
        # Ensure credential pair keys are lowercase
        credential_pairs = _lowercase_credential_pairs(
            data['credential_pairs']
        )
        if not _check_credential_pair_uniqueness(credential_pairs):
            ret = {'error': 'credential pairs must be key: value'}
            return jsonify(ret), 400
        # Ensure credential pairs don't conflicts with pairs from other
        # services
        conflicts = _pair_key_conflicts_for_services(
            id,
            credential_pairs,
            services
        )
        if conflicts:
            ret = {
                'error': 'Conflicting key pairs in mapped service.',
                'conflicts': conflicts
            }
            return jsonify(ret), 400
        update['credential_pairs'] = json.dumps(credential_pairs)
    else:
        data_key = keymanager.decrypt_key(
            _cred.data_key,
            encryption_context={'id': id}
        )
        cipher_version = _cred.cipher_version
        cipher = CipherManager(data_key, cipher_version)
        update['credential_pairs'] = cipher.decrypt(_cred.credential_pairs)
    data_key = keymanager.create_datakey(encryption_context={'id': id})
    cipher = CipherManager(data_key['plaintext'], version=2)
    credential_pairs = cipher.encrypt(update['credential_pairs'])
    # Try to save to the archive
    try:
        Credential(
            id='{0}-{1}'.format(id, revision),
            name=update['name'],
            data_type='archive-credential',
            credential_pairs=credential_pairs,
            enabled=update['enabled'],
            revision=revision,
            data_key=data_key['ciphertext'],
            cipher_version=2,
            modified_by=authnz.get_logged_in_user_email()
        ).save(id__null=True)
    except PutError as e:
        log.error(e)
        return jsonify({'error': 'Failed to add credential to archive.'}), 500
    try:
        cred = Credential(
            id=id,
            name=update['name'],
            data_type='credential',
            credential_pairs=credential_pairs,
            enabled=update['enabled'],
            revision=revision,
            data_key=data_key['ciphertext'],
            cipher_version=2,
            modified_by=authnz.get_logged_in_user_email()
        )
        cred.save()
    except PutError as e:
        log.error(e)
        return jsonify({'error': 'Failed to update active credential.'}), 500
    if services:
        service_names = [x.id for x in services]
        msg = 'Updated credential "{0}" ({1}); Revision {2}'
        msg = msg.format(cred.name, cred.id, cred.revision)
        graphite.send_event(service_names, msg)
    return jsonify({
        'id': cred.id,
        'name': cred.name,
        'credential_pairs': json.loads(cipher.decrypt(cred.credential_pairs)),
        'revision': cred.revision,
        'enabled': cred.enabled,
        'modified_date': cred.modified_date,
        'modified_by': cred.modified_by
    })
예제 #7
0
파일: v1.py 프로젝트: rsk-project/confidant
def map_service_credentials(id):
    data = request.get_json()
    try:
        _service = Service.get(id)
        if _service.data_type != 'service':
            msg = 'id provided is not a service.'
            return jsonify({'error': msg}), 400
        revision = _service.revision + 1
        _service_credential_ids = _service.credentials
    except Service.DoesNotExist:
        revision = 1
        _service_credential_ids = []

    if data.get('credentials'):
        conflicts = _pair_key_conflicts_for_credentials(
            copy.deepcopy(data['credentials'])
        )
        if conflicts:
            ret = {
                'error': 'Conflicting key pairs in mapped service.',
                'conflicts': conflicts
            }
            return jsonify(ret), 400

    # If this is the first revision, we should attempt to create a grant for
    # this service.
    if revision == 1:
        try:
            keymanager.ensure_grants(id)
        except keymanager.ServiceCreateGrantError:
            msg = 'Failed to add grants for {0}.'.format(id)
            log.error(msg)
    # Try to save to the archive
    try:
        Service(
            id='{0}-{1}'.format(id, revision),
            data_type='archive-service',
            credentials=data.get('credentials'),
            enabled=data.get('enabled'),
            revision=revision,
            modified_by=authnz.get_logged_in_user_email()
        ).save(id__null=True)
    except PutError as e:
        log.error(e)
        return jsonify({'error': 'Failed to add service to archive.'}), 500

    try:
        service = Service(
            id=id,
            data_type='service',
            credentials=data['credentials'],
            enabled=data.get('enabled'),
            revision=revision,
            modified_by=authnz.get_logged_in_user_email()
        )
        service.save()
    except PutError as e:
        log.error(e)
        return jsonify({'error': 'Failed to update active service.'}), 500
    added = list(set(service.credentials) - set(_service_credential_ids))
    removed = list(set(_service_credential_ids) - set(service.credentials))
    msg = 'Added credentials: {0}; Removed credentials {1}; Revision {2}'
    msg = msg.format(added, removed, service.revision)
    graphite.send_event([id], msg)
    try:
        credentials = _get_credentials(service.credentials)
    except KeyError:
        return jsonify({'error': 'Decryption error.'}), 500
    return jsonify({
        'id': service.id,
        'credentials': credentials,
        'revision': service.revision,
        'enabled': service.enabled,
        'modified_date': service.modified_date,
        'modified_by': service.modified_by
    })
예제 #8
0
def update_credential(id):
    try:
        _cred = Credential.get(id)
    except Credential.DoesNotExist:
        return jsonify({'error': 'Credential not found.'}), 404
    if _cred.data_type != 'credential':
        msg = 'id provided is not a credential.'
        return jsonify({'error': msg}), 400
    data = request.get_json()
    update = {}
    revision = _cred.revision + 1
    update['name'] = data.get('name', _cred.name)
    if 'enabled' in data:
        if not isinstance(data['enabled'], bool):
            return jsonify({'error': 'Enabled must be a boolean.'}), 400
        update['enabled'] = data['enabled']
    else:
        update['enabled'] = _cred.enabled
    services = _get_services_for_credential(id)
    if 'credential_pairs' in data:
        # Ensure credential pair keys are lowercase
        credential_pairs = _lowercase_credential_pairs(
            data['credential_pairs'])
        if not _check_credential_pair_uniqueness(credential_pairs):
            ret = {'error': 'credential pairs must be key: value'}
            return jsonify(ret), 400
        # Ensure credential pairs don't conflicts with pairs from other
        # services
        conflicts = _pair_key_conflicts_for_services(id, credential_pairs,
                                                     services)
        if conflicts:
            ret = {
                'error': 'Conflicting key pairs in mapped service.',
                'conflicts': conflicts
            }
            return jsonify(ret), 400
        update['credential_pairs'] = json.dumps(credential_pairs)
    else:
        data_key = keymanager.decrypt_key(_cred.data_key,
                                          encryption_context={'id': id})
        cipher_version = _cred.cipher_version
        cipher = CipherManager(data_key, cipher_version)
        update['credential_pairs'] = cipher.decrypt(_cred.credential_pairs)
    data_key = keymanager.create_datakey(encryption_context={'id': id})
    cipher = CipherManager(data_key['plaintext'], version=2)
    credential_pairs = cipher.encrypt(update['credential_pairs'])
    # Try to save to the archive
    try:
        Credential(
            id='{0}-{1}'.format(id, revision),
            name=update['name'],
            data_type='archive-credential',
            credential_pairs=credential_pairs,
            enabled=update['enabled'],
            revision=revision,
            data_key=data_key['ciphertext'],
            cipher_version=2,
            modified_by=authnz.get_logged_in_user_email()).save(id__null=True)
    except PutError as e:
        log.error(e)
        return jsonify({'error': 'Failed to add credential to archive.'}), 500
    try:
        cred = Credential(id=id,
                          name=update['name'],
                          data_type='credential',
                          credential_pairs=credential_pairs,
                          enabled=update['enabled'],
                          revision=revision,
                          data_key=data_key['ciphertext'],
                          cipher_version=2,
                          modified_by=authnz.get_logged_in_user_email())
        cred.save()
    except PutError as e:
        log.error(e)
        return jsonify({'error': 'Failed to update active credential.'}), 500
    if services:
        service_names = [x.id for x in services]
        msg = 'Updated credential "{0}" ({1}); Revision {2}'
        msg = msg.format(cred.name, cred.id, cred.revision)
        graphite.send_event(service_names, msg)
    return jsonify({
        'id':
        cred.id,
        'name':
        cred.name,
        'credential_pairs':
        json.loads(cipher.decrypt(cred.credential_pairs)),
        'revision':
        cred.revision,
        'enabled':
        cred.enabled,
        'modified_date':
        cred.modified_date,
        'modified_by':
        cred.modified_by
    })
예제 #9
0
def map_service_credentials(id):
    data = request.get_json()
    try:
        _service = Service.get(id)
        if _service.data_type != 'service':
            msg = 'id provided is not a service.'
            return jsonify({'error': msg}), 400
        revision = _service.revision + 1
        _service_credential_ids = _service.credentials
    except Service.DoesNotExist:
        revision = 1
        _service_credential_ids = []

    if data.get('credentials'):
        conflicts = _pair_key_conflicts_for_credentials(
            copy.deepcopy(data['credentials']))
        if conflicts:
            ret = {
                'error': 'Conflicting key pairs in mapped service.',
                'conflicts': conflicts
            }
            return jsonify(ret), 400

    # If this is the first revision, we should attempt to create a grant for
    # this service.
    if revision == 1:
        try:
            keymanager.ensure_grants(id)
        except keymanager.ServiceCreateGrantError:
            msg = 'Failed to add grants for {0}.'.format(id)
            log.error(msg)
    # Try to save to the archive
    try:
        Service(
            id='{0}-{1}'.format(id, revision),
            data_type='archive-service',
            credentials=data.get('credentials'),
            enabled=data.get('enabled'),
            revision=revision,
            modified_by=authnz.get_logged_in_user_email()).save(id__null=True)
    except PutError as e:
        log.error(e)
        return jsonify({'error': 'Failed to add service to archive.'}), 500

    try:
        service = Service(id=id,
                          data_type='service',
                          credentials=data['credentials'],
                          enabled=data.get('enabled'),
                          revision=revision,
                          modified_by=authnz.get_logged_in_user_email())
        service.save()
    except PutError as e:
        log.error(e)
        return jsonify({'error': 'Failed to update active service.'}), 500
    added = list(set(service.credentials) - set(_service_credential_ids))
    removed = list(set(_service_credential_ids) - set(service.credentials))
    msg = 'Added credentials: {0}; Removed credentials {1}; Revision {2}'
    msg = msg.format(added, removed, service.revision)
    graphite.send_event([id], msg)
    try:
        credentials = _get_credentials(service.credentials)
    except KeyError:
        return jsonify({'error': 'Decryption error.'}), 500
    return jsonify({
        'id': service.id,
        'credentials': credentials,
        'revision': service.revision,
        'enabled': service.enabled,
        'modified_date': service.modified_date,
        'modified_by': service.modified_by
    })
예제 #10
0
    def decorated(*args, **kwargs):
        if not app.config.get("USE_AUTH"):
            return f(*args, **kwargs)

        auth = request.authorization
        headers = request.headers
        using_basic_kms_auth = auth and auth.get("username") and auth.get("password") != ""
        using_kms_auth = "X-Auth-Token" in headers and "X-Auth-From" in headers

        # User suppplied basic auth info
        if using_basic_kms_auth or using_kms_auth:
            if using_basic_kms_auth:
                _from = auth["username"]
                token = auth["password"]
            else:
                _from = headers["X-Auth-From"]
                token = headers["X-Auth-Token"]
            try:
                with stats.timer("decrypt_token"):
                    payload = keymanager.decrypt_token(token, _from)
                log.debug("Auth request had the following payload:" " {0}".format(payload))
                role = "service"
                msg = "Authenticated {0} with role {1} via kms auth"
                msg = msg.format(_from, role)
                log.debug(msg)
                if role_has_privilege(role, f.func_name):
                    g.auth_role = role
                    g.username = _from
                    return f(*args, **kwargs)
                else:
                    msg = "{0} is not authorized to access {1}."
                    msg = msg.format(_from, f.func_name)
                    log.warning(msg)
                    return abort(403)
            except keymanager.TokenDecryptionError:
                msg = "Access denied for {0}. Authentication Failed."
                msg = msg.format(_from)
                log.warning(msg)
                return abort(403)
        # If not using kms auth, require google auth.
        else:
            role = "user"
            if not role_has_privilege(role, f.func_name):
                return abort(403)
            if "email" in session.get("google_oauth2", []):
                if app.config["USERS_FILE"] and get_logged_in_user_email() not in users:
                    msg = "User not authorized: {0}"
                    log.warning(msg.format(get_logged_in_user_email()))
                    return abort(403)
                else:
                    g.auth_role = role
                    return f(*args, **kwargs)
            response = make_response()
            if request.is_secure:
                secure_cookie = True
            else:
                secure_cookie = False
            result = _authomatic.login(
                WerkzeugAdapter(request, response),
                "google",
                session=session,
                session_saver=lambda: app.save_session(session, response),
                secure_cookie=secure_cookie,
            )
            if result:
                if result.error:
                    msg = "Google auth failed with error: {0}"
                    log.error(msg.format(result.error.message))
                    return abort(403)
                if result.user:
                    result.user.update()
                    user = result.user
                    email_suffix = app.config["GOOGLE_AUTH_EMAIL_SUFFIX"]
                    if email_suffix and not user.email.endswith(email_suffix):
                        return abort(403)
                    session["google_oauth2"] = {}
                    session["google_oauth2"]["email"] = user.email
                    session["google_oauth2"]["first_name"] = user.first_name
                    session["google_oauth2"]["last_name"] = user.last_name
                    g.auth_role = role
                    # TODO: find a way to save the angular args
                    # authomatic adds url params google auth has stripped the
                    # angular args anyway, so let's just redirect back to the
                    # index.
                    return redirect(url_for("index"))
            return response
        return abort(403)