Подключение к 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