Byte Ebi's Logo

Byte Ebi 🍀

A Bit everyday A Byte every week

Investigating Connection Encryption on Amazon MWAA

Investigating whether Connections can be stored in plaintext on Amazon MWAA

Ray

The Airflow docs actually state that setting the encryption key to an empty string makes Connections fall back to plaintext.
But does the same thing hold true on AWS-managed MWAA?
This post traces that question from Airflow’s native Fernet mechanism all the way to MWAA’s reserved environment variables.

Why I Started Digging

Per the Airflow documentation, when the encryption key is an empty string, the password and extra fields on a Connection are stored in plaintext, with is_encrypted showing 0.
This is native Airflow behavior, not a misconfiguration.

That made me curious: on AWS-managed MWAA, can encryption be disabled the same way?

Investigation

The Default Behavior

The Airflow 3 documentation states that connections should be encrypted with Fernet by default:

For connections stored in the Airflow metadata database, Airflow uses Fernet to encrypt password and other potentially sensitive data. It guarantees that without the encryption password, Connection Passwords cannot be manipulated or read without the key. For information on configuring Fernet, look at Fernet .

How Native Airflow Encrypts Connections

AWS MWAA doesn’t let you connect to its metadata DB directly, so this part of the investigation used a locally spun-up Airflow container to verify the native encryption mechanism.

Environment

  • Metadata DB: SQLite, located at /usr/local/airflow/airflow.db
  • Encryption key: AIRFLOW__CORE__FERNET_KEY
  • Algorithm: Fernet

Checking Whether Fields Are Encrypted

Query the connection table in SQLite:

sqlite3 /usr/local/airflow/airflow.db \
  "SELECT conn_id, conn_type, is_encrypted, is_extra_encrypted, password, extra FROM connection;"

A GUI tool works too, for example the VS Code extension qwtel.sqlite-viewer .

What to look for:

Column Meaning
is_encrypted 1 means the password column is encrypted
is_extra_encrypted 1 means the extra column is encrypted
password / extra When encrypted, the value is a Fernet token starting with gAAAAAB..., not plaintext

By default, only the password and extra columns are encrypted, while conn_id, conn_type, host, login, port, and schema are always stored as plaintext.

Confirming the Key Exists

airflow config get-value core fernet_key

A non-empty value means the encryption key is configured. Only when the key is explicitly set to an empty string does Airflow fall back to plaintext, and is_encrypted will be 0.

This is because when airflow.cfg doesn’t exist, Airflow automatically generates a random Fernet key and writes it into the config file.

Verifying Decryption

Method 1: Airflow CLI (automatic decryption)

airflow connections get <conn_id> -o json

Airflow automatically decrypts the value using the current environment’s AIRFLOW__CORE__FERNET_KEY, and prints the password field in plaintext.

⚠️ This command prints the plaintext password to the terminal β€” be careful where that output ends up.

Method 2: Manually decrypt the raw encrypted value with the Fernet key

from cryptography.fernet import Fernet

fernet_key = "<value from `airflow config get-value core fernet_key`>"
encrypted = b"<the gAAAAAB... string from connection.password>"

f = Fernet(fernet_key.encode())
print(f.decrypt(encrypted).decode())

This method demonstrates the full chain: raw encrypted string + key β†’ decrypted plaintext.

Summary

  • Airflow encrypts the password and extra columns of a Connection using symmetric Fernet encryption, with the key controlled by AIRFLOW__CORE__FERNET_KEY.
  • Anyone with access to the key can decrypt the data.
  • Only when the key is explicitly cleared does Airflow fall back to plaintext, with is_encrypted showing 0.

Checking the MWAA Configuration

My working assumption was that core.fernet_key might be overridden to an empty value in MWAA’s Airflow Configuration Options, so I checked the actual configuration on the AWS console first.

β‡’ Checked the Airflow Configuration Options on MWAA

β‡’ Result: it was not overridden to an empty value

But that check alone couldn’t rule out other ways of overriding this value. Digging further, I found that Using a startup script with Amazon MWAA states that AIRFLOW__CORE__FERNET_KEY is a reserved environment variable, and no matter how you try to override it, it always gets restored to its default:

Amazon MWAA reserves a set of critical environment variables. If you overwrite a reserved variable, Amazon MWAA restores it to its default. The following lists the reserved variables:

  • AIRFLOW__CORE__FERNET_KEY – The key used for encryption and decryption of sensitive data stored in the metadata database, for example, connection passwords.

So, as mentioned in Fernet InvalidToken #18127 , setting FERNET_KEY to an empty string to disable encryption doesn’t work here.

Conclusion

Because core.fernet_key is a reserved MWAA variable and any attempt to override it gets restored to its default, sensitive connection data stored in the Airflow metadata database is always forced into an encrypted state at the storage layer on MWAA. So there’s no need to worry about MWAA Connection passwords ever being stored in plaintext.

Recent Posts

Categories

Tags