Пример #1
0
def delete_submission(sid, **kwargs):
    """
    INCOMPLETE
    Delete a submission as well as all related 
    files, results and errors
    
    Variables:
    sid         => Submission ID to be deleted
    
    Arguments: 
    None
    
    Data Block:
    None
    
    Result example:
    {success: true}
    """
    user = kwargs['user']
    submission = STORAGE.get_submission(sid)
    
    if submission and user \
            and Classification.is_accessible(user['classification'], submission['classification']) \
            and (submission['submission']['submitter'] == user['uname'] or user['is_admin']):
        with forge.get_filestore() as f_transport:
            STORAGE.delete_submission_tree(sid, transport=f_transport)
        STORAGE.commit_index('submission')
        return make_api_response({"success": True})
    else:
        return make_api_response("", "Your are not allowed to delete this submission.", 403)
Пример #2
0
def get_error(error_key, **kwargs):
    """
    Get the error details for a given error key
    
    Variables:
    error_key         => Error key to get the details for
    
    Arguments: 
    None
    
    Data Block:
    None
    
    Result example:
    {
        KEY: VALUE,   # All fields of an error in key/value pair
    }
    """
    user = kwargs['user']
    data = STORAGE.get_error(error_key)

    if user and data and Classification.is_accessible(user['classification'],
                                                      data['classification']):
        return make_api_response(data)
    else:
        return make_api_response("",
                                 "You are not allowed to see this error...",
                                 403)
Пример #3
0
def get_signature(sid, rev, **kwargs):
    """
    Get the detail of a signature based of its ID and revision
    
    Variables:
    sid    =>     Signature ID
    rev    =>     Signature revision number
    
    Arguments: 
    None
    
    Data Block:
    None
     
    Result example:
    {"name": "sig_name",          # Signature name    
     "tags": ["PECheck"],         # Signature tags
     "comments": [""],            # Signature comments lines
     "meta": {                    # Meta fields ( **kwargs )
       "id": "SID",                 # Mandatory ID field
       "rule_version": 1 },         # Mandatory Revision field
     "type": "rule",              # Rule type (rule, private rule ...)
     "strings": ['$ = "a"'],      # Rule string section (LIST)
     "condition": ["1 of them"]}  # Rule condition section (LIST)    
    """
    user = kwargs['user']
    data = STORAGE.get_signature("%sr.%s" % (sid, rev))
    if data:
        if not Classification.is_accessible(user['classification'],
                                            data['meta'].get('classification',
                                                             Classification.UNRESTRICTED)):
            return make_api_response("", "Your are not allowed to view this signature.", 403)
        return make_api_response(data)
    else:
        return make_api_response("", "Signature not found. (%s r.%s)" % (sid, rev), 404)
Пример #4
0
def setup_watch_queue(sid, **kwargs):
    """
    Starts a watch queue to get live results
    
    Variables:
    sid      => Submission ID
    
    Arguments: (optional)
    suffix    => suffix to be appended to the queue name
    
    Data Block:
    None
    
    Result example:
    {"wq_id": "c7668cfa-...-c4132285142e"} #ID of the watch queue
    """
    data = STORAGE.get_submission(sid)
    user = kwargs['user']

    if user and data and Classification.is_accessible(user['classification'],
                                                      data['classification']):
        watch_queue = reply_queue_name(request.args.get('suffix', "WQ"))
        SubmissionWrapper.watch(sid, watch_queue)
        return make_api_response({"wq_id": watch_queue})
    else:
        return make_api_response(
            "", "You are not allowed to access this submissions.", 403)
