From 7b8dbf540908373515973186e49e6c5382abddaf Mon Sep 17 00:00:00 2001 From: Anthony Mahanna Date: Wed, 17 Jan 2024 15:54:55 -0500 Subject: [PATCH 1/8] DE-741 | initial commit --- arango/database.py | 54 ++++++++++++++++++++++++++++++++++++++++++ arango/exceptions.py | 8 +++++++ tests/test_database.py | 9 +++++++ 3 files changed, 71 insertions(+) diff --git a/arango/database.py b/arango/database.py index e33bd5ae..8f3b3c37 100644 --- a/arango/database.py +++ b/arango/database.py @@ -40,6 +40,8 @@ PermissionListError, PermissionResetError, PermissionUpdateError, + ServerAvailableOptionsGetError, + ServerCurrentOptionsGetError, ServerDetailsError, ServerEchoError, ServerEncryptionError, @@ -933,6 +935,58 @@ def response_handler(resp: Response) -> Json: return self._execute(request, response_handler) + def options(self) -> Result[Json]: + """Return the currently-set server options. + + As this API may reveal sensitive data about the deployment, it can only + be accessed from inside the _system database. In addition, there is a + policy control startup option --server.options-api that determines if and + to whom the API is made available. This option can have the following + values: + - disabled: API is disabled. + - jwt: API can only be accessed via superuser JWT. + - admin: API can be accessed by admin users in the _system database only. + - public: everyone with access to _system database can access the API. + + :return: Server options. + :rtype: dict + """ + request = Request(method="get", endpoint="/_admin/options") + + def response_handler(resp: Response) -> Json: + if resp.is_success: + result: Json = resp.body + return result + raise ServerCurrentOptionsGetError(resp, request) + + return self._execute(request, response_handler) + + def options_available(self) -> Result[Json]: + """Return a description of all available server options. + + As this API may reveal sensitive data about the deployment, it can only + be accessed from inside the _system database. In addition, there is a + policy control startup option --server.options-api that determines if and + to whom the API is made available. This option can have the following + values: + - disabled: API is disabled. + - jwt: API can only be accessed via superuser JWT. + - admin: API can be accessed by admin users in the _system database only. + - public: everyone with access to _system database can access the options API. + + :return: Server options. + :rtype: dict + """ + request = Request(method="get", endpoint="/_admin/options-description") + + def response_handler(resp: Response) -> Json: + if resp.is_success: + result: Json = resp.body + return result + raise ServerAvailableOptionsGetError(resp, request) + + return self._execute(request, response_handler) + ####################### # Database Management # ####################### diff --git a/arango/exceptions.py b/arango/exceptions.py index fb11f8d5..e03ec95a 100644 --- a/arango/exceptions.py +++ b/arango/exceptions.py @@ -698,6 +698,14 @@ class ServerEncryptionError(ArangoServerError): """Failed to reload user-defined encryption keys.""" +class ServerCurrentOptionsGetError(ArangoServerError): + """Failed to retrieve currently-set server options.""" + + +class ServerAvailableOptionsGetError(ArangoServerError): + """Failed to retrieve available server options.""" + + ##################### # Task Exceptions # ##################### diff --git a/tests/test_database.py b/tests/test_database.py index da6307a4..94db3b68 100644 --- a/tests/test_database.py +++ b/tests/test_database.py @@ -373,3 +373,12 @@ def test_license(sys_db, enterprise): assert license == {"license": "none"} with pytest.raises(ServerLicenseSetError): sys_db.set_license("abc") + + +def test_options(sys_db, db_version): + # Skip if below 3.12 + if db_version < version.parse("3.12.0"): + pytest.skip("Database options require ArangoDB 3.12+") + + assert sys_db.options() + assert sys_db.options_available() From 85e12669c27511e5deaf47d65e07b78d9ae7227f Mon Sep 17 00:00:00 2001 From: Anthony Mahanna Date: Wed, 17 Jan 2024 16:02:34 -0500 Subject: [PATCH 2/8] doc: update docstrings --- arango/database.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arango/database.py b/arango/database.py index 8f3b3c37..e15d2e07 100644 --- a/arango/database.py +++ b/arango/database.py @@ -936,7 +936,7 @@ def response_handler(resp: Response) -> Json: return self._execute(request, response_handler) def options(self) -> Result[Json]: - """Return the currently-set server options. + """Return the currently-set server options (ArangoDB 3.12+) As this API may reveal sensitive data about the deployment, it can only be accessed from inside the _system database. In addition, there is a @@ -962,7 +962,7 @@ def response_handler(resp: Response) -> Json: return self._execute(request, response_handler) def options_available(self) -> Result[Json]: - """Return a description of all available server options. + """Return a description of all available server options (ArangoDB 3.12+) As this API may reveal sensitive data about the deployment, it can only be accessed from inside the _system database. In addition, there is a From 1080b96c31a2335824169dac02602a161160b389 Mon Sep 17 00:00:00 2001 From: Anthony Mahanna Date: Mon, 22 Apr 2024 17:03:58 -0400 Subject: [PATCH 3/8] fix import --- tests/test_database.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_database.py b/tests/test_database.py index a278234b..cab4bd24 100644 --- a/tests/test_database.py +++ b/tests/test_database.py @@ -1,6 +1,7 @@ from datetime import datetime import pytest +from packaging import version from arango.aql import AQL from arango.backup import Backup From d015474e50f26c4503e8b9692e57c0947ffacb2b Mon Sep 17 00:00:00 2001 From: Anthony Mahanna Date: Mon, 22 Apr 2024 17:04:03 -0400 Subject: [PATCH 4/8] fix starter --- starter.sh | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/starter.sh b/starter.sh index d0973f37..3258d6e3 100755 --- a/starter.sh +++ b/starter.sh @@ -32,11 +32,10 @@ else exit 1 fi -conf_file="" -if [[ "${version%.*}" == "3.10" ]]; then - conf_file="${setup}-3.10" +if [ "$version" == "latest" ]; then + conf_file="${setup}-3.12" else - conf_file="${setup}" + conf_file="${setup}-${version%.*}" fi docker run -d \ From eeee55384245aad43db44781c4eeb223802bcf7a Mon Sep 17 00:00:00 2001 From: Anthony Mahanna Date: Mon, 22 Apr 2024 17:04:29 -0400 Subject: [PATCH 5/8] cleanup `.conf` files --- tests/static/{cluster.conf => cluster-3.11.conf} | 0 tests/static/cluster-3.12.conf | 14 ++++++++++++++ tests/static/{single.conf => single-3.11.conf} | 0 tests/static/single-3.12.conf | 13 +++++++++++++ 4 files changed, 27 insertions(+) rename tests/static/{cluster.conf => cluster-3.11.conf} (100%) create mode 100644 tests/static/cluster-3.12.conf rename tests/static/{single.conf => single-3.11.conf} (100%) create mode 100644 tests/static/single-3.12.conf diff --git a/tests/static/cluster.conf b/tests/static/cluster-3.11.conf similarity index 100% rename from tests/static/cluster.conf rename to tests/static/cluster-3.11.conf diff --git a/tests/static/cluster-3.12.conf b/tests/static/cluster-3.12.conf new file mode 100644 index 00000000..cf764a1d --- /dev/null +++ b/tests/static/cluster-3.12.conf @@ -0,0 +1,14 @@ +[starter] +mode = cluster +local = true +address = 0.0.0.0 +port = 8528 + +[auth] +jwt-secret = /tests/static/keyfile + +[args] +all.database.password = passwd +all.database.extended-names = true +all.log.api-enabled = true +all.server.options-api = admin \ No newline at end of file diff --git a/tests/static/single.conf b/tests/static/single-3.11.conf similarity index 100% rename from tests/static/single.conf rename to tests/static/single-3.11.conf diff --git a/tests/static/single-3.12.conf b/tests/static/single-3.12.conf new file mode 100644 index 00000000..424d809e --- /dev/null +++ b/tests/static/single-3.12.conf @@ -0,0 +1,13 @@ +[starter] +mode = single +address = 0.0.0.0 +port = 8528 + +[auth] +jwt-secret = /tests/static/keyfile + +[args] +all.database.password = passwd +all.database.extended-names = true +all.javascript.allow-admin-execute = true +all.server.options-api = admin \ No newline at end of file From 8603ab6d785161d87a13c0e6ddee9fee2a505819 Mon Sep 17 00:00:00 2001 From: Anthony Mahanna Date: Tue, 23 Apr 2024 12:09:27 -0400 Subject: [PATCH 6/8] fix: typo --- starter.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/starter.sh b/starter.sh index 3258d6e3..3716dc22 100755 --- a/starter.sh +++ b/starter.sh @@ -35,7 +35,7 @@ fi if [ "$version" == "latest" ]; then conf_file="${setup}-3.12" else - conf_file="${setup}-${version%.*}" + conf_file="${setup}-${version%.*.*}" fi docker run -d \ From dbdeb696a89eb6d74de2634309de0703e6db6258 Mon Sep 17 00:00:00 2001 From: Anthony Mahanna Date: Tue, 23 Apr 2024 12:11:06 -0400 Subject: [PATCH 7/8] Update cluster-3.12.conf --- tests/static/cluster-3.12.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/static/cluster-3.12.conf b/tests/static/cluster-3.12.conf index cf764a1d..66265420 100644 --- a/tests/static/cluster-3.12.conf +++ b/tests/static/cluster-3.12.conf @@ -11,4 +11,5 @@ jwt-secret = /tests/static/keyfile all.database.password = passwd all.database.extended-names = true all.log.api-enabled = true +all.javascript.allow-admin-execute = true all.server.options-api = admin \ No newline at end of file From cae36f36109fd1709ce4fcb960d8eb6a151308f5 Mon Sep 17 00:00:00 2001 From: Anthony Mahanna Date: Tue, 23 Apr 2024 12:13:58 -0400 Subject: [PATCH 8/8] fix eof --- tests/static/cluster-3.12.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/static/cluster-3.12.conf b/tests/static/cluster-3.12.conf index 66265420..d33e07a3 100644 --- a/tests/static/cluster-3.12.conf +++ b/tests/static/cluster-3.12.conf @@ -12,4 +12,4 @@ all.database.password = passwd all.database.extended-names = true all.log.api-enabled = true all.javascript.allow-admin-execute = true -all.server.options-api = admin \ No newline at end of file +all.server.options-api = admin