Skip to content

Commit 4a288ce

Browse files
download server CA cert for tests (GoogleCloudPlatform#9086)
* download server CA cert for tests * add note to connect_tcp * remove raise_for_status * debug print response * refresh invalid credential * linting * Update connection_test.py --------- Co-authored-by: Jack Wotherspoon <jackwoth@google.com>
1 parent e8e8b4e commit 4a288ce

4 files changed

Lines changed: 53 additions & 2 deletions

File tree

cloud-sql/sql-server/sqlalchemy/connect_connector.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,24 @@ def connect_with_connector() -> sqlalchemy.engine.base.Engine:
4141

4242
connector = Connector(ip_type)
4343

44+
connect_args = {}
45+
# If your SQL Server instance requires SSL, you need to download the CA
46+
# certificate for your instance and include cafile={path to downloaded
47+
# certificate} and validate_host=False. This is a workaround for a known issue.
48+
if os.environ.get("DB_ROOT_CERT"): # e.g. '/path/to/my/server-ca.pem'
49+
connect_args = {
50+
"cafile" : os.environ["DB_ROOT_CERT"],
51+
"validate_host": False,
52+
}
53+
4454
def getconn() -> pytds.Connection:
4555
conn = connector.connect(
4656
instance_connection_name,
4757
"pytds",
4858
user=db_user,
4959
password=db_pass,
5060
db=db_name,
61+
**connect_args
5162
)
5263
return conn
5364

cloud-sql/sql-server/sqlalchemy/connect_tcp.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ def connect_tcp_socket() -> sqlalchemy.engine.base.Engine:
4040
# For deployments that connect directly to a Cloud SQL instance without
4141
# using the Cloud SQL Proxy, configuring SSL certificates will ensure the
4242
# connection is encrypted.
43+
44+
# If your SQL Server instance requires SSL, you need to download the CA
45+
# certificate for your instance and include cafile={path to downloaded
46+
# certificate} and validate_host=False, even when using the proxy.
47+
# This is a workaround for a known issue.
4348
if os.environ.get("DB_ROOT_CERT"): # e.g. '/path/to/my/server-ca.pem'
4449
connect_args = {
4550
"cafile" : os.environ["DB_ROOT_CERT"],

cloud-sql/sql-server/sqlalchemy/connection_test.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,21 @@
1616
import os
1717

1818
from flask.testing import FlaskClient
19-
19+
from google.auth import default
20+
import google.auth.transport.requests
2021
import pytest
22+
import requests
2123

2224
import app
2325

2426
logger = logging.getLogger()
2527

2628

29+
CA_FILENAME = "certs/ca.pem"
30+
SQLADMIN_API_ENDPOINT = "https://sqladmin.googleapis.com"
31+
SQLADMIN_API_VERSION = "v1beta4"
32+
33+
2734
# load proper environment variables
2835
def setup_test_env():
2936
os.environ["DB_USER"] = os.environ["SQLSERVER_USER"]
@@ -33,6 +40,32 @@ def setup_test_env():
3340
os.environ["INSTANCE_HOST"] = os.environ["SQLSERVER_INSTANCE_HOST"]
3441
os.environ["INSTANCE_CONNECTION_NAME"] = os.environ["SQLSERVER_INSTANCE"]
3542

43+
project, _, instance = os.environ["INSTANCE_CONNECTION_NAME"].split(":")
44+
download_ca_cert(project, instance)
45+
os.environ["DB_ROOT_CERT"] = CA_FILENAME
46+
47+
48+
def download_ca_cert(project, instance):
49+
""" Download server CA cert"""
50+
scopes = ["https://www.googleapis.com/auth/sqlservice.admin"]
51+
credentials, _ = default(scopes=scopes)
52+
53+
if not credentials.valid:
54+
request = google.auth.transport.requests.Request()
55+
credentials.refresh(request)
56+
57+
headers = {
58+
"Authorization": f"Bearer {credentials.token}",
59+
}
60+
url = (f"{SQLADMIN_API_ENDPOINT}/sql/{SQLADMIN_API_VERSION}"
61+
f"/projects/{project}/instances/{instance}/connectSettings")
62+
63+
resp = requests.get(url, headers=headers)
64+
server_ca_cert = resp.json()["serverCaCert"]["cert"]
65+
66+
with open(CA_FILENAME, "w+") as ca_out:
67+
ca_out.write(server_ca_cert)
68+
3669

3770
@pytest.fixture(scope="module")
3871
def client() -> FlaskClient:
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
pytest==7.0.1
1+
pytest==7.0.1
2+
google-auth==2.16.0
3+
Requests==2.28.2

0 commit comments

Comments
 (0)