Пример #5
0
def add_apikey(name, priv, **kwargs):
    """
    Add an API Key for the currently logged in user with given privileges

    Variables:
    name    => Name of the API key
    priv    => Requested privileges

    Arguments:
    None

    Data Block:
    None

    Result example:
    {"apikey": <ramdomly_generated_password>}
    """
    user = kwargs['user']
    user_data = STORAGE.get_user(user['uname'])

    if name in [x[0] for x in user_data.get('apikeys', [])]:
        return make_api_response("", err="APIKey %s already exist" % name, status_code=400)

    if priv not in API_PRIV_MAP.keys():
        return make_api_response("", err="Invalid APIKey privilege '%s'. "
                                         "Choose between: %s " % (priv, API_PRIV_MAP.keys()), status_code=400)

    keys = user_data.get('apikeys', [])
    random_pass = get_random_password(length=48)
    keys.append((name, bcrypt.encrypt(random_pass), API_PRIV_MAP[priv]))
    user_data['apikeys'] = keys
    STORAGE.save_user(user['uname'], user_data)

    return make_api_response({"apikey": random_pass})
Пример #6
0
def get_service_result(cache_key, **kwargs):
    """
    Get the result for a given service cache key.
        
    Variables:
    cache_key         => Service result cache key
                         as SRL.ServiceName.ServiceVersion.ConfigHash
                         
    Arguments: 
    None
    
    Data Block:
    None
    
    Result example:
    {"response": {                        # Service Response
       "milestones": {},                    # Timing object
       "supplementary": [],                 # Supplementary files  
       "service_name": "Mcafee",            # Service Name
       "message": "",                       # Service error message
       "extracted": [],                     # Extracted files
       "service_version": "v0"},            # Service Version
     "result": {                          # Result objects
       "score": 1302,                       # Total score for the file 
       "sections": [{                       # Result sections
         "body": "Text goes here",            # Body of the section (TEXT)
         "classification": "",                # Classification
         "links": [],                         # Links inside the section
         "title_text": "Title",               # Title of the section
         "depth": 0,                          # Depth (for Display purposes)
         "score": 500,                        # Section's score
         "body_format": null,                 # Body format
         "subsections": []                    # List of sub-sections
         }, ... ], 
       "classification": "",                # Maximum classification for service
       "tags": [{                           # Generated Tags
         "usage": "IDENTIFICATION",           # Tag usage 
         "value": "Tag Value",                # Tag value
         "type": "Tag Type",                  # Tag type
         "weight": 50,                        # Tag Weight
         "classification": ""                 # Tag Classification
         }, ...]
       }
    }
    """
    user = kwargs['user']
    data = STORAGE.get_result(cache_key)
    if data is None:
        return make_api_response("",
                                 "Cache key %s does not exists." % cache_key,
                                 404)

    cur_file = STORAGE.get_file(cache_key[:64])
    data = format_result(user['classification'], data,
                         cur_file['classification'])
    if not data:
        return make_api_response(
            "", "You are not allowed to view the results for this key", 403)

    return make_api_response(data)
Пример #7
0
def remove_workflow(workflow_id, **_):
    """
    Remove the specified workflow.
    
    Variables: 
    workflow_id       => ID of the workflow to remove
    
    Arguments: 
    None
    
    Data Block:
    None
    
    Result example:
    {                        
     "success": true  # Was the remove successful?
    } 
    """
    wf = STORAGE.get_workflow(workflow_id)
    if wf:
        STORAGE.delete_workflow(workflow_id)
        return make_api_response({"success": True})
    else:
        return make_api_response({"success": False},
                                 err="Workflow ID %s does not exist" % workflow_id,
                                 status_code=404)
Пример #8
0
def set_user_avatar(username, **_):
    """
    Sets the user's Avatar
    
    Variables: 
    username    => Name of the user you want to set the avatar for
    
    Arguments: 
    None
    
    Data Block:
    "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD..."
    
    Result example:
    {
     "success": true    # Was saving the avatar successful ?
    }
    """
    data = request.json
    if not isinstance(data, str) or not STORAGE.set_user_avatar(
            username, data):
        make_api_response({"success": False},
                          "Data block should be a base64 encoded image "
                          "that starts with 'data:image/<format>;base64,'")

    return make_api_response({"success": True})
Пример #9
0
def get_cluster_config(name, **kwargs):
    data = STORAGE.get_blob("prov_conf_%s" % name)
    if not data:
        return make_api_response({},
                                 "Provisionning config %s not found." % name,
                                 404)
    return make_api_response(data)
