Hello,
I'm relatively new to Google Cloud software, and despite my efforts to thoroughly read through the documentation, I find myself unable to access my MySQL database on Google Cloud. To provide some context, I hope this information will help clarify my issue.
I'm tasked with creating access to a MySQL database on Google Cloud for the employees of a company. I've created an instance with a private IP and configured a service account with all the necessary roles and permissions, which I intend to use to grant access to the database to the workers. Additionally, I've set up a VPC network and connected the Cloud SQL Instance to this VPC, as well as authorizing my local IP to connect. As of now, I haven't configured a Google Cloud VPN or a tunnel with my local network. My initial question is: Do I need to have a VPN IPsec for my local network in order to allow communication between my Cloud SQL instance and my local network?
At present, I can't configured a VPN IPsec in my local network, and assuming it was necessary, I temporarily switched my Cloud SQL instance to public, just long enough to establish a successful connection. My hope was that this would simplify the process for connecting to my database. I've set up some firewall rules to only allow communication from my local IP to my instance. I attempted to connect to my database using the following Python script (adapted from documentation):
'''
def connect_with_connector() -> sqlalchemy.engine.base.Engine:
"""
Initializes a connection pool for a Cloud SQL instance of MySQL.
Uses the Cloud SQL Python Connector package.
"""
# Note: Saving credentials in environment variables is convenient, but not
# secure - consider a more secure solution such as
# Cloud Secret Manager (https://cloud.google.com/secret-manager) to help
# keep secrets safe.
load_dotenv()
instance_connection_name = os.getenv("INSTANCE_CONNECTION_NAME")
db_user = os.getenv("DB_USER")
db_pass = os.getenv("DB_PASS")
db_name = os.getenv("DB_NAME")
credential_path = os.getenv("CREDENTIAL_PATH")
credential, _ = load_credentials_from_file(credential_path)
# Chemins des fichiers SSL
ssl_ca = os.getenv("SSL_CA") # Chemin vers le fichier server-ca.pem
ssl_cert = os.getenv("SSL_CERT") # Chemin vers le fichier client-cert.pem
ssl_key = os.getenv("SSL_KEY") # Chemin vers le fichier client-key.pem
ssl_args = {
'ssl': {
'ca': ssl_ca,
'cert': ssl_cert,
'key': ssl_key
}
}
# ip_type = IPTypes.PRIVATE if private_ip else IPTypes.PUBLIC
ip_type = IPTypes.PUBLIC
connector = Connector(ip_type)
def getconn() -> pymysql.connections.Connection:
conn: pymysql.connections.Connection = connector.connect(
instance_connection_name,
"pymysql",
user=db_user,
db=db_name,
**ssl_args
)
return conn
pool = sqlalchemy.create_engine(
"mysql+pymysql://",
creator=getconn,
pool_size=5, # Taille de la pool de connexions
max_overflow=2, # Nombre maximal de connexions supplémentaires autorisées
pool_timeout=30, # Délai d'attente maximum pour obtenir une connexion
pool_recycle=1800, # Durée de vie maximale d'une connexion en secondes
)
return pool
As I intend to connect with a service account (as it aligns with the final use case), I executed the following command to set up Application Default Credentials (ADC):
gcloud auth application-default login --impersonate-service-account SERVICE_ACCT_EMAIL
gcloud config set auth/impersonate_service_account gcloud auth application-default login --impersonate-service-account SERVICE_ACCT_EMAIL
This provided me with a credential file, which I then set the path to in the environment variable GOOGLE_APPLICATION_CREDENTIALS. I've managed to grant all the necessary permissions to the service account. Below is the list of permissions:
I acknowledge that these permissions may be excessive for my needs, but I'll address that once I'm able to connect to my database. Additionally, as mentioned earlier, I've added firewall rules to:
The fact is, as I'm learning these concepts while implementing them, and feeling a bit desperate, I also attempted to connect using Google Cloud Proxy and other methods, which may have affected my configuration.
To conclude, I'm encountering the following error message:
sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (1045, "Access denied for user 'serviceaccountusername’ @'cloudsqlproxy~’localIP' (using password: NO)")
(Background on this error at: URL Removed by Staff)
I'm not using a password because I'm attempting to connect with a service account, and I have the credential file. I've triple-checked information such as db_user, db_name, instance_connection_name, as well as ssl_certificate (I read after attempting that it may be unnecessary when connecting using the Python Connector).
I'm struggling to identify the origin of the error and, consequently, the solution. Is there something essential that I might have overlooked? Or perhaps something I'm doing incorrectly?
Thank you for your assistance.
Solved! Go to Solution.
Hello @pol_rouxel,
Welcome to the Google Cloud Community!
Your error message suggests that the user 'serviceaccountusername' is unable to connect from the 'cloudsqlproxy~localIP'. To resolve this, try the following steps:
1. Ensure the service account is assigned the "cloudsql.client" role, which is necessary for connecting to Cloud SQL instances. You can find more information here: cloudsql.client role. This role allows the service account to connect to Cloud SQL instances.
2. Verify that the 'db_user' variable in your script uses the Cloud SQL username, not the service account email.
3. Check that the host in your connection settings is correct. The error message mentions `"cloudsqlproxy~'localIP'" as the host. It should be the public IP address of your Cloud SQL instance for a public connection, or the private IP address if using a private network.
If you're still encountering issues after these steps, its best to consider reaching out to our Google Cloud Support.
Hello @pol_rouxel,
Welcome to the Google Cloud Community!
Your error message suggests that the user 'serviceaccountusername' is unable to connect from the 'cloudsqlproxy~localIP'. To resolve this, try the following steps:
1. Ensure the service account is assigned the "cloudsql.client" role, which is necessary for connecting to Cloud SQL instances. You can find more information here: cloudsql.client role. This role allows the service account to connect to Cloud SQL instances.
2. Verify that the 'db_user' variable in your script uses the Cloud SQL username, not the service account email.
3. Check that the host in your connection settings is correct. The error message mentions `"cloudsqlproxy~'localIP'" as the host. It should be the public IP address of your Cloud SQL instance for a public connection, or the private IP address if using a private network.
If you're still encountering issues after these steps, its best to consider reaching out to our Google Cloud Support.