-
Notifications
You must be signed in to change notification settings - Fork 68
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
Provide samples for using Python Connector with Django #437
Comments
Any ETA on this? |
@hadim I can't really provide a precise ETA as of right now, it most likely won't be until early 2023. I have begun playing around with usage of the Python Connector and Django as is currently. However, if development work is needed to add support within Django for the Python Connector I won't be able to get around to it until the new year. If anyone here has had experience in leveraging the Python Connector with Django I'm more than happy to hear about their feedback/experience to update the Python Connector documentation accordingly with a code sample. Will ping this thread with any updates moving forward. |
Any updates on this? |
Hi @stiangrim, I've begun trying to find elegant workarounds to using the Cloud SQL Python Connector with Django as I hope to avoid having to write Django backend(s) to support the Python Connector. In the meantime if you or anyone else has had any luck feel free to post your finding here! I'm sure others would benefit greatly 😃 |
I don't know about doing it without writing a Django backend, but it turned out to be super easy to write one that supports the connector. In my case, since I was only targeting MySQL, I put this into a
and then with a DATABASES setting like this:
it Just Worked. (The Happy to contribute this as a PR to the docs. |
@danielroseman That is great news! 👏 Would be greatly appreciated if you could put up a PR adding this to the frameworks section of our README, we'd love to showcase this solution for others 😄 |
Refs GoogleCloudPlatform#437 Note, I realised while writing this that it won't work with Postgres as there's no equivalent of the `install_as_mysqldb` call; I included a note explaining this.
Writing three separate custom backends for each db engine is probably the way to go. Incidentally, this mirrors what we do in Go with three separate |
Is there any support for Postgres + Django using the cloud-sql-connector? |
You'd have to write a custom backend using pg8000 (or asyncpg) like above. I haven't tried this myself, but in theory it's possible. |
Here's one way to do it. https://github.com/rcleveng/django_gcp_iam_auth Instructions on how to install with pip on the README.md
|
Thanks, @rcleveng -- that's a nice approach. In effect it's a variation of #214 (comment). It gets you IAM authentication without the Connector. Meanwhile, we're working on improving Django support in the near term. |
Adding the code sample from the link above for posterity: import copy
from django.db.backends.postgresql import base
try:
import google.auth
import google.auth.exceptions
from google.auth.transport import requests
from google.auth.credentials import Credentials, Scoped, TokenState
except google.auth.exceptions.DefaultCredentialsError:
pass
CLOUDSQL_IAM_LOGIN_SCOPE = ["https://www.googleapis.com/auth/sqlservice.login"]
class DatabaseWrapper(base.DatabaseWrapper):
def get_connection_params(self):
params = super().get_connection_params()
# need to remove this otherwise we'll get errors like
# 'invalid dsn: invalid connection option "gcp_iam_auth"'
if params.pop("gcp_iam_auth", None):
self._credentials, _ = google.auth.default(scopes=CLOUDSQL_IAM_LOGIN_SCOPE)
if not self._credentials.token_state == TokenState.FRESH:
self._credentials.refresh(requests.Request())
params.setdefault("port", 5432)
# TODO - should we add in a resource restriction for the DB instance?
# https://cloud.google.com/iam/docs/downscoping-short-lived-credentials#auth_downscoping_token_broker-python
# Set password to newly fetched access token
params["password"] = self._credentials.token
return params |
@enocom Your comments on this thread and others has been really helpful! I'm wondering if you might have any ideas on this related issue I'm hitting. I've been trying to get the IAM auth approach to work with Django on my local machine but the connection keeps timing out. AFAICT my psycopg2.connect database url matches the format in this other thead: |
@JoshTanke Thanks for the comment on this issue. Do you mind creating a new issue on the repo with the error you are seeing? That way we can help debug your problem while keeping this thread clean 😄
Once you open a new issue with your stacktrace I'll get a better grasp of what is going on. However, yes if you have "Require trusted client certificates" turned on and are not creating a database connection using SSL with client certs (mTLS). Which by the sample above and database URL you provided you are not then I would expect it to error. You would need to download your certificates and add their path to your psycopg2 database url (this SO post does a good job explaining the psycopg2 config) Depending on your use-case and especially for Private IP connections you may be fine with turning the setting to "Allow only SSL connections". This would allow you to update your database url with
However, this still isn't ideal for Public IP connections which we are working on by adding support for psycopg2 to the Cloud SQL Python Connector soon (will be worked on this quarter) which will then also unblock Django for postgres and give users a way of using Django + Cloud SQL for "Require trusted client certificates" without having to manage certificates yourself. |
Django is one of the most widely used Python web frameworks. We should look at providing samples on how to connect to a Cloud SQL database using the Python Connector and Django.
What makes this a more difficult feat is that the default Django backend for Postgres is
psycopg2
and for MySQL ismysqlclient
ormysql-connector-python
, which are not currently supported with the Python Connector.The text was updated successfully, but these errors were encountered: