Skip to content

add convenience method for authenticating with astra via db_id and token #1228

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions cassandra/cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
import time
from threading import Lock, RLock, Thread, Event
import uuid
import os
import urllib.request
import json

import weakref
from weakref import WeakValueDictionary
Expand Down Expand Up @@ -1169,6 +1172,26 @@ def __init__(self,

uses_twisted = TwistedConnection and issubclass(self.connection_class, TwistedConnection)
uses_eventlet = EventletConnection and issubclass(self.connection_class, EventletConnection)

# Check if we need to download the secure connect bundle
if 'db_id' in cloud and 'token' in cloud:
# download SCB if necessary
if 'secure_connect_bundle' not in cloud:
bundle_path = f'astra-secure-connect-{cloud["db_id"]}.zip'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since each region within a given Astra DB cluster has its own SCB, how do we handle a multi-region scenario here?

if not os.path.exists(bundle_path):
print('Downloading Secure Cloud Bundle')
url = self._get_astra_bundle_url(cloud['db_id'], cloud['token'])
try:
with urllib.request.urlopen(url) as r:
with open(bundle_path, 'wb') as f:
f.write(r.read())
except urllib.error.URLError as e:
raise Exception(f"Error downloading secure connect bundle: {str(e)}")
cloud['secure_connect_bundle'] = bundle_path
# Set up auth_provider if not provided
if auth_provider is None:
auth_provider = PlainTextAuthProvider('token', cloud['token'])

cloud_config = dscloud.get_cloud_config(cloud, create_pyopenssl_context=uses_twisted or uses_eventlet)

ssl_context = cloud_config.ssl_context
Expand Down Expand Up @@ -2184,6 +2207,29 @@ def get_control_connection_host(self):
endpoint = connection.endpoint if connection else None
return self.metadata.get_host(endpoint) if endpoint else None

@staticmethod
def _get_astra_bundle_url(db_id, token):
# set up the request
url = f"https://api.astra.datastax.com/v2/databases/{db_id}/secureBundleURL"
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json"
}

req = urllib.request.Request(url, method="POST", headers=headers, data=b"")
try:
with urllib.request.urlopen(req) as response:
response_data = json.loads(response.read().decode())
# happy path
if 'downloadURL' in response_data:
return response_data['downloadURL']
# handle errors
if 'errors' in response_data:
raise Exception(response_data['errors'][0]['message'])
raise Exception('Unknown error in ' + str(response_data))
except urllib.error.URLError as e:
raise Exception(f"Error connecting to Astra API: {str(e)}")

def refresh_schema_metadata(self, max_schema_agreement_wait=None):
"""
Synchronously refresh all schema metadata.
Expand Down