使用Apache airflow存储和访问密码

时间:2017-07-24 12:27:19

标签: python airflow

我们使用气流作为调度程序。我想在DAG中调用一个简单的bash运算符。 bash脚本需要使用密码作为参数来进行进一步处理。

如何在airflow(config / variables / connection)中安全地存储密码并在dag定义文件中访问它。

我是气流和Python的新手,所以我们会欣赏代码片段。

7 个答案:

答案 0 :(得分:26)

您可以将密码存储在挂钩中 - 只要您设置了您的fernet密钥,就会对其进行加密。

以下是创建连接的方法。

from airflow.models import Connection
def create_conn(username, password, host=None):
    new_conn = Connection(conn_id=f'{username}_connection',
                                  login=username,
                                  host=host if host else None)
    new_conn.set_password(password)

然后,在您设置的数据库中加密此密码。

要访问此密码:

from airflow.hooks.base_hook import BaseHook

 connection = BaseHook.get_connection("username_connection")
 password = connection.password # This is a getter that returns the unencrypted password.

编辑:

通过UI创建连接有一种更简单的方法:

Main Menu 然后: Create Connection

答案 1 :(得分:3)

使用“管理/连接”标签中的GUI。

真正有效的答案,通过以编程方式将连接保持在Airflow中,如下所示。

在下面的示例中,myservice代表一些外部凭据缓存。

使用以下方法时,您可以在气流内部存储要管理的连接。无需从每个任务/任务中轮询服务。取而代之的是,您可以依靠气流的连接机制,而不必迷失于气流所暴露的运营商(您的组织应允许这样做)。

技巧是使用airflow.utils.db.merge_conn来处理您创建的连接对象的设置。

    from airflow.utils.db import provide_session, merge_conn




    creds = {"user": myservice.get_user(), "pwd": myservice.get_pwd() 

    c = Connection(conn_id=f'your_airflow_connection_id_here',
                   login=creds["user"],
                   host=None)
    c.set_password(creds["pwd"])
    merge_conn(c)

merge_conn是内置的,气流本身用于初始化空连接。但是,它不会自动更新。为此,您将必须使用自己的帮助器功能。

from airflow.utils.db import provide_session

@provide_session
def store_conn(conn, session=None):
    from airflow.models import Connection
    if session.query(Connection).filter(Connection.conn_id == conn.conn_id).first():
        logging.info("Connection object already exists, attempting to remove it...")
        session.delete(session.query(Connection).filter(Connection.conn_id == conn.conn_id).first())

    session.add(conn)
    session.commit()

答案 2 :(得分:3)

from airflow.hooks.base_hook import BaseHook
conn = BaseHook.get_connection('bigquery_connection')
print(conn.get_extra())

这些conn.get_extra()将为您提供连接中存储的设置的JSON。

答案 3 :(得分:1)

您可以将密码存储在气流变量https://airflow.incubator.apache.org/ui.html#variable-view

  1. 在UI中创建一个带键和值的变量,例如mypass:XXX
  2. 导入变量from airflow.models import Variable
  3. MyPass = Variable.get(“mypass”)
  4. 将MyPass传递给您的bash脚本:
  5. command = """
              echo "{{ params.my_param }}"
              """
    
    
    
    task = BashOperator(
            task_id='templated',
            bash_command=command,
            params={'my_param': MyPass},
            dag=dag)
    

答案 4 :(得分:1)

在这种情况下,我将使用PythonOperator,您可以使用它从中获取p数据库连接 Hook。然后,您可以在此挂钩上调用hook = PostgresHook(postgres_conn_id=postgres_conn_id),它将为您提供一个Connection对象,您可以从中获取数据库连接的主机,登录名和密码。

最后,使用例如get_connection将连接详细信息作为参数传递。

此方法有点复杂但它确实允许您在Airflow中保持数据库连接的加密。此外,您应该能够将此策略拉入一个单独的Operator类,继承PythonOperator的基本行为,但添加了获取钩子并调用bash脚本的逻辑。

答案 5 :(得分:0)

这就是我用过的。

    def add_slack_token(ds, **kwargs):
        """"Add a slack token"""
        session = settings.Session()

        new_conn = Connection(conn_id='slack_token')
        new_conn.set_password(SLACK_LEGACY_TOKEN)

        if not (session.query(Connection).filter(Connection.conn_id == 
         new_conn.conn_id).first()):
        session.add(new_conn)
        session.commit()
        else:
            msg = '\n\tA connection with `conn_id`={conn_id} already exists\n'
            msg = msg.format(conn_id=new_conn.conn_id)
            print(msg)

    dag = DAG(
        'add_connections',
        default_args=default_args,
        schedule_interval="@once")


    t2 = PythonOperator(
        dag=dag,
        task_id='add_slack_token',
        python_callable=add_slack_token,
        provide_context=True,
    )

答案 6 :(得分:0)

我编写了以下实用方法,用于创建到保存在 Airflow 中的外部数据库配置的会话:

from airflow.hooks.base_hook import BaseHook
from sqlalchemy.orm.session import sessionmaker


def get_session(conn_id):
    dbhook = BaseHook.get_hook(conn_id=conn_id)
    engine = create_engine(dbhook.get_uri())
    Session = sessionmaker()
    session = Session(bind=engine)
    return session