Skip to content

Commit d86cc83

Browse files
committed
Test for Nebius credentials
1 parent 459b888 commit d86cc83

File tree

1 file changed

+78
-21
lines changed

1 file changed

+78
-21
lines changed

tests/auth/test_credentials.py

Lines changed: 78 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
import concurrent.futures
33
import grpc
44
import time
5+
import http.server
6+
import urllib
7+
import threading
8+
import json
59

610
import ydb.iam
711

@@ -14,7 +18,7 @@
1418
PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu+fyUt6zHCycbxYKTsxe\nftoB/mIoN0RNjE5fbsAtAWSgL+n6GK+8csEMliCvltXAYc/EeC3xZmaNozNGgr3U\nZjQXVtBA0k5xy8QrBYaEFi1avmyOX+Y85HKIoqFLWhKQAz6sIFVC1bTf55zyYmev\n3VN9At45kevi1IBJ7VLVrd3qt8UCJ+ZRt8wtZJQWPx8bXx+R7vMQb8EUEyZ4d1KT\ny4/F8Epq4g4Ha4Ue6OrplslbhqzCpSx5nor5X842LX8ztTDiDBvLdv88RkfsW+Fc\nJLO97B9Sq7h/9PyTF1Pe56cKXvlJvrl4aZXT8oBhKxImu2m8mQdoDKV6q1mCjKNN\njQIDAQAB\n-----END PUBLIC KEY-----\n"
1519

1620

17-
def test_credentials():
21+
def test_metadata_credentials():
1822
credentials = ydb.iam.MetadataUrlCredentials()
1923
raised = False
2024
try:
@@ -48,29 +52,14 @@ def __init__(self):
4852
self.server.start()
4953

5054
def stop(self):
55+
self.server.stop(1)
5156
self.server.wait_for_termination()
5257

5358
def get_endpoint(self):
5459
return "[::]:54321"
5560

5661

5762
class TestServiceAccountCredentials(ydb.iam.ServiceAccountCredentials):
58-
def __init__(
59-
self,
60-
service_account_id,
61-
access_key_id,
62-
private_key,
63-
iam_endpoint=None,
64-
iam_channel_credentials=None,
65-
):
66-
super(TestServiceAccountCredentials, self).__init__(
67-
service_account_id,
68-
access_key_id,
69-
private_key,
70-
iam_endpoint,
71-
iam_channel_credentials,
72-
)
73-
7463
def _channel_factory(self):
7564
return grpc.insecure_channel(
7665
self._iam_endpoint
@@ -80,12 +69,80 @@ def get_expire_time(self):
8069
return self._expires_in - time.time()
8170

8271

83-
def test_service_account_credentials():
72+
class TestNebiusServiceAccountCredentials(ydb.iam.NebiusServiceAccountCredentials):
73+
def get_expire_time(self):
74+
return self._expires_in - time.time()
75+
76+
77+
class NebiusTokenServiceHandler(http.server.BaseHTTPRequestHandler):
78+
def do_POST(self):
79+
assert self.headers["Content-Type"] == "application/x-www-form-urlencoded"
80+
assert self.path == "/token/exchange"
81+
content_length = int(self.headers["Content-Length"])
82+
post_data = self.rfile.read(content_length).decode("utf8")
83+
print("NebiusTokenServiceHandler.POST data: {}".format(post_data))
84+
parsed_request = urllib.parse.parse_qs(str(post_data))
85+
assert len(parsed_request["grant_type"]) == 1
86+
assert parsed_request["grant_type"][0] == "urn:ietf:params:oauth:grant-type:token-exchange"
87+
88+
assert len(parsed_request["requested_token_type"]) == 1
89+
assert parsed_request["requested_token_type"][0] == "urn:ietf:params:oauth:token-type:access_token"
90+
91+
assert len(parsed_request["subject_token_type"]) == 1
92+
assert parsed_request["subject_token_type"][0] == "urn:ietf:params:oauth:token-type:jwt"
93+
94+
assert len(parsed_request["subject_token"]) == 1
95+
jwt_token = parsed_request["subject_token"][0]
96+
decoded = jwt.decode(jwt_token, key=PUBLIC_KEY, algorithms=["RS256"], audience="token-service.iam.new.nebiuscloud.net")
97+
assert decoded["iss"] == SERVICE_ACCOUNT_ID
98+
assert decoded["sub"] == SERVICE_ACCOUNT_ID
99+
assert decoded["aud"] == "token-service.iam.new.nebiuscloud.net"
100+
assert abs(decoded["iat"] - time.time()) <= 60
101+
assert abs(decoded["exp"] - time.time()) <= 3600
102+
103+
response = {
104+
"access_token": "test_nebius_token",
105+
"issued_token_type": "urn:ietf:params:oauth:token-type:access_token",
106+
"token_type": "Bearer",
107+
"expires_in": 42
108+
}
109+
110+
self.send_response(200)
111+
self.send_header("Content-type", "application/json")
112+
self.end_headers()
113+
self.wfile.write(json.dumps(response).encode("utf8"))
114+
115+
116+
class NebiusTokenServiceForTest(http.server.HTTPServer):
117+
def __init__(self):
118+
http.server.HTTPServer.__init__(self, ("localhost", 54322), NebiusTokenServiceHandler)
119+
120+
def endpoint(self):
121+
return "http://localhost:54322/token/exchange"
122+
123+
124+
def test_yandex_service_account_credentials():
84125
server = IamTokenServiceTestServer()
85-
iam_endpoint = server.get_endpoint()
86-
grpc_channel_creds = grpc.local_channel_credentials()
87-
credentials = TestServiceAccountCredentials(SERVICE_ACCOUNT_ID, ACCESS_KEY_ID, PRIVATE_KEY, iam_endpoint, grpc_channel_creds)
126+
credentials = TestServiceAccountCredentials(SERVICE_ACCOUNT_ID, ACCESS_KEY_ID, PRIVATE_KEY, server.get_endpoint())
88127
credentials.set_token_expiration_timeout(1)
89128
t = credentials.get_auth_token()
90129
assert t == "test_token"
91130
assert credentials.get_expire_time() <= 42
131+
server.stop()
132+
133+
134+
def test_nebius_service_account_credentials():
135+
server = NebiusTokenServiceForTest()
136+
137+
def serve(s):
138+
s.handle_request()
139+
140+
serve_thread = threading.Thread(target=serve, args=(server,))
141+
serve_thread.start()
142+
143+
credentials = TestNebiusServiceAccountCredentials(SERVICE_ACCOUNT_ID, ACCESS_KEY_ID, PRIVATE_KEY, server.endpoint())
144+
t = credentials.get_auth_token()
145+
assert t == "test_nebius_token"
146+
assert credentials.get_expire_time() <= 42
147+
148+
serve_thread.join()

0 commit comments

Comments
 (0)