Подключение к Amazon Aurora с использованием SQLAlchemy

Я пытаюсь подключиться к Amazon Aurora с помощью SQLAlchemy, используя соединение SSL, указав роль IAM в качестве учетной записи пользователя базы данных и маркер аутентификации в качестве пароля, как описано здесь в [Документах AWS] (http://docs.aws.amazon)..com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.html # UsingWithRDS.IAMDBAuth.Connecting)

Вот шаги, которым я следовал.

wget https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.pem

export LIBMYSQL_ENABLE_CLEARTEXT_PLUGIN=1

aws rds generate-db-auth-token --hostname 'datadbcluster-1.cluster-xxxxxxxxxxxx.us-west-2.rds.amazonaws.com' --port 3306 --username dt_analyst --region us-west-2 > /home/ubuntu/dt_analyst.pem

mysql -h datadbinstance2nd. xxxxxxxxxxxx.us-west-2.rds.amazonaws.com--ssl-ca /home/ubuntu/rds-combined-ca-bundle.pem -u dt_analyst --ssl-verify-server-cert --enable-cleartext-plugin -p'<token>'

Я подтвердил, что могу подключиться через SSL с помощью клиента mysql.

Но я хочу подключиться с помощью sqlalchemy, а не клиента mysql. Следующий код скомпилирован из десятка советов, найденных в Интернете, но выдает только следующую ошибку.

'sqlalchemy.exc.OperationalError: (_mysql_exceptions.OperationalError) (1045, "Доступ запрещен для пользователя...")

Мой код выглядит следующим образом.

import boto3

client = boto3.client('rds', region_name='us-west-2')

dialect='mysql'
user = ‘dt_analyst
host = 'datadbcluster-1.cluster-xxxxxxxxxxxx.us-west-2.rds.amazonaws.com'
port = 3306
data = ‘datadb
region='us-west-2'

token = client.generate_db_auth_token(host,port,user,region)
host1 = 'datadbinstance2nd. xxxxxxxxxxxx.us-west-2.rds.amazonaws.com'
conn_str = '%s://%s:%[email protected]%s:%d/%s'%(dialect,user,token,host1,port,data)
conn_str += '?ssl_key=%s'%token
conn_str += '&ssl_cert=/home/ubuntu/rds-combined-ca-bundle.pem'

ssl_args = {
    'ssl': {
        'ca_cert': '/home/ubuntu/rds-combined-ca-bundle.pem',
        'sslmode': 'require',
        'verify_ssl_cert': True
    }
}

engine = create_engine(conn_str,connect_args=ssl_args, echo=True)

Ответ 1

Мой ответ тройной:

Роли IAM

Есть один шаг, который не был упомянут здесь: вам нужно назначить роль IAM, которая дает вашему клиенту право подключаться к RDS.

Под "клиентом" я имею в виду любой ресурс AWS, на котором выполняется код из этого вопроса. Это может быть лямбда-функция, или экземпляр EC2, или что-то еще. Что бы это ни было, у него есть ARN, и ему должно быть разрешено действие rds-db:connect.

Строка соединения с цитированием URL

Тогда может быть проблема с учетными данными RDS. Возможно, вам придется URL-адрес, указать пароль, если он содержит символы, которые не допускаются в URL-адресе.

  • Python 3: passwd = urllib.parse.quote(rds_password)
  • Python 2: passwd = urllib.quote(rds_password)

Временные учетные данные RDS

Наконец, возможно, ваша база данных RDS требует временных учетных данных. Этот пример кода показывает, как получить эти:

# get RDS config, often done through environment variables
import os

rds_host = os.environ.get("RDS_HOST")  
rds_port = os.environ.get("RDS_PORT")
rds_username = os.environ.get("RDS_USER")   

# get temp credential
import boto3

temp_passwd = boto3.client('rds').generate_db_auth_token(
    DBHostname=rds_host,
    Port=rds_port,
    DBUsername=rds_username 
)

rds_credentials = {'user': rds_username, 'passwd': temp_passwd}

Объединяя это:

def create_sqlalchemy_engine(self):
    conn_str = f"{protocol}://{rds_host}:{rds_port}/{database}"

    kw = dict()
    kw.update(rds_credentials)
    # kw.update({'ssl': {'ca': /path/to/pem-file.pem}})  # MySQL
    # kw.update({'sslmode': 'verify-full', 'sslrootcert /path/to/pem-file.pem})  # PostgreSQL

    return create_engine(conn_str, connect_args=kw)

Я переместил параметры user и passwd из строки соединения в connect_args. Это устраняет необходимость цитирования URL.

Смотрите также: https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.IAMPolicy.html