Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions airflow-core/newsfragments/59844.improvement.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Prevent airflow connections list from exposing sensitive connection values by default.
14 changes: 13 additions & 1 deletion airflow-core/src/airflow/cli/commands/connection_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,18 @@ def connections_get(args):
)


def _connection_list_mapper(conn: Connection) -> dict[str, Any]:
return {
"id": conn.id,
"conn_id": conn.conn_id,
"conn_type": conn.conn_type,
"description": conn.description,
"host": conn.host,
"schema": conn.schema,
"port": conn.port,
}


@suppress_logs_and_warning
@providers_configuration_loaded
def connections_list(args):
Expand All @@ -89,7 +101,7 @@ def connections_list(args):
AirflowConsole().print_as(
data=conns,
output=args.output,
mapper=_connection_mapper,
mapper=_connection_list_mapper,
)


Expand Down
37 changes: 37 additions & 0 deletions airflow-core/tests/unit/cli/commands/test_connection_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
# under the License.
from __future__ import annotations

import argparse
import json
import os
import re
Expand All @@ -28,6 +29,7 @@

from airflow.cli import cli_config, cli_parser
from airflow.cli.commands import connection_command
from airflow.cli.commands.connection_command import connections_list
from airflow.exceptions import AirflowException
from airflow.models import Connection
from airflow.utils.db import merge_conn
Expand Down Expand Up @@ -1023,3 +1025,38 @@ def test_cli_create_default_connections(self, mocker):
)["create-default-connections"]
create_default_connection_fnc(())
mock_db_create_default_connections.assert_called_once()


def test_connections_list_hides_sensitive_values(session, capsys):
conn = Connection(
conn_id="test_conn",
conn_type="generic",
login="user",
password="password",
host="localhost",
port=5432,
schema="db",
)
session.add(conn)
session.commit()

args = argparse.Namespace(
output="table",
verbose=False,
log_level="INFO",
subcommand="connections list",
cfg_path=None,
)

connections_list(args)

captured = capsys.readouterr()
stdout = captured.out

# Non-sensitive identifier should be present
assert "test_conn" in stdout

# Sensitive values must not be present
assert "user" not in stdout
assert "password" not in stdout
assert "generic://user:password" not in stdout