Пример #1
0
def delete_named_document(url: str, db_name: str,
                          doc_name: str) -> dict or None:
    """
    Delete the named document
    :param url: couchDB base URL in format http://host:port/
    :param db_name:name of db
    :param doc_name: document name
    :return: delete result or None
    """
    doc_url = url + db_name + "/" + doc_name
    get_resp = RestClientApis.http_get_and_check_success(doc_url)
    if get_resp.http_status == HTTPStatus.OK:
        rev = get_resp.json_body["_rev"]
        doc_url = doc_url + "?rev=" + rev
    elif get_resp.http_status == HTTPStatus.UNAUTHORIZED:
        print("Delete requested but not enough permissions \n")
        return None
    else:
        print("Error reading doc_id {}. HTTP Code {}".format(
            doc_url, get_resp.http_status))
        return None
    del_resp = RestClientApis.http_delete_and_check_success(doc_url)
    if del_resp.http_status == HTTPStatus.OK:
        return del_resp.json_body
    else:
        print("Error deleting doc_id {}. HTTP Code {}".format(
            doc_url, get_resp.http_status))
        return None
Пример #2
0
def get_db_all_docs(url: str, db_name: str) -> list or None:
    """
    Retrieve all docs for a DB. CouchDB returns list of documents as
    chunked-encoding, therefore special reassembly is needed
    :param url: CouchDB URL
    :param db_name: DB name
    :return: A list of JSON dicts objects
    """

    # Make static analysis happy
    buf = None
    try:
        json_dict_list = list()
        all_docs = url + db_name + "/" + "_all_docs"
        get_resp = RestClientApis.http_get_and_check_success(all_docs)
        headers = get_resp.response_object.headers
        if ("Transfer-Encoding", "chunked") in headers.items():
            for buf in read_chunks(get_resp.response_object):
                json_dict = json.loads(buf)
                json_dict_list.append(json_dict)
            return json_dict_list
        else:
            return None
    except JSONDecodeError:
        error_msg = "Error decoding response {}".format(buf)
        print(error_msg)
        return None
Пример #3
0
def create_opa_policy(url: str, policy):
    """
    This function creates a OPA policy on the server
    :param url: url address where policy is placed
    :param file_path: .rego file path or a raw rego string
    :return: RestReturn
    """
    if os.path.isfile(policy):
        with open(policy, 'r') as file:
            policy_data = file.read()
            policy_resp = RestClientApis.http_put_and_check_success(
                url, policy_data, headers={'Content-Type': 'text/plain'})
        return policy_resp
    else:
        # we are going to treat it as a raw string and hope for the best.
        policy_resp = RestClientApis.http_put_and_check_success(
            url, policy, headers={'Content-Type': 'text/plain'})
        return policy_resp.success, policy_resp.message
Пример #4
0
def create_base_doc(url, json_data):
    """
    This function creates a OPA policy on the server
    :param url: url address where base document is placed
    :param json_data: Json data for Base Document
    :return: success, message
    :rtype: tuple
    """
    resp = RestClientApis.http_put_and_check_success(url, json_data)
    return resp.success, resp.message
Пример #5
0
def get_base_doc(url: str, debug=False) -> (object):
    """
    This function gets an OPA base doc on the server
    :param url: url address where base document is placed
    :return: RestReturn Obj
    :rtype: RestReturn
    """
    if debug:
        url = url + DEBUG_QUERY_STRING
    resp = RestClientApis.http_get_and_check_success(url)
    return resp
Пример #6
0
def create_opa_base_doc(url, json_data):
    """
    This function creates a OPA policy on the server
    :param url: url address where base document is placed
    :param json_data: Json data for Base Document
    :return: Rest Return
    """
    resp = RestClientApis.http_put_and_check_success(url, json_data, headers={'Content-Type': 'application/json'})
    if resp.http_status != HTTPStatus.OK:
        raise json.JSONDecodeError(resp.message)
    return resp
Пример #7
0
def delete_base_doc(url: str, debug=False):
    """
    This function deletes an OPA base doc on the server
    :param url: url address where base document is placed
    :return: success, message
    :rtype: tuple
    """
    if debug:
        url = url + DEBUG_QUERY_STRING
    resp = RestClientApis.http_delete_and_check_success(url)
    return resp.success, resp.message
Пример #8
0
def delete_all_policies(url: str, debug=False):
    """
    This function deletes all OPA base docs on the server
    :param url: url address where base document is placed
    :return: success, message
    :rtype: tuple
    """
    if debug:
        url = url + DEBUG_QUERY_STRING
    data = json.dumps(dict())
    resp = RestClientApis.http_put_and_check_success(url, data)
    return resp.success, resp.message
