Airflowスモールスタート-Connectionsメニューのトラブルシューティング


私は良い気流を使っていて、突然UIからConnectionsメニューに入ると、次のようなエラーが発生し始めました.
Can't decrypt encrypted password for login=ADMIN, FERNET_KEY configuration is missing
最初はconfigにFERNET KEYがないと思っていたので、環境変数としてAIRFLOW__CORE__FERNET_KEYを追加しましたが、類似のエラーが発生しました.
cryptography.fernet.InvalidToken
airflow db resetだけが解決策であり,QA環境はAIRFLOW__CORE__FERNET_KEYを追加しdbresetを解決した.
オペレーティング環境では、dbresetによって実行レコードがすべて失われます.
だから私はコードを開けて問題が何なのかを見ました.
エラーはここです.
# airflow/models/connection.py
...

    def get_password(self) -> Optional[str]:
        """Return encrypted password."""
        if self._password and self.is_encrypted:
            fernet = get_fernet()
            if not fernet.is_encrypted:
                raise AirflowException(
                    "Can't decrypt encrypted password for login={}, \
                    FERNET_KEY configuration is missing".format(
                        self.login
                    )
                )
            return fernet.decrypt(bytes(self._password, 'utf-8')).decode()
        else:
            return self._password
self._passwordおよびself.is_encryptedがTrueであればfernetがもたらされ、このときfernet.is_encryptedがFalseとして向上する.
ではどんな場合にfernet.is_encryptedがFalseなのか確認してみましょうget_fernet()にはここです。があります.
# airflow/models/crypto.py
...

def get_fernet():
    """
    Deferred load of Fernet key.
    This function could fail either because Cryptography is not installed
    or because the Fernet key is invalid.
    :return: Fernet object
    :raises: airflow.exceptions.AirflowException if there's a problem trying to load Fernet
    """
    global _fernet  # pylint: disable=global-statement

    if _fernet:
        return _fernet

    try:
        fernet_key = conf.get('core', 'FERNET_KEY')
        if not fernet_key:
            log.warning("empty cryptography key - values will not be stored encrypted.")
            _fernet = NullFernet()
        else:
            _fernet = MultiFernet(
                [Fernet(fernet_part.encode('utf-8')) for fernet_part in fernet_key.split(',')]
            )
            _fernet.is_encrypted = True
    except (ValueError, TypeError) as value_error:
        raise AirflowException(f"Could not create Fernet object: {value_error}")

    return _fernet
コンフィグで個別に設定されたFERNET KEYがない場合、fernet.is_encryptedに障害が発生する可能性があります.(FERNET KEYがあれば、Trueを明確に設定します.)
しかし、我々はFERNET KEYを設置しておらず、これまでよく使ってきた.ではself._passwordself.is_encryptedがTrueになっている部分は問題ではないでしょうか.
この考えがあるまで、get_passwordの方法があるConnection類が何なのかよく見ました.
# airflow/models/connection.py
...

class Connection(Base, LoggingMixin):  # pylint: disable=too-many-instance-attributes
    """
    Placeholder to store information about different database instances
    connection information. The idea here is that scripts use references to
    database instances (conn_id) instead of hard coding hostname, logins and
    passwords when using operators or hooks.
...
Connectionはmetadata dbのConnectionテーブルから接続情報を取得するクラスであり、self._passwordおよびself.is_encryptedはテーブル内の各行の情報を含む.
また、運用に使用されるmetadabの接続テーブルには、気流を例にとって置かれた(不要な)接続にもpasswordが存在し、いくつかのis_encryptedがTrueの接続である.
これらをis_encrypted=Falseに変更すると、connectionsメニューを正常に閲覧できます.
その他の考え方
  • を解決しましたが...Blameから見れば、関連論理は3年前に修正されたので、なぜ突然このような問題が発生したのか分からない.
  • は思ったより早く解決できました.
  • の内部ネットワークでしか気流が効かないのでfernetkeyには考えられませんでしたが、安全上、使うべきか確認しなければなりません.クラウドなどの外部サービスを利用する必要がある場合は、これが必要です.
  • リファレンス
  • 気流わらびキーの追加
  • 気流db resetによる修復の例