Skip to content

Commit 3be6843

Browse files
authored
Use updated authentication method for IAM Bolt queries (#438)
* Use updated authentication method for IAM Bolt queries * update changelog Co-authored-by: Michael Chin <chnmch@amazon.com>
1 parent a35b4fa commit 3be6843

File tree

3 files changed

+60
-13
lines changed

3 files changed

+60
-13
lines changed

ChangeLog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ Starting with v1.31.6, this file will contain a record of major features and upd
99
- Added support for list/tuple element access in cell variable injection ([Link to PR](https://github.com/aws/graph-notebook/pull/409))
1010
- Fixed failing endpoint creation step in [01-People-Analytics/People-Analytics-using-Neptune-ML](https://github.com/aws/graph-notebook/blob/main/src/graph_notebook/notebooks/04-Machine-Learning/Sample-Applications/01-People-Analytics/People-Analytics-using-Neptune-ML.ipynb) ([Link to PR](https://github.com/aws/graph-notebook/pull/411))
1111
- Fixed browser-specific issues with fullscreen graph widget ([Link to PR](https://github.com/aws/graph-notebook/pull/427))
12+
- Fixed IAM authenticated Bolt queries failing on certain Neptune engine versions ([Link to PR](https://github.com/aws/graph-notebook/pull/438))
1213
- Pinned `numpy<1.24.0` to fix conflicts with `networkx` dependency during installation ([Link to PR](https://github.com/aws/graph-notebook/pull/416))
1314
- Excluded certain `itables` versions causing errors in query magics ([PR #1](https://github.com/aws/graph-notebook/pull/429)) ([PR #2](https://github.com/aws/graph-notebook/pull/429))
1415
- Pinned version ceiling for all dependencies ([Link to PR](https://github.com/aws/graph-notebook/pull/431))
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import json
2+
3+
from neo4j import Auth
4+
from botocore.awsrequest import AWSRequest
5+
from botocore.credentials import Credentials
6+
from botocore.compat import urlsplit
7+
from botocore.auth import SigV4Auth
8+
9+
SCHEME = "basic"
10+
REALM = "realm"
11+
SERVICE_NAME = "neptune-db"
12+
DUMMY_USERNAME = "username"
13+
HTTP_METHOD_HDR = "HttpMethod"
14+
HTTP_METHOD = "GET"
15+
AUTHORIZATION = "Authorization"
16+
X_AMZ_DATE = "X-Amz-Date"
17+
X_AMZ_SECURITY_TOKEN = "X-Amz-Security-Token"
18+
HOST = "Host"
19+
20+
21+
class NeptuneBoltAuthToken(Auth):
22+
def __init__(
23+
self,
24+
credentials: Credentials,
25+
region: str,
26+
url: str,
27+
**parameters
28+
):
29+
request = AWSRequest(method=HTTP_METHOD, url=url)
30+
31+
url_parts = urlsplit(request.url)
32+
host_part = url_parts.hostname
33+
request.headers.add_header("Host", host_part)
34+
sigv4 = SigV4Auth(credentials, SERVICE_NAME, region)
35+
sigv4.add_auth(request)
36+
37+
auth_obj = {
38+
hdr: request.headers[hdr]
39+
for hdr in [AUTHORIZATION, X_AMZ_DATE, X_AMZ_SECURITY_TOKEN, HOST]
40+
}
41+
auth_obj[HTTP_METHOD_HDR] = request.method
42+
creds: str = json.dumps(auth_obj)
43+
super().__init__(SCHEME, DUMMY_USERNAME, creds, REALM, **parameters)

src/graph_notebook/neptune/client.py

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
from base64 import b64encode
2222
import nest_asyncio
2323

24+
from graph_notebook.neptune.bolt_auth_token import NeptuneBoltAuthToken
25+
2426

2527
# This patch is no longer needed when graph_notebook is using the a Gremlin Python
2628
# client >= 3.5.0 as the HashableDict is now part of that client driver.
@@ -391,22 +393,23 @@ def get_opencypher_driver(self):
391393
url = f'bolt://{self.host}:{self.port}'
392394

393395
if self.is_neptune_domain():
394-
user = DEFAULT_NEO4J_USERNAME
395396
if self._session:
396-
method = 'POST'
397-
headers = {
398-
'HttpMethod': method,
399-
'Host': url
400-
}
401-
aws_request = self._get_aws_request('POST', url)
402-
for item in aws_request.headers.items():
403-
headers[item[0]] = item[1]
404-
405-
auth_str = json.dumps(headers)
406-
password = auth_str
397+
# check engine version via status API to determine if we need the OC endpoint path
398+
status_res = self.status()
399+
status_res.raise_for_status()
400+
status_res_json = status_res.json()
401+
engine_version_raw = status_res_json["dbEngineVersion"]
402+
engine_version = int(engine_version_raw.rsplit('.', 1)[0].replace('.', ''))
403+
if engine_version >= 1200:
404+
url += "/opencypher"
405+
406+
credentials = self._session.get_credentials()
407+
frozen_creds = credentials.get_frozen_credentials()
408+
auth_final = NeptuneBoltAuthToken(frozen_creds, self.region, url)
407409
else:
410+
user = 'username'
408411
password = DEFAULT_NEO4J_PASSWORD
409-
auth_final = (user, password)
412+
auth_final = (user, password)
410413
else:
411414
if self.neo4j_auth:
412415
auth_final = (self.neo4j_username, self.neo4j_password)

0 commit comments

Comments
 (0)