Пример #9
0
def execute_query(url: str, json_data: str) -> (bool, str, dict):
    """

    :param url: URL for query
    :param json_data: JSON in string format.
    :return: success, message and json body in dict
    :rtype: tuple(bool, str, dict)
    """
    resp_obj = RestClientApis.http_post_and_check_success(url,
                                                          json_data,
                                                          location=False)
    return resp_obj.success, resp_obj.message, resp_obj.json_body
Пример #10
0
def delete_db(url, db_name):
    """
    Deletes a DB from couchDB
    :param url: couchDB base URL in format http://host:port/
    :param db_name: name of db to be deleted
    :return: boolean
    """
    del_resp = RestClientApis.http_delete_and_check_success(url + db_name)
    if del_resp.success:
        return 0
    else:
        print("Failed to delete DB {}".format(url + db_name))
        return -1
Пример #11
0
def patch_base_doc(url: str, json_data: str) -> (bool, str):
    """
    Patches a base document.
    :param url: URL of resource to be patched
    :param json_data: JSON data as string
    :return: success and message
    :rtype: tuple
    """
    resp = RestClientApis.http_patch_and_check_success(
        url,
        json_data,
        headers={'Content-Type': 'application/json-patch+json'})
    return resp.success, resp.message
Пример #12
0
def create_named_document(url: str,
                          db_name: str,
                          doc_name: str,
                          document: str,
                          overwrite=False) -> dict or None:
    """

    :param overwrite: Should we create a new revision if doc exists?
    :param url: couchDB base URL in format http://host:port/
    :param db_name:name of db
    :param doc_name: document name
    :param document: document as a json string
    :return: Json body as dict or None
    """
    doc_url = url + db_name + "/" + doc_name
    if overwrite:
        get_resp = RestClientApis.http_get_and_check_success(doc_url)
        if get_resp.http_status == HTTPStatus.OK:
            rev = get_resp.json_body["_rev"]
            rev_json = '"_rev":"{}",'.format(rev)
            document = document.replace('{', '{' + rev_json, 1)
        elif get_resp.http_status == HTTPStatus.NOT_FOUND:
            # If document does not exist we continue and add it
            print("Overwrite requested but document does not exist \n")
        elif get_resp.http_status == HTTPStatus.UNAUTHORIZED:
            print("Overwrite requested but not enough permissions \n")
            return None
        else:
            print("Error reading doc_id {}. HTTP Code {}".format(
                doc_url, get_resp.http_status))
            return None
    put_resp = RestClientApis.http_put_and_check_success(doc_url, document)
    if put_resp.http_status == HTTPStatus.CREATED:
        return put_resp.json_body
    else:
        print("Failed to save doc_id {}, doc {}. HTTP Code: {}".format(
            doc_url, document, put_resp.http_status))
        return None
Пример #13
0
def execute_adhoc_query(url: str,
                        query_string: str = None) -> (bool, str, dict):
    """
    Executed an ad-hoc query
    :param query_string: Everything after the ?=
    :param url: URL for query that includes the query string
    :return: success, message and json body as dict
    :rtype: tuple(bool, str, dict)
    """
    if query_string:
        enc_query_string = urllib.parse.quote_plus(query_string)
        url = url + "?q=" + enc_query_string
    resp_obj = RestClientApis.http_get_and_check_success(url)
    return resp_obj.success, resp_obj.message, resp_obj.json_body
Пример #14
0
def create_opa_policy(url, file_path):
    """
    This function creates a OPA policy on the server
    :param url: url address where policy is placed
    :param file_path: .rego file path
    :return: Rest Return
    """
    policy_resp = None
    with open(file_path, 'r') as file:
        policy_data = file.read()
        policy_resp = RestClientApis.http_put_and_check_success(url,
                                                                policy_data, headers={'Content-Type': 'text/plain'},
                                                                params={'file': file_path})
        if policy_resp.http_status != HTTPStatus.OK:
            raise exceptions.HTTPError(policy_resp.message)
    return policy_resp
Пример #15
0
def get_named_document(url: str, db_name: str, doc_name: str) -> dict or None:
    """
    Retrieve the named document
    :param url: couchDB base URL in format http://host:port/
    :param db_name:name of db
    :param doc_name: document name
    :return: document as json dict or None
    """
    doc_url = url + db_name + "/" + doc_name
    get_resp = RestClientApis.http_get_and_check_success(doc_url)
    if get_resp.http_status == HTTPStatus.OK:
        return get_resp.json_body
    else:
        print("Failed to read doc_id {}. HTTP Code: {}".format(
            doc_url, get_resp.http_status))
        return None
Пример #16
0
def create_db(url, db_name, overwrite=False):
    """
    Creates a DB in couchDB. We return success if db was created or already exists.
    :param overwrite: whether to overwrite db if it exists
    :param url: couchDB base URL in format http://host:port/
    :param db_name:  name of db to be created
    :return: boolean
    """
    if overwrite:
        delete_db(url, db_name)
    put_resp = RestClientApis.http_put_and_check_success(url + db_name, "{}")
    if put_resp.http_status == HTTPStatus.CREATED or \
            put_resp.http_status == HTTPStatus.PRECONDITION_FAILED:
        return 0
    else:
        print("Failed to create DB {}".format(url + db_name))
        return -1
Пример #17
0
def create_watch(url: str) -> (bool, str, OpaWatch):
    """
    Creates a watch in OPA. Watches are persistent connections and changes to the watch points
    are streamed back through chunked-encoding.
    :param url: URL for resource to watch
    :return: success, message, OpaWatch class
    :rtype: tuple(bool, message, OpaWatch)
    """
    orig_url = url
    url = url + WATCH_QUERY_STRING
    resp_obj = RestClientApis.http_get_and_check_success(url,
                                                         stream=True,
                                                         timeout=(2.0, None))
    p = Process(target=process_watch_stream, args=(resp_obj.response_object, ))
    p.start()
    opa_watch = OpaWatch(orig_url, p, p.pid)
    return resp_obj.success, resp_obj.message, opa_watch
Пример #18
0
    def create_policy(self, name: str, rego_policy) -> Policy:
        """
        Policy creation invokes PUT request to an OPA server and returns a policy object
        :param name: name of policy; allows '/'
        :type name: str
        :param rego_policy: blob policy in REGO language
        :type rego_policy: str or file handler
        :return: policy object
        :rtype: Policy
        """
        def validate():
            """
            validation function for name parameter
            :rtype: void
            """
            words = name.split('/')
            valid_words = [x for x in words if x.isalpha() or '_' in x]
            if len(words) != len(valid_words):
                raise OPAValidationError(
                    'only slashes, underscores and letters are acceptable in policy name'
                )

        validate()
        policy_url = self.base + 'policies/' + name
        rego_policy = get_policy_blob(rego_policy)

        rest_response = RestClientApis.http_put_and_check_success(
            policy_url, rego_policy, headers={'Content-Type': 'text/plain'})

        rest_json = rest_response.json_body
        if rest_response.http_status == HTTPStatus.BAD_REQUEST and rest_json.get(
                'code') == INVALID_REGO_ERROR:
            raise OPAValidationError(
                str(rest_json.get('errors', 'Invalid or Empty REGO')))

        if rest_response.http_status == HTTPStatus.OK and not rest_json:
            return Policy(policy_name=name,
                          policy_path=policy_url,
                          rego_contents=rego_policy)
Пример #19
0
def delete_policy(url: str, debug=False) -> (bool, str, dict):
    if debug:
        url = url + DEBUG_QUERY_STRING
    resp = RestClientApis.http_delete_and_check_success(url)
    return resp.success, resp.message, resp.json_body
Пример #20
0
    os.makedirs(hackathon_data_dir)

with open("bearer.txt", "r+") as bearer_f:
    bearer = bearer_f.read()

server_urls_instance = ServerUrls().get_instance()
hackaton_globals = HackathonGlobals()
hackaton_globals.data_dir = hackathon_data_dir
file_name = "test_up.txt"
src_file_full_path = os.path.join(hackaton_globals.data_dir, file_name)
magen_file = open(src_file_full_path, 'w+')
magen_file.write("this is a test")
magen_file.close()
post_json = json.loads(SIN_MAGEN_INGESTION_POST_WITH_EMPTY_DOWNLOAD_URL)

get_resp_obj = RestClientApis.http_get_and_check_success(
    server_urls_instance.ingestion_server_check_url)
get_resp_json_obj = get_resp_obj.json_body
in_docker = get_resp_json_obj["response"]["docker"]
if in_docker:
    # If ingestion is running inside docker, we need to use the destination volume as file url.
    src_file_full_path = "/opt/data/" + file_name
post_json["asset"][0]["download_url"] = "file://" + src_file_full_path

post_resp_obj = RestClientApis.http_post_and_check_success(
    server_urls_instance.ingestion_server_asset_url, json.dumps(post_json))
post_resp_json_obj = post_resp_obj.json_body
container_file_path = post_resp_json_obj["response"]["asset"][
    "file_path"] + ".html"
container_file_name = file_name + ".html"
if in_docker:
    # Overwrite returned docker file path with the source volume so that it has significance.