Пример #10
0
def remove_user_favorite(username, favorite_type, **_):
    """
    Remove a favorite from the user's favorites.

    Variables:
    username       => Name of the user to remove the favorite from
    favorite_type  => Type of favorite to remove

    Arguments:
    None

    Data Block:
    "name_of_favorite"   # Name of the favorite to remove

    Result example:
    {
     "success": true  # Was the remove successful?
    }
    """
    if favorite_type not in ALLOWED_FAVORITE_TYPE:
        return make_api_response({}, "%s is not a valid favorite type" %
                                 favorite_type, 500)

    name = request.data or "None"
    try:
        favorites = STORAGE.get_user_favorites(username)
        for fav in favorites[favorite_type]:
            if fav['name'] == name:
                favorites[favorite_type].remove(fav)
    except Exception:
        return make_api_response({}, "Favorite does not exists, (%s)" % name,
                                 404)

    return make_api_response(
        {"success": STORAGE.set_user_favorites(username, favorites)})
Пример #11
0
def outstanding_services(sid, **kwargs):
    """
    List outstanding services and the number of file each
    of them still have to process.
    
    Variables:
    sid      => Submission ID
    
    Arguments:
    None
    
    Data Block:
    None
    
    Result example:
    {"MY SERVICE": 1, ... } # Dictionnary of services and number of files
    """
    data = STORAGE.get_submission(sid)
    user = kwargs['user']

    if user and data and Classification.is_accessible(user['classification'],
                                                      data['classification']):
        return make_api_response(DispatchClient.get_outstanding_services(sid))
    else:
        return make_api_response(
            {}, "You are not allowed to access this submissions.", 403)
Пример #12
0
def get_source_seed(**kwargs):
    """
    Get the default configuration seed

    Variables:
    None

    Arguments:
    None

    Data Block:
    None

    Result example:
    {
     "KEY": "value",  # Dictionary of key/value pair
     ...
    }
    """
    seed_module = STORAGE.get_blob("seed_module")
    if not seed_module:
        return make_api_response({})
    seed = module_attribute_by_name(seed_module)
    services_to_register = seed['services']['master_list']

    for service, svc_detail in services_to_register.iteritems():
        seed['services']['master_list'][service] = get_merged_svc_config(service, svc_detail, LOGGER)

    return make_api_response(seed)
Пример #13
0
def get_file_hex(srl, **kwargs):
    """
    Returns the file hex representation
    
    Variables: 
    srl       => A resource locator for the file (sha256)
    
    Arguments: 
    None
    
    Data Block:
    None

    API call example:
    /api/v3/file/hex/123456...654321/

    Result example:
    <THE FILE HEX REPRESENTATION>
    """
    user = kwargs['user']
    file_obj = STORAGE.get_file(srl)

    if not file_obj:
        return make_api_response({}, "The file was not found in the system.", 404)
    
    if user and Classification.is_accessible(user['classification'], file_obj['classification']):
        with forge.get_filestore() as f_transport:
            data = f_transport.get(srl)

        if not data:
            return make_api_response({}, "This file was not found in the system.", 404)

        return make_api_response(hexdump(data))
    else:
        return make_api_response({}, "You are not allowed to view this file.", 403)
Пример #14
0
def validate_otp(token, **kwargs):
    """
    Validate newly setup OTP token

    Variables:
    token     => Current token for temporary OTP sercret key

    Arguments:
    None

    Data Block:
    None

    Result example:
    {
     "success": true
    }
    """
    uname = kwargs['user']['uname']
    user_data = STORAGE.get_user(uname)

    try:
        token = int(token)
    except ValueError:
        return make_api_response({'success': False}, err="This is not a valid OTP token", status_code=400)

    secret_key = flsk_session.pop('temp_otp_sk', None)
    if get_totp_token(secret_key) == token:
        user_data['otp_sk'] = secret_key
        STORAGE.save_user(uname, user_data)
        return make_api_response({'success': True})
    else:
        flsk_session['temp_otp_sk'] = secret_key
        return make_api_response({'success': False}, err="OTP token does not match secret key", status_code=400)
