Investigating Connection Encryption on Amazon MWAA
Investigating whether Connections can be stored in plaintext on Amazon MWAA
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
passwordandextracolumns of a Connection using symmetric Fernet encryption, with the key controlled byAIRFLOW__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_encryptedshowing0.
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.