Пример #21
0
def delete_policy(url):
    resp = RestClientApis.http_delete_and_check_success(url)
    if resp.http_status != HTTPStatus.OK:
        raise exceptions.HTTPError(resp.message)
    return
Пример #22
0
def main(args):
    #: setup parser -----------------------------------------------------------
    parser = argparse.ArgumentParser(description='Magen IO Server',
                                     usage=("\npython3 server.py "
                                            "--csrf"
                                            "--clean-init"
                                            "--ingestion-data-dir"
                                            "\n\nnote:\n"
                                            "root privileges are required "))

    if inside_docker():
        ingestion_data_dir = os.path.join("/opt", "data")
    else:
        home_dir = str(Path.home())
        ingestion_data_dir = os.path.join(home_dir, "magen_data", "ingestion")

    parser.add_argument('--ingestion-data-dir',
                        default=ingestion_data_dir,
                        help='Set directory for data files'
                        'Default is %s' % ingestion_data_dir)

    parser.add_argument('--clean-init',
                        action='store_false',
                        help='Clean All data when initializing'
                        'Default is to clean)')

    parser.add_argument('--csrf',
                        action='store_true',
                        help='Enable Cross Request Forgery protection'
                        'Default is to not use it)')

    parser.add_argument('--test',
                        action='store_true',
                        help='Run server in test mode. Used for unit tests'
                        'Default is to run in production mode)')

    #: parse CMD arguments ----------------------------------------------------
    # args = parser.parse_args()
    args, _ = parser.parse_known_args(args)
    """ Main Magen.io Sever """
    home_dir = str(Path.home())

    ingestion_globals = IngestionGlobals()
    ingestion_globals.data_dir = args.ingestion_data_dir

    try:
        os.makedirs(ingestion_globals.data_dir)
    except OSError as e:
        if e.errno != errno.EEXIST:
            raise

    # Starting OPA server
    docker_client = docker.from_env()
    # if there is no image we pull it
    try:
        opa_image = docker_client.images.get("openpolicyagent/opa")
    except NotFound as e:
        opa_image = docker_client.images.pull("openpolicyagent/opa",
                                              tag="latest")

    assert opa_image is not None

    # if container is not running we will start it
    try:
        opa_container = docker_client.containers.get("magen_opa")
        if opa_container.status == "exited" or opa_container.status == "created":
            opa_container.remove()
            raise NotFound("Container Exited or could not be started")
    except NotFound as e:
        print("OPA docker container not found or not running, starting... \n")
        opa_container = docker_client.containers.run(
            "openpolicyagent/opa",
            command="run --server --log-level=debug",
            name="magen_opa",
            ports={"8181/tcp": 8181},
            detach=True)
        time.sleep(5)

    assert opa_container.status == "running" or (
        opa_container.status == "created"
        and not opa_container.attrs["State"]["Error"])

    ks_args = [[]]
    ks_process = Process(target=ks_server.main, args=ks_args)
    ks_process.start()
    time.sleep(2)
    serverurls = ServerUrls()
    ks_check_url = serverurls.key_server_base_url + "check/"
    get_resp_obj = RestClientApis.http_get_and_check_success(ks_check_url)
    assert get_resp_obj.success is True

    mongo_ip, mongo_port = mongo_host_port()

    # We initialize at runtime everything about Mongo and its functions
    # Any client of the API can change it later

    db = MainDb.get_instance()
    db.core_database = MongoCore.get_instance()
    db.core_database.utils_strategy = MongoUtils.get_instance()
    db.core_database.asset_strategy = MongoAsset.get_instance()
    db.core_database.db_ip_port = '{ip}:{port}'.format(ip=mongo_ip,
                                                       port=mongo_port)
    db.core_database.utils_strategy.check_db(db.core_database.db_ip_port)
    db.core_database.initialize()

    if args.clean_init:
        success, _ = AssetDbApi.delete_all()
        assert success is True
        user_api.drop_user_collection()
        GridFsApi.delete_all()

    if args.csrf:
        app.config['WTF_CSRF_ENABLED'] = True
        app.config['WTF_CSRF_SECRET_KEY'] = token_hex(16)
        CSRFProtect(app)
    else:
        app.config['WTF_CSRF_ENABLED'] = False

    app.register_blueprint(main_bp)
    app.register_blueprint(users_bp)
    app.register_blueprint(ingestion_file_upload_bp,
                           url_prefix='/magen/ingestion/v2')
    app.register_blueprint(ingestion_bp_v2, url_prefix='/magen/ingestion/v2')
    app.register_blueprint(ingestion_bp, url_prefix='/magen/ingestion/v2')
    app.run('0.0.0.0', 5005, threaded=True)