Пример #15
0
def download_file(srl, **kwargs):
    """
    Download the file using the default encoding method. This api
    will force the browser in download mode.
    
    Variables: 
    srl       => A resource locator for the file (sha256)
    
    Arguments: 
    name      => Name of the file to download
    format    => Format to encode the file in
    password  => Password of the password protected zip
    
    Data Block:
    None

    API call example:
    /api/v3/file/download/123456...654321/

    Result example:
    <THE FILE BINARY ENCODED IN SPECIFIED FORMAT>
    """
    user = kwargs['user']
    file_obj = STORAGE.get_file(srl)

    if not file_obj:
        return make_api_response({}, "The file was not found in the system.", 404)

    if user and Classification.is_accessible(user['classification'], file_obj['classification']):
        params = load_user_settings(user)
    
        name = request.args.get('name', srl)
        if name == "": 
            name = srl
        else:
            name = basename(name)
        name = safe_str(name)

        file_format = request.args.get('format', params['download_encoding'])
        if file_format == "raw" and not ALLOW_RAW_DOWNLOADS:
            return make_api_response({}, "RAW file download has been disabled by administrators.", 403)

        password = request.args.get('password', None)
        
        with forge.get_filestore() as f_transport:
            data = f_transport.get(srl)

        if not data:
            return make_api_response({}, "The file was not found in the system.", 404)

        data, error, already_encoded = encode_file(data, file_format, name, password)
        if error:
            return make_api_response({}, error['text'], error['code'])

        if file_format != "raw" and not already_encoded:
            name = "%s.%s" % (name, file_format)
    
        return make_file_response(data, name, len(data))
    else:
        return make_api_response({}, "You are not allowed to download this file.", 403)
Пример #16
0
def get_file_children(srl, **kwargs):
    """
    Get the list of children files for a given file

    Variables:
    srl       => A resource locator for the file (sha256)

    Arguments:
    None

    Data Block:
    None

    API call example:
    /api/v3/file/children/123456...654321/

    Result example:
    [                           # List of children
     {"name": "NAME OF FILE",       # Name of the children
      "srl": "123..DEF"},           # SRL of the children (SHA256)
    ]
    """
    user = kwargs['user']
    file_obj = STORAGE.get_file(srl)

    if file_obj:
        if user and Classification.is_accessible(user['classification'], file_obj['classification']):
            return make_api_response(STORAGE.list_file_childrens(srl, access_control=user["access_control"]))
        else:
            return make_api_response({}, "You are not allowed to view this file.", 403)
    else:
        return make_api_response({}, "This file does not exists.", 404)
Пример #17
0
def get_file_raw(srl, **kwargs):
    """
    Return the raw values for a file where non-utf8 chars are replaced by DOTs.

    Variables:
    srl       => A resource locator for the file (sha256)

    Arguments:
    None

    Data Block:
    None

    Result example:
    <THE RAW FILE>
    """

    user = kwargs['user']
    file_obj = STORAGE.get_file(srl)

    if not file_obj:
        return make_api_response({}, "The file was not found in the system.", 404)

    if user and Classification.is_accessible(user['classification'], file_obj['classification']):
        with forge.get_filestore() as f_transport:
            data = f_transport.get(srl)

        if not data:
            return make_api_response({}, "This file was not found in the system.", 404)

        return make_api_response(data.translate(FILTER_RAW))
    else:
        return make_api_response({}, "You are not allowed to view this file.", 403)
Пример #18
0
def get_alert(alert_key, **kwargs):
    """
    Get the alert details for a given alert key
    
    Variables:
    alert_key         => Alert key to get the details for
    
    Arguments: 
    None
    
    Data Block:
    None

    API call example:
    /api/v3/alert/1234567890/

    Result example:
    {
        KEY: VALUE,   # All fields of an alert in key/value pair
    }
    """
    user = kwargs['user']
    data = STORAGE.get_alert(alert_key)

    if user and data and Classification.is_accessible(user['classification'],
                                                      data['classification']):
        return make_api_response(data)
    else:
        return make_api_response("",
                                 "You are not allowed to see this alert...",
                                 403)
Пример #19
0
def get_service_error(cache_key, **_):
    """
    Get the content off a given service error cache key.
        
    Variables:
    cache_key     => Service result cache key
                     as (SRL.ServiceName)
                            
    Arguments: 
    None
    
    Data Block:
    None
    
    Result example:
    {"response": {                   # Service Response                      
         "milestones": {},              # Timing object
         "supplementary": [],           # Supplementary files  
         "status": "FAIL",              # Status
         "service_version": "",         # Service Version
         "service_name": "NSRL",        # Service Name
         "extracted": [],               # Extracted files
         "score": 0,                    # Service Score
         "message": "Err Message"},     # Error Message
     "result": []}                   # Result objets
    """
    data = STORAGE.get_error(cache_key)
    if data is None:
        return make_api_response("",
                                 "Cache key %s does not exists." % cache_key,
                                 404)

    return make_api_response(data)
Пример #20
0
def bind(**kwargs):
    """
    Complete registration of the new key

    Variables:
    None

    Arguments:
    data    => Response to the enroll challenge

    Data Block:
    None

    Result example:
    {
     "success": True
    }
    """
    uname = kwargs['user']['uname']
    data = request.json
    if "errorCode" in data:
        return make_api_response({'success': False}, err=U2F_CLIENT_ERROR_MAP[data['errorCode']], status_code=400)

    user = STORAGE.get_user(uname)
    current_enroll = session.pop('_u2f_enroll_')

    try:
        device, cert = complete_registration(current_enroll, data, [APP_ID])
    except Exception as e:
        return make_api_response({'success': False}, err=e.message, status_code=400)

    user.setdefault('u2f_devices', []).append(device.json)
    STORAGE.save_user(uname, user)
    return make_api_response({"success": True})
Пример #21
0
def check_srl_exists(*args, **kwargs):
    """
    Check if the the provided Resource locators exist in the
    system or not.
    
    Variables:
    None
    
    Arguments: 
    None
    
    Data Block (REQUIRED): 
    ["SRL1", SRL2]    # List of SRLs (SHA256)
    
    Result example:
    {
     "existing": [],  # List of existing SRLs
     "missing": []    # List of missing SRLs
     }
    """
    srls_to_check = request.json
    if type(srls_to_check) != list:
        return make_api_response("", "Expecting a list of SRLs", 403)

    with forge.get_filestore() as f_transport:
        check_results = SubmissionWrapper.check_exists(f_transport, srls_to_check)
    return make_api_response(check_results)
Пример #22
0
def add_user_account(username, **_):
    """
    Add a user to the system
    
    Variables: 
    username    => Name of the user to add
    
    Arguments: 
    None
    
    Data Block:
    {                        
     "name": "Test user",        # Name of the user
     "is_active": true,          # Is the user active?
     "classification": "",            # Max classification for user
     "uname": "usertest",        # Username
     "is_admin": false,          # Is the user admin?
     "avatar": null,             # Avatar of the user
     "groups": ["TEST"]          # Groups the user is member of
    } 
    
    Result example:
    {
     "success": true             # Saving the user info succeded 
    }
    """

    data = request.json

    if "{" in username or "}" in username:
        return make_api_response({"success": False},
                                 "You can't use '{}' in the username", 412)

    if not STORAGE.get_user_account(username):
        new_pass = data.pop('new_pass', None)
        if new_pass:
            if not check_password_requirements(
                    new_pass, strict=config.auth.internal.strict_requirements):
                if config.auth.internal.strict_requirements:
                    error_msg = "Password needs to be 8 characters with at least an uppercase, " \
                                "a lowercase, a number and a special character."
                else:
                    error_msg = "Password needs to be 8 alphanumeric characters."
                return make_api_response({"success": False}, error_msg, 469)
            data['password'] = get_password_hash(new_pass)

        STORAGE.save_user(
            username,
            validate_settings(data,
                              ACCOUNT_DEFAULT,
                              exceptions=[
                                  'avatar', 'agrees_with_tos', 'dn',
                                  'password', 'otp_sk', 'u2f_devices'
                              ]))
        return make_api_response({"success": True})
    else:
        return make_api_response(
            {"success": False},
            "The username you are trying to add already exists.", 400)
