selbst probelesen

This commit is contained in:
2025-02-26 16:46:35 +01:00
parent 09781d02c2
commit bd2096f494
9 changed files with 35 additions and 34 deletions

View File

@@ -59,7 +59,7 @@ aufwändig betrachtet wird und für den durch sie erbrachten Vorteil zu viel Auf
\subsubsection{Ansatz 3}
Der letzte Lösungsansatz befasst sich mit dem Erstellen dedizierter Vaults für jede*n Entwickler*in $d$.
Hierbei existiert eine Python-Toolbox, die anhand einer Yaml-Datei Referenzen auf diese Passwort-Einträge
Hierbei existiert eine Python-Toolbox, die anhand einer Yaml-Datei Referenzen auf die Passwort-Einträge
in $\text{Vault}_d$ legt und von dort entfernt, wenn ein solcher Zugriff laut der Yaml-Datei nicht mehr vorgesehen ist.
Diese Einträge können über feste Eintrags-IDs und über Regex bezogen auf die Eingrags-Titel einem/r Entwickler*in vorgesehen werden.
@@ -136,7 +136,7 @@ wie zehn Anfragen für jeweils einen Eintrag zu stellen.
In der naiven Herangehensweise, um einen Eintrag einer bestimmten originalen \ac{UUID} zu finden,
wird jeder Eintrag auf dessen originale \ac{UUID} geprüft, bis der passende Eintrag gefunden wurde.
Dieser Lösungsweg hat für \emph{einen} Eintrag eine Zeitkomplexität von $O(n)$.
Eine spätere Ergänzung, um die programmatische Auslesung \emph{eines} Eintrages einer bestimmten originalen \ac{UUID} in $O(1)$ anstatt $O(n)$ zu gewährleisten,
Eine spätere Ergänzung, um das programmatische Auslesen \emph{eines} Eintrages einer bestimmten originalen \ac{UUID} in $O(1)$ anstatt $O(n)$ zu gewährleisten,
ist die Unterhaltung von Mapping-Objekten in Entwickler*innen-Vaults.
Je Entwickler*innen-Vault wird abschließend zur Synchronisierung ein Mapping-Objekt erstellt.
Diese Mapping-Objekte halten die Informationen vorrätig, welche öffentliche \ac{1P}-\ac{UUID} zu welcher privaten \ac{1P}-\ac{UUID} gehört.
@@ -156,23 +156,22 @@ Werkzeug alle sich dort befindlichen Zugänge löschen. Das wäre ein Super-GAU
\subsubsection{Sicherheitsvorkehrungen}
Um das zu verhindern, wurde eine Liste mit wichtigen Vault-IDs fest einkodiert.
Alle Erstell- oder Löschmethoden müssen einen Vault-ID-Parameter erhalten, selbst wenn dieser technisch nicht notwendig ist.
Wenn diese Vault-ID nun in der Liste der fest kodierten Nutzvault-IDs vorkommt, meldet die Methode einen deskriptiven Fehler und beendet die Programmausführung.
Alle Erstell- oder Löschfunktionen müssen einen Vault-ID-Parameter erhalten, selbst wenn dieser technisch nicht notwendig ist.
Wenn diese Vault-ID nun in der Liste der fest kodierten Nutzvault-IDs vorkommt, meldet die Funktion einen deskriptiven Fehler und beendet die Programmausführung.
Somit ist gewährleistet, dass selbst bei einer fatalen Fehlkonfiguration kein Datenverlust entseht.
\section{Integration in Ansible}
Eine Anfordergung beschreibt, dass \ac{1P}-Einträge von Entwicklern*innen innerhalb von Ansible-Playbooks
dereferenziert und verwendet werden können.
\ac{1P} unterstützt nativ das Ersetzen von \ac{1P}-Referenzen in Dateien durch Secrets.
Diese Technik nennt sich \enquote{\ac{1PSA}}.
Diese Technologie ist jedoch nicht für die hier vorliegende Aufgabenstellung verwertbar, da die dem zugrunde liegende
Berechtigungsverwaltung auf Vault-Basis steht. Entweder hat ein*e Entwickler*in Zugriff auf einen gesamten Vault, oder er*sie hat keinen Zugriff auf den gesamten Vault.
Berechtigungsverwaltung auf Vaults basiert. Entweder hat ein*e Entwickler*in Zugriff auf einen gesamten Vault, oder er*sie hat keinen Zugriff auf den gesamten Vault.
Eine feinere Steuerung ist hier nicht möglich, jedoch für die hier gegebenen Anforderungen nötig. \cite{bib:1password-secrets-automation}
\ac{1PSA} erfasst \acp{UUID} und ist daher mit dem Konzept von Entwickler*innen-Vaults inkompatibel, da
Entwickler*innen hierbei eigene Kopien der originalen Einträge führen, die jeweils eigene \acp{UUID} haben.
Externe Entwickler*innen haben somit keinen Zugriff auf die originalen, öffentlichen \acp{UUID} und die privaten \acp{UUID}, die im Entwickler*innen-Vault
vorhanden sind, gelten jeweils nur für eine*n Entwickler*in. Das erfordert eine maßgeschneiderte, programmatische Lösung:
vorhanden sind, existieren jeweils nur für eine*n Entwickler*in. Das erfordert eine maßgeschneiderte, programmatische Lösung:
\begin{nicepic}
\includegraphics[width=0.75\textwidth]{images/docker-ansible-structure.png}
@@ -187,7 +186,7 @@ Also eine UUID, die für alle Entwickler*innen greifbar ist.
Ab hier wird die Nutzergruppe \enquote{Entwickler*innen} in zwei Untergruppen strukturiert:
\begin{description}
\item [Interne Entwickler*innen] \hfill \\
Interne, festangestellte Entwickler*innen haben Vollzugriff auf den \ac{1P} und somit auch Zugriff auf die
Interne, festangestellte Entwickler*innen haben Vollzugriff auf \ac{1P} und somit auch Zugriff auf die
in den Host-Konfigurationen vermerkte, öffentliche \ac{UUID} eines Eintrages.
Da diese Entwickler*innen keinen Entwickler*innen-Vault haben, müssen sie direkt auf diese notierte, öffentliche \ac{UUID} zugreifen.
\end{description}
@@ -196,7 +195,7 @@ Ab hier wird die Nutzergruppe \enquote{Entwickler*innen} in zwei Untergruppen st
\item [Externe Entwickler*innen] \hfill \\
Externe Entwickler*innen verfügen über einen Entwickler*innen-Vault, nicht jedoch über direkten Zugriff auf die vermerkte, öffentliche \ac{UUID}.
Falls der*die jeweilige Entwickler*in Zugriff auf einen verlinkten Eintrag hat, dann nur auf eine Kopie des Eintrages in dessen*deren jeweiligen Entwickler*innen-Vault.
Diese Kopie hat eine andere \ac{UUID} als die, die in der Host-Konfiguration steht. Sie ist ja auf technischer Ebene ein anderer Eintrag, nur mit identischem Inhalt.
Diese Kopie hat eine andere \ac{UUID} als die, die in der Host-Konfiguration steht. Sie ist auf technischer Ebene ein anderer Eintrag, nur mit identischem Inhalt.
Die in den Host-Konfigurationen vermerkten, öffentlichen \acp{UUID} müssen also zunächst in eine private, sich im Entwickler*innen-Vault befindliche, \ac{UUID} übersetzt werden.
\end{description}
@@ -226,7 +225,8 @@ Ein Beispiel mit dem im Rahmen dieser Ausarbeitung bereitgestellten Filtermodul
Das Filtermodul akzeptiert mehrere, verschiedene Eingabeformate und ist rückwärtskompatibel.
\subsubsection*{Kein erkanntes Format}
Wird kein bekanntes Format erkannt, wird der Wert unverändert zurückgegeben. Das ermöglicht Rückwärtskompatibilät,
Wird kein bekanntes Format erkannt, wird der Wert unverändert zurückgegeben.
Das ermöglicht Rückwärtskompatibilität,
sodass nach-wie-vor hardgecodede Secrets funktionieren, und nicht versehentlich als \ac{UUID} interpretiert werden.
Das gewährleistet eine flüssigere Migration der Host-Konfigurationen, da somit bestehende Dateien weiterhin valide sind.
@@ -237,7 +237,7 @@ Es wird versucht, das Feld \enquote{password} aus diesem Eintrag zu dereferenzie
\subsubsection*{Objektformat}
Wird ein Yaml-Objekt übergeben, so werden die Keys \enquote{1P\_secret\_uuid} und \enquote{1P\_field\_id} erwartet.
Diese definieren die Werte der Eintrags-\ac{UUID} und der Feld-ID in der ein Secret steht. Das ermöglicht z.B. auch den Benutzernamen (\textit{1P\_field\_id: username}) eines
Eintrages abzufragen, anstelle nur des Passworts. Ist keine Feld-ID gegeben, so wird auf das Standardfeld \enquote{password} zurückgefallen.
Eintrages abzufragen, anstelle des Passworts. Ist keine Feld-ID gegeben, so wird auf das Standardfeld \enquote{password} zurückgefallen.
\subsection{Übersetzung der UUIDs}
@@ -256,7 +256,7 @@ Ist eine \ac{UUID} ermittelt, auf die der*die Nutzer*in Zugriff hat, wird diese
Dieser Aufruf ist: \textit{op item get <UUID>} mit dem Zusatz \textit{--format json}, um die Ausgabe programmatisch auswerten zu können.
\subsection{Performanz und Benchmarks}
Um diese Konfiguration zu testen, werden in einem Testszenario fünf Werte aus \ac{1P} ausgelesen:
Um die Implementation zu testen, werden in einem Testszenario fünf Werte aus \ac{1P} ausgelesen:
\begin{itemize}
\item Datenbank-Host
\item Datenbank-Port
@@ -264,7 +264,7 @@ Um diese Konfiguration zu testen, werden in einem Testszenario fünf Werte aus \
\item Datenbank-Passwort
\item Datenbank-Name
\end{itemize}
Diese Einträge abzufragen dauert durch das imperformante \ac{1P}-CLI rund 17 Sekunden.
Diese Einträge abzufragen dauert durch das imperformante \ac{1P}-CLI 17 Sekunden.
\subsection{Optimierung}
Es bieten sich zwei Möglichkeiten an, den in \fullref{fig:flowchart-filtermodule-resolve-1p-secret} abgebildeten Prozess zu beschleunigen.
@@ -272,15 +272,15 @@ Diese beschäftigen sich damit, zu limitieren, wie oft das \ac{1P}-CLI angefragt
\begin{description}
\item [Das Mapping-Objekt zwischenspeichern] \hfill \\
Anstatt das Mapping-Objekt für jedes angefragte Secret erneut abzufragen, könnte es zwischengespeichert werden.
Anstatt das Mapping-Objekt für jedes angefragte Secret erneut abzufragen, kann es zwischengespeichert werden.
\item [Ganze Einträge zwischenspeichern] \hfill \\
Für den Fall, dass ein Eintrag mehrach angefragt wird, könnte ein einmal angefragter Eintrag zwischengespeichert werden.
Würden mehrere Felder eines Eintrages angefragt werden (z.B. \textit{=Host, Port, Benutzername, Passwort, Name}), so müsste der gesamte Eintrag nur ein mal angefragt werden.
Für den Fall, dass ein Eintrag mehrfach angefragt wird, könnte ein einmal angefragter Eintrag zwischengespeichert werden.
Würden mehrere Felder desselben Eintrages angefragt werden (z.B. \textit{=Host, Port, Benutzername, Passwort, Name}), so müsste der gesamte Eintrag nur ein mal angefragt werden.
\end{description}
All diese Ansätze erfordern es Daten zwischenzuspeichern. Filtermodule haben allerdings keinen persistenten Arbeitsspeicher über verschiedene Aufrufe hinaus.
Also nach jedem angefragten Secret verliert das Filtermodul seinen Zustand.
Daher muss dieses zwischengespeichert in einer Datei stattfinden. Hierfür wird eine Tempdatei über Pythons \textit{tempfile.gettempdir()}-Funktion ermittelt.
Daher muss der Zwischenspeicher eine Datei sein. Hierfür wird eine Tempdatei über Pythons \textit{tempfile.gettempdir()}-Funktion ermittelt.
Diese Zwischenspeicher beinhalten die vom \ac{1P}-CLI zurückgegebenen Informationen.
\begin{nicepic}
@@ -294,7 +294,7 @@ Diese Zwischenspeicher beinhalten die vom \ac{1P}-CLI zurückgegebenen Informati
Wenn das Mapping-Objekt angefragt wird, so wird zunächst geprüft, ob es eine lokal zwischengespeicherte Version gibt.
Falls ja, wird diese geladen und verwendet.
Falls nein, wird es via dem \ac{1P}-CLI angefragt und lokal gespeichert.
Sollte der Mapping-Zwischenspeicher verwendet werden und das gesuchte Objekt nicht darin gefunden werden, so wird dieser Zwischenspeicher gelöscht und das Mapping-Objekt erneut angefragt.
Sollte der Mapping-Zwischenspeicher verwendet werden und das gesuchte Objekt nicht darin gefunden werden, so wird der Zwischenspeicher gelöscht und das Mapping-Objekt neu angefragt.
Das deckt folgenden Problemfall ab:
\begin{enumerate}
@@ -316,7 +316,7 @@ Dieser Prozess würde durch diese Vorkehrung so aussehen:
\item Der Prozess ist erfolgreich
\end{enumerate}
Durch die Implementation des Mapping-Zwischenspeichers, wird die Ausführzeit von 17 Sekunden auf acht Sekunden reduziert.
Durch die Implementation des Mapping-Zwischenspeichers wird die Ausführzeit von 17 Sekunden auf acht Sekunden reduziert.
\subsubsection{Eintrags-Zwischenspeicher}
Wird ein Eintrag von \ac{1P} angefragt, so soll das Filtermodul diesen lokal zwischenspeichern.
@@ -347,4 +347,4 @@ Durch das Implementieren des Eintrags-Zwischenspeichers wird die Ausführzeit vo
\subsubsection{Sicherheit}
Um zu vermeiden, dass sensible Daten, wie zum Beispiel die Secrets in den Eintragsdaten des Passwortmanagers im Klartext im Zwischenspeicher, für viele Prozesse lesbar, gespeichert werden,
werden diese in der Schreib- und Lesefunktion mit AES-256 verschlüsselt.
Die Wahl fällt auf AES-256, weil es keine bekannten Angriffe gegen AES-256 gibt, die wesentlich effektiver sind als generische Angriffe gegen Blockchiffren. \cite{bib:BSI-TR-02102-1-2024}
Die Wahl fällt auf AES-256, weil es keine bekannten Angriffe gegen AES-256 gibt, die wesentlich effektiver als generische Angriffe gegen Blockchiffren sind. \cite{bib:BSI-TR-02102-1-2024}