Access denied for user on Cloud SQL when connecting from Cloud Run service.

huangapple go评论53阅读模式
英文:

Access denied for user on Cloud SQL when connecting from Cloud Run service

问题

我已构建了一个使用 Python Flask 框架的应用程序,该应用程序连接到 Cloud SQL 实例并执行一些操作。我在本地使其正常运行,然后将其容器化并上传到 Google Cloud 上的容器注册表。接下来,我从该容器创建了一个 Cloud Run 服务,但我得到的错误是"mydb" 未定义。通过检查 SQL 实例的日志,我看到了以下错误:"[Server] 用户 'root'@'实际 IP 地址' 拒绝访问(使用密码: 是)"

以下仅为展示实际问题的代码片段:

from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    result = mydb.execute(text("SELECT * from users")).fetchall() #error line
    msg = ""
    for row in result:
        msg += str(row) + "\n"
    return msg

def createSQLConnection():
    # 创建 SQLAlchemy 连接池
    with Connector() as connector:
        conn = connector.connect(
            "actual_region",
            "pymysql",
            user="root",
            password="actual_password",
            db="actual_db",
            ip_type=IPTypes.PUBLIC
        )
    pool = sqlalchemy.create_engine(
        "mysql+pymysql://",
        creator=lambda: conn,
    )
    return pool

if __name__ == "__main__":
    pool = createSQLConnection()
    mydb = pool.connect()
    app.run(debug=True)

我遵循了连接的文档。之前我使用了 Python 的 MySQL 连接器,但我转而使用了谷歌的 SQL 库,因为它可以自动授权。

我配置了我的 SQL 实例以具有公共 IP 地址并接受任何人(我知道这是一个不好的做法,但我会稍后更改它)SQL 配置

我启用了 IAM 管理 API,并将 SQL 客户端权限添加到了默认应用程序引擎帐户和 SQL 实例上列出的服务帐户帐户权限

而且在部署时,我添加了我的 SQL 实例SQL 实例

就像我说的,这段代码在本地可以正常工作,并且我可以从 SQL Workbench 等地方连接到数据库,没有任何问题,所以凭据是正确的。我猜我的问题与 Cloud Run 配置有关。如果可能的话,我希望保持简单(无 VPC、套接字)。

英文:

I have built a python flask app, which connects to cloud SQL instance and does some stuff. I made it work locally, so I dockerized it, and uploaded it to container registry on google cloud. Next, I made a cloud run service from that container, and the error that I get is that **"mydb" is not defined**. By inspecting the logs from SQL instance, I saw the following error: **[Server] Access denied for user 'root'@'ACTUAL_IP_ADDRESS' (using password: YES)"**

Here is only a snippet of code to show the actual problem:

from flask import Flask

app = Flask(__name__)

@app.route('/')
def index():
    result = mydb.execute(text("SELECT * from users")).fetchall() #error line
    msg = ""
    for row in result:
        msg += str(row) + "\n"
    return msg

def createSQLConnection():
    # create SQLAlchemy connection pool
    with Connector() as connector:
        conn = connector.connect(
            "actual_region", 
            "pymysql",
            user="root",
            password="actual_password",
            db="actual_db",
            ip_type=IPTypes.PUBLIC 
        )
    pool = sqlalchemy.create_engine(
        "mysql+pymysql://",
        creator=lambda: conn,
    )
    return pool

if __name__ == "__main__":
    pool = createSQLConnection()
    mydb = pool.connect()
    app.run(debug=True)`

I followed the docs for connection. Previously I used mysql connector for python, but I switched to google's library for sql because it has authorization automatically.

I configured my sql instance to have public ip adress and to accept anyone(I know it is bad practice to do that, but I'll change it later)SQL Config

I enabled IAM admin api, and I added sql cliend permission to both the default app engine account that should be used here, and to account that is listed as service account on sql instance
Account permissions

And also while deploying, I added my sql instance.
SQL Instance

As I sad, this code works locally, and I can connect to the db from like sql workbench without any issues, so the credential are good. I guess my issue is something with cloud run configuration. If possible I would like to keep it simple (no VPC, sockets)

答案1

得分: 1

这个错误是由Flask引起的。在你的 if __name__ == "__main__": 块中初始化的变量不是全局变量,将无法在你的 index 函数和路由的范围内访问。你可以考虑使用 Flask会话(Flask session) 来存储数据库连接池。

为了简单起见,你也可以尝试使用全局变量来解除阻塞自己。

from flask import Flask
from google.cloud.sql.connector import Connector, IPTypes
from sqlalchemy import text, create_engine

app = Flask(__name__)

def createSQLConnection():
    # 创建SQLAlchemy连接池
    with Connector() as connector:
        conn = connector.connect(
            "project:region:instance",
            "pymysql",
            user="root",
            password="actual_pass",
            db="actual_db",
            ip_type=IPTypes.PUBLIC
        )
    pool = create_engine(
        "mysql+pymysql://",
        creator=lambda: conn,
    )
    return pool

# 全局连接池
pool = createSQLConnection()
mydb = pool.connect()

@app.route('/')
def index():
    result = mydb.execute(text("SELECT NOW()")).fetchone() #错误行
    time = str(result[0])
    return time

if __name__ == "__main__":
    app.run(debug=True)

我配置了我的SQL实例具有公共IP地址,并接受任何人(我知道这是不良做法,但我以后会更改)SQL配置

您无需添加任何授权网络。Cloud SQL Python连接器将为您授权IP以进行安全连接。

并且在部署时,我添加了我的SQL实例。SQL实例

当使用像你正在使用的Cloud SQL语言连接器(如Python连接器)时,不需要添加此连接。只有在使用Cloud SQL Auth代理时才需要添加连接到您的服务的连接。

英文:

This error is caused by Flask. Variables initialized in your if __name__ == "__main__": block aren't global variables and won't be accessible within the scope of your index function and route. You can look at using a Flask session to store the database connection pool.

For simplicity you can also try unblocking yourself with using a global variable.

from flask import Flask
from google.cloud.sql.connector import Connector, IPTypes
from sqlalchemy import text, create_engine

app = Flask(__name__)

def createSQLConnection():
    # create SQLAlchemy connection pool
    with Connector() as connector:
        conn = connector.connect(
            "project:region:instance", 
            "pymysql",
            user="root",
            password="actual_pass",
            db="actual_db",
            ip_type=IPTypes.PUBLIC 
        )
    pool = create_engine(
        "mysql+pymysql://",
        creator=lambda: conn,
    )
    return pool

# global connection pool
pool = createSQLConnection()
mydb = pool.connect()

@app.route('/')
def index():
    result = mydb.execute(text("SELECT NOW()")).fetchone() #error line
    time = str(result[0])
    return time

if __name__ == "__main__":
    app.run(debug=True)

> I configured my sql instance to have public ip adress and to accept anyone(I know it is bad practice to do that, but I'll change it later)SQL Config

You do not need to add any authorized networks at all. The Cloud SQL Python Connector will authorize the IP for you with a secure connection.

> And also while deploying, I added my sql instance. SQL Instance

Adding this connection is also unnecessary when using a Cloud SQL Language Connector such as the Python one you are using. Adding a Connection to your service is only necessary while using the Cloud SQL Auth Proxy.

huangapple
  • 本文由 发表于 2023年5月8日 01:33:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/76195373.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定