Пример #23
0
def find_related_alert_ids(**kwargs):
    """
    Return the list of all IDs related to the currently selected query

    Variables:
    None

    Arguments:
    q         =>  Main query to filter the data [REQUIRED]
    tc        =>  Time constraint to apply to the search
    start     =>  Time at which to start the days constraint
    fq        =>  Filter query applied to the data

    Data Block:
    None

    API call example:
    /api/v3/alert/related/?q=event_id:1

    Result example:
    ["1"]
    """
    user = kwargs['user']
    q = request.args.get('q', None)
    fq = request.args.getlist('fq')
    if not q and not fq:
        return make_api_response(
            {
                "success": False,
                "event_id": None
            },
            err="You need to at least provide a query to filter the data",
            status_code=400)
    if not q:
        q = fq.pop(0)
    tc = request.args.get('tc', None)
    stime = request.args.get('start', None)

    fq_list = []

    if tc is not None and tc != "":
        if stime is not None:
            fq_list.append("reporting_ts:[%s-%s TO %s]" % (stime, tc, stime))
        else:
            fq_list.append("reporting_ts:[NOW-%s TO NOW]" % tc)
    elif stime is not None and stime != "":
        fq_list.append("reporting_ts:[* TO %s]" % stime)

    if fq:
        if isinstance(fq, list):
            fq_list.extend(fq)
        elif fq != "":
            fq_list.append(fq)

    return make_api_response([
        x['event_id'] for x in STORAGE.stream_search(
            'alert', q, fq=fq_list, access_control=user['access_control'])
    ])
Пример #24
0
def list_alerts(**kwargs):
    """
    List all alert in the system (per page)
    
    Variables:
    None
    
    Arguments:
    start_time   => Time offset at which to list alerts
    time_slice   => Length after the start time that we query
    offset       => Offset at which we start giving alerts
    length       => Numbers of alerts to return
    filter       => Filter to apply to the alert list
    fq           => Post filter queries (you can have multiple of those)
    
    Data Block:
    None

    API call example:
    /api/v3/alert/list/

    Result example:
    {"total": 201,                # Total alerts found
     "offset": 0,                 # Offset in the alert list
     "count": 100,                # Number of alerts returned
     "items": []                  # List of alert blocks
    }
    """
    user = kwargs['user']

    offset = int(request.args.get('offset', 0))
    length = int(request.args.get('length', 100))
    query = request.args.get('filter', "*")
    if not query:
        query = "*"
    start_time = request.args.get('start_time', None)
    time_slice = request.args.get('time_slice', None)
    filter_queries = [x for x in request.args.getlist("fq") if x != ""]

    try:
        return make_api_response(
            STORAGE.list_alerts(query,
                                start=offset,
                                rows=length,
                                access_control=user['access_control'],
                                fq_list=filter_queries,
                                start_time=start_time,
                                time_slice=time_slice))
    except SearchException:
        return make_api_response("",
                                 "The specified search query is not valid.",
                                 400)
    except RiakError, e:
        if e.value == "Query unsuccessful check the logs.":
            return make_api_response(
                "", "The specified search query is not valid.", 400)
        else:
            raise
Пример #25
0
def change_status_by_batch(status, **kwargs):
    """
    Apply status to all alerts matching the given filters using a background process

    Variables:
    status     =>  Status to apply

    Arguments:
    q         =>  Main query to filter the data [REQUIRED]
    tc        =>  Time constraint to apply to the search
    start     =>  Time at which to start the days constraint
    fq        =>  Filter query applied to the data

    Data Block:
    None

    API call example:
    /api/v3/alert/status/batch/MALICIOUS/?q=al_av:*

    Result example:
    {"status": "QUEUED"}
    """
    action_queue = queue.PriorityQueue('alert-actions', db=DATABASE_NUM)
    status = status.upper()

    user = kwargs['user']
    q = request.args.get('q', None)
    fq = request.args.getlist('fq')
    if not q and not fq:
        return make_api_response(
            {
                "success": False,
                "event_id": None
            },
            err="You need to at least provide a query to filter the data",
            status_code=400)
    if not q:
        q = fq.pop(0)
    tc = request.args.get('tc', None)
    start = request.args.get('start', None)

    msg = {
        "user": user['uname'],
        "action": "batch_workflow",
        "query": q,
        "tc": tc,
        "start": start,
        "fq": fq,
        "status": status,
        "queue_priority": QUEUE_PRIORITY
    }

    action_queue.push(QUEUE_PRIORITY, msg)

    return make_api_response({"status": "QUEUED"})
Пример #26
0
def set_user_account(username, **kwargs):
    """
    Save the user account information.
    
    Variables: 
    username    => Name of the user to get the account info
    
    Arguments: 
    None
    
    Data Block:
    {                        
     "name": "Test user",        # Name of the user
     "is_active": true,          # Is the user active?
     "classification": "",            # Max classification for user
     "uname": "usertest",        # Username
     "is_admin": false,          # Is the user admin?
     "avatar": null,             # Avatar of the user
     "groups": ["TEST"]          # Groups the user is member of
    } 
    
    Result example:
    {
     "success": true             # Saving the user info succeded 
    }
    """
    try:
        data = request.json
        new_pass = data.pop('new_pass', None)

        old_user = STORAGE.get_user(username)
        if not old_user:
            return make_api_response({"success": False},
                                     "User %s does not exists" % username, 404)

        data['apikeys'] = old_user.get('apikeys', [])
        data['otp_sk'] = old_user.get('otp_sk', None)
        data['u2f_devices'] = old_user.get('u2f_devices', [])

        if new_pass:
            if not check_password_requirements(
                    new_pass, strict=config.auth.internal.strict_requirements):
                return make_api_response(
                    {"success": False},
                    "Password does not meet minimum password requirements.",
                    469)
            data['password'] = get_password_hash(new_pass)
            data.pop('new_pass_confirm', None)
        else:
            data['password'] = old_user.get('password', None)

        return make_api_response(
            {"success": save_user_account(username, data, kwargs['user'])})
    except AccessDeniedException, e:
        return make_api_response({"success": False}, e.message, 403)
Пример #27
0
def flowjs_check_chunk(**kwargs):
    """
    Flowjs check file chunk.
    
    This API is reserved for the FLOWJS file uploader. It allows FLOWJS 
    to check if the file chunk already exists on the server.
    
    Variables: 
    None
    
    Arguments (REQUIRED): 
    flowChunkNumber      => Current chunk number
    flowFilename         => Original filename
    flowTotalChunks      => Total number of chunks
    flowIdentifier       => File unique identifier
    flowCurrentChunkSize => Size of the current chunk
    
    Data Block:
    None
    
    Result example:
    {'exists': True}     #Does the chunk exists on the server?
    """

    flow_chunk_number = request.args.get("flowChunkNumber", None)
    flow_chunk_size = request.args.get("flowChunkSize", None)
    flow_total_size = request.args.get("flowTotalSize", None)
    flow_filename = request.args.get("flowFilename", None)
    flow_total_chunks = request.args.get("flowTotalChunks", None)
    flow_identifier = request.args.get("flowIdentifier", None)
    flow_current_chunk_size = request.args.get("flowCurrentChunkSize", None)

    if not flow_chunk_number or not flow_identifier or not flow_current_chunk_size or not flow_filename \
            or not flow_total_chunks or not flow_chunk_size or not flow_total_size:
        return make_api_response(
            "", "Required arguments missing. flowChunkNumber, flowIdentifier, "
            "flowCurrentChunkSize, flowChunkSize and flowTotalSize "
            "should always be present.", 412)

    mydir = os.path.join(TEMP_DIR_CHUNKED, flow_identifier)
    myfile = os.path.join(mydir, 'chunk.part' + flow_chunk_number)
    if os.path.exists(myfile):
        if os.path.getsize(myfile) == int(flow_current_chunk_size):
            if validate_chunks(mydir, flow_total_chunks, flow_chunk_size,
                               flow_total_size):
                reconstruct_file(mydir, flow_identifier, flow_filename,
                                 flow_total_chunks)
            return make_api_response({"exist": True})
        else:
            return make_api_response({"exist": False},
                                     "Chunk wrong size, please resend!", 404)
    else:
        return make_api_response({"exist": False},
                                 "Chunk does not exist, please send it!", 404)
Пример #28
0
def set_cluster_config(name, **kwargs):
    data = request.json
    if not data:
        return make_api_response({},
                                 "There are no provisionning config to save",
                                 400)

    if 'allocation' not in data or 'flex' not in data or 'overrides' not in data:
        return make_api_response({}, "Invalid provisioning config", 400)

    STORAGE.save_blob("prov_conf_%s" % name, data)
    return make_api_response({"success": True})
Пример #29
0
def set_service(servicename, **_):
    """
    Save the configuration of a given service
    
    Variables: 
    servicename    => Name of the service to save
    
    Arguments: 
    None
    
    Data Block:
    {'accepts': '(archive|executable|java|android)/.*',
     'category': 'Extraction',
     'classpath': 'al_services.alsvc_extract.Extract',
     'config': {'DEFAULT_PW_LIST': ['password', 'infected']},
     'cpu_cores': 0.1,
     'description': "Extract some stuff",
     'enabled': True,
     'install_by_default': True,
     'name': 'Extract',
     'ram_mb': 256,
     'rejects': 'empty|metadata/.*',
     'stage': 'EXTRACT',
     'submission_params': [{'default': u'',
       'name': 'password',
       'type': 'str',
       'value': u''},
      {'default': False,
       'name': 'extract_pe_sections',
       'type': 'bool',
       'value': False},
      {'default': False,
       'name': 'continue_after_extract',
       'type': 'bool',
       'value': False}],
     'supported_platforms': ['Linux'],
     'timeout': 60}
    
    Result example:
    {"success": true }    #Saving the user info succeded
    """
    data = request.json

    try:
        if servicename != data['name']:
            raise AccessDeniedException(
                "You are not allowed to change the service name.")

        return make_api_response(
            {"success": STORAGE.save_service(servicename, data)})
    except AccessDeniedException, e:
        return make_api_response({"success": False}, e.message, 403)
Пример #30
0
def add_labels(alert_id, labels, **kwargs):
    """
    Add one or multiple labels to a given alert

    Variables:
    alert_id     => ID of the alert to add the label to
    labels       => List of labels to add as comma separated string

    Arguments:
    None

    Data Block:
    None

    API call example:
    /api/v3/alert/label/1234567890/EMAIL/

    Result example:
    {"success": true,
     "event_id": 0}
    """
    user = kwargs['user']
    labels = set(labels.upper().split(","))

    alert = STORAGE.get_alert(alert_id)

    if not alert:
        return make_api_response({
            "success": False,
            "event_id": None
        },
                                 err="Alert ID %s not found" % alert_id,
                                 status_code=404)

    if not Classification.is_accessible(user['classification'],
                                        alert['classification']):
        return make_api_response("",
                                 "You are not allowed to see this alert...",
                                 403)

    cur_label = set(alert.get('label', []))
    if labels.difference(labels.intersection(cur_label)):
        cur_label = cur_label.union(labels)
        alert['label'] = list(cur_label)
        STORAGE.save_alert(alert_id, alert)
        return make_api_response({"success": True})
    else:
        return make_api_response({"success": False},
                                 err="Alert already has labels %s" %
                                 ", ".join(labels),
                                 status_code=403)