Heim  >  Artikel  >  Backend-Entwicklung  >  Testgeheimnisse mit pytest-mask-secrets sichern

Testgeheimnisse mit pytest-mask-secrets sichern

WBOY
WBOYOriginal
2024-08-12 18:43:59472Durchsuche

Securing Testing Secrets with pytest-mask-secrets

Die Sicherheit und Vertraulichkeit sensibler Daten hat bei der Softwareentwicklung oberste Priorität. Anwendungsprotokolle, einer der häufigsten Vektoren für Datenlecks, werden sorgfältig geschützt, um das Vorhandensein von Geheimnissen zu verhindern. Die gleichen Bedenken und Risiken gelten auch für Testprotokolle, die Passwörter oder Zugriffstoken preisgeben können. Tools, die CI-Workflows ausführen, bieten normalerweise Mechanismen, um vertrauliche Daten in Protokollen mit geringem oder gar keinem Aufwand zu maskieren. Dies ist zwar sehr praktisch, effizient und einfach zu verwenden, in bestimmten Situationen kann dies jedoch nicht ausreichend sein.

Warum CI-Workflow-Maskierung allein möglicherweise nicht ausreicht

Zum Beispiel leistet GitHub Actions gute Arbeit beim Umgang mit Geheimnissen. Jedes im Workflow definierte Geheimnis wird automatisch aus der erfassten Ausgabe maskiert, was wie ein Zauber wirkt. Allerdings hat es, wie jedes CI-System, seine Grenzen. Wenn der Ausgabebericht einen anderen Pfad annimmt – z. B. in einer Datei gespeichert, Junit generiert oder an einen Remote-Protokollspeicher gesendet wird – ist GitHub Actions nicht in der Lage, den Inhalt zu überprüfen und die Geheimnisse zu maskieren.

Darüber hinaus werden Tests nicht immer innerhalb eines CI-Workflows ausgeführt, und selbst dann müssen möglicherweise noch Geheimnisse verborgen werden. Stellen Sie sich vor, Sie führen Tests lokal durch und geben ein Protokoll frei, um ein Problem zu besprechen. Ohne es zu merken, fügen Sie Ihrem Zugriffstoken eine URL hinzu.

Daher ist es auf allen Ebenen unerlässlich, über einen Mechanismus zum Umgang mit sensiblen Daten in Testprotokollen zu verfügen. Der beste Ansatz besteht darin, dies direkt auf Testebene oder innerhalb des Testframeworks selbst zu implementieren. Dadurch wird sichergestellt, dass keine Geheimnisse aus der Primärquelle durchsickern und verhindert wird, dass sie durch das System weitergegeben werden.

Schutz auf der richtigen Ebene hinzufügen

Die Maskierung von Geheimnissen direkt in Tests aufrechtzuerhalten, kann relativ kostspielig und fehleranfällig sein und fühlt sich oft wie ein verlorener Kampf an. Stellen Sie sich beispielsweise vor, Sie müssten eine URL mit einem Token als Parameter entwerfen. Diese URL muss für die Verwendung in einer Anfrage anders gerendert werden als für ihre Präsenz im Protokoll.

Im Gegensatz dazu bietet das Abfangen der Berichtserstellung innerhalb des Test-Frameworks eine ideale Gelegenheit, sich in den Prozess einzubinden und die Datensätze zu ändern, um sensible Daten zu eliminieren. Dieser Ansatz ist für die Tests transparent, erfordert keine Änderungen am Testcode und funktioniert genau wie die Geheimnismaskierungsfunktion in einem CI-Workflow – führen Sie ihn einfach aus und vergessen Sie die Verwaltung der Geheimnisse. Es automatisiert den Prozess und stellt sicher, dass sensible Daten geschützt sind, ohne den Testaufbau zusätzlich zu komplexieren.

Das ist genau das, was pytest-mask-secrets tut, offensichtlich, wenn pytest für die Testausführung verwendet wird. Unter seinen vielen Funktionen bietet Pytest ein umfangreiches und flexibles Plugin-System. Zu diesem Zweck können Sie direkt vor der Protokollgenerierung in den Prozess einsteigen, also zu einem Zeitpunkt, an dem bereits alle Daten erfasst wurden. Dies erleichtert das Suchen und Entfernen sensibler Werte aus den Datensätzen vor deren Ausgabe.

Auf die Probe stellen: Eine praktische Demo

Um zu veranschaulichen, wie das funktioniert, ist ein einfaches Beispiel am effektivsten. Unten finden Sie einen trivialen Test, der möglicherweise kein reales Testszenario darstellt, aber dazu dient, die Geheimnisse von Pytest-Masken recht gut zu demonstrieren.

import logging
import os


def test_password_length():
    password = os.environ["PASSWORD"]
    logging.info("Tested password: %s", password)
    assert len(password) > 18

In diesem Beispiel gibt es eine Behauptung, die möglicherweise fehlschlägt (und das wird auch der Fall sein), zusammen mit einer Protokollnachricht, die ein Geheimnis enthält. Ja, es mag albern erscheinen, ein Geheimnis in das Protokoll aufzunehmen, aber stellen Sie sich ein Szenario vor, in dem Sie eine URL mit einem Token als Parameter haben und eine detaillierte Debug-Protokollierung aktiviert ist. In solchen Fällen könnten Bibliotheken wie Anfragen das Geheimnis versehentlich auf diese Weise protokollieren.

Jetzt zum Testen. Legen Sie zunächst das zu Testzwecken benötigte Geheimnis fest:

(venv) $ export PASSWORD="TOP-SECRET"

Als nächstes führen Sie den Test durch:

(venv) $ pytest --log-level=info test.py 
============================= test session starts ==============================
platform linux -- Python 3.12.4, pytest-8.3.2, pluggy-1.5.0
rootdir: /tmp/tmp.AvZtz7nHZS
collected 1 item                                                               

test.py F                                                                [100%]

=================================== FAILURES ===================================
_____________________________ test_password_length _____________________________

    def test_password_length():
        password = os.environ["PASSWORD"]
        logging.info("Tested password: %s", password)
>       assert len(password) > 18
E       AssertionError: assert 10 > 18
E        +  where 10 = len('TOP-SECRET')

test.py:8: AssertionError
------------------------------ Captured log call -------------------------------
INFO     root:test.py:7 Tested password: TOP-SECRET
=========================== short test summary info ============================
FAILED test.py::test_password_length - AssertionError: assert 10 > 18
============================== 1 failed in 0.03s ===============================

Standardmäßig erscheint der geheime Wert zweimal in der Ausgabe: einmal in der erfassten Protokollnachricht und erneut in der fehlgeschlagenen Behauptung.

Aber was ist, wenn pytest-mask-secrets installiert ist?

(venv) $ pip install pytest-mask-secrets

Und entsprechend konfiguriert. Es muss eine Liste der Umgebungsvariablen kennen, die die Geheimnisse enthalten. Dies geschieht durch Setzen der Variablen MASK_SECRETS:

(venv) $ export MASK_SECRETS=PASSWORD

Führen Sie nun den Test erneut aus:

(venv) $ pytest --log-level=info test.py 
============================= test session starts ==============================
platform linux -- Python 3.12.4, pytest-8.3.2, pluggy-1.5.0
rootdir: /tmp/tmp.AvZtz7nHZS
plugins: mask-secrets-1.2.0
collected 1 item                                                               

test.py F                                                                [100%]

=================================== FAILURES ===================================
_____________________________ test_password_length _____________________________

    def test_password_length():
        password = os.environ["PASSWORD"]
        logging.info("Tested password: %s", password)
>       assert len(password) > 18
E       AssertionError: assert 10 > 18
E        +  where 10 = len('*****')

test.py:8: AssertionError
------------------------------ Captured log call -------------------------------
INFO     root:test.py:7 Tested password: *****
=========================== short test summary info ============================
FAILED test.py::test_password_length - AssertionError: assert 10 > 18
============================== 1 failed in 0.02s ===============================

Anstelle des Geheimwerts erscheinen jetzt Sternchen überall dort, wo das Geheimnis gedruckt worden wäre. Die Arbeit ist erledigt und der Prüfbericht ist nun frei von sensiblen Daten.

Abschließende Gedanken

Aus dem Beispiel könnte es scheinen, dass pytest-mask-secrets nicht viel mehr tut als das, was GitHub Actions bereits standardmäßig tut, was den Aufwand überflüssig erscheinen lässt. Wie bereits erwähnt, maskieren CI-Workflow-Ausführungstools jedoch nur Geheimnisse in der erfassten Ausgabe, sodass JUnit-Dateien und andere Berichte unverändert bleiben. Ohne pytest-mask-secrets könnten in diesen Dateien immer noch vertrauliche Daten offengelegt werden – dies gilt für alle von pytest generierten Berichte. Andererseits maskiert pytest-mask-secrets die direkte Ausgabe nicht, wenn die Option log_cli verwendet wird, sodass die Maskierungsfunktionen von CI-Workflows weiterhin nützlich sind. Oft ist es am besten, beide Tools gemeinsam zu verwenden, um den Schutz sensibler Daten zu gewährleisten.

Das ist es. Vielen Dank, dass Sie sich die Zeit genommen haben, diesen Beitrag zu lesen. Ich hoffe, es lieferte wertvolle Einblicke in die Verwendung von pytest-mask-secrets, um die Sicherheit Ihres Testprozesses zu erhöhen.

Viel Spaß beim Testen!

Das obige ist der detaillierte Inhalt vonTestgeheimnisse mit pytest-mask-secrets sichern. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn