使用IAM角色使用Python连接到Redshift

问题描述:

我使用sqlalchemy和psycopg2将python连接到redshift。使用IAM角色使用Python连接到Redshift

engine = create_engine('postgresql://user:[email protected]:port/database_name') 

我想避免使用我的密码连接到红移和使用IAM角色。

AWS IAM用户与Redshift数据库用户不同。虽然Redshift是postgres的(非常遥远的)亲戚,但它并不允许无密码连接,afaik。

编辑:

我的回答是不再适用,检查相关的代码片段答案。

+0

这是不正确的。您可以(截至2018年1月)调用'get_cluster_credentials'来获取临时凭证以访问Redshift集群。 https://boto3.readthedocs.io/en/latest/reference/services/redshift.html#Redshift.Client.get_cluster_credentials – danielchalef

+0

谢谢,我添加了一个编辑,表明我的答案不再适用。当我回答时,我没有找到这个功能。要么我在搜索时遇到不好的情况,要么在一段时间之后将它添加到boto中。 –

AWS提供了一种请求访问Redshift群集的临时证书的方法。 Boto3实现了get_cluster_credentials,允许您执行以下操作。确保您已经按照instructions here设置您的IAM用户和角色。

def db_connection(): 
    logger = logging.getLogger(__name__) 

    RS_PORT = 5439 
    RS_USER = 'myDbUser' 
    DATABASE = 'myDb' 
    CLUSTER_ID = 'myCluster' 
    RS_HOST = 'myClusterHostName' 

    client = boto3.client('redshift') 

    cluster_creds = client.get_cluster_credentials(DbUser=RS_USER, 
               DbName=DATABASE, 
              ClusterIdentifier=CLUSTER_ID, 
               AutoCreate=False) 

    try: 
     conn = psycopg2.connect(
     host=RS_HOST, 
     port=RS_PORT, 
     user=cluster_creds['DbUser'], 
     password=cluster_creds['DbPassword'], 
     database=DATABASE 
    ) 
     return conn 
    except psycopg2.Error: 
     logger.exception('Failed to open database connection.') 

AWS为python中的IAM creds提供了像他们的JDBC驱动程序一样的方便包装器。您需要手动拨打GetClusterCredentials端点,然后将返回的用户名和密码传递给create_engine。看起来像这样:

def get_redshift_credentials(): 
    role_creds = get_role_credentials() 
    client = boto3.client(
     'redshift', 
     region_name=CLUSTER_REGION, 
     aws_access_key_id=role_creds['AccessKeyId'], 
     aws_secret_access_key=role_creds['SecretAccessKey'], 
     aws_session_token=role_creds['SessionToken'], 
    ) 
    response = client.get_cluster_credentials(
     DbUser=PGUSER, 
     ClusterIdentifier=CLUSTER_IDENTIFIER, 
    ) 
    return response 

creds = get_redshift_credentials() 
engine = create_engine('postgresql://{creds.DbUser}:{creds.DbPassword}@hostname:port/database_name'.format(creds))