Compare commits
4 Commits
f3a1cb1ea9
...
61c30e6af5
Author | SHA1 | Date | |
---|---|---|---|
61c30e6af5 | |||
16b10d9f87 | |||
fc5911df8c | |||
d0a48376e0 |
@ -6,7 +6,7 @@
|
||||
In der Arbeitsumgebung des Partnerunternehmens besteht zum Zeitpunkt der Themenfindung der hier beleuchteten Arbeit kein
|
||||
Management für Secrets und Logindaten zwischen Entwickler*innen. Logindaten zu den Projekten des Unternehmens liegen schlicht in einem \ac{1P}-Vault.
|
||||
\ac{1P} ist der vom Unternehmen verwendete Passwortmanager. Auf diesen Vault haben sämtliche internen Entwickler*innen Zugriff, jedoch keine externen Entwickler*innen.
|
||||
Das ist so, weil anderenfalls dLesezugriff auf sämtliche Einträge dieses Vaults gegeben werden müssten.
|
||||
Das ist so, weil anderenfalls Lesezugriff auf sämtliche Einträge dieses Vaults gegeben werden müssten.
|
||||
\ac{1P} unterstützt keine Freigaben einzelner Einträge an andere Nutzer, ohne diese Einträge in einen eigenen Vault zu kopieren.
|
||||
Würden diese manuell in einen eigenen Vault kopiert werden, müssten diese Einträge fortan redundant gepflegt werden. Das ist eine Fehlerquelle, die zu
|
||||
asynchronen Einträgen führt. Außerdem ist das ein großer Arbeitsaufwand.
|
||||
|
@ -128,7 +128,7 @@ abgefragt werden. Hier ist ein CLI-API-Aufruf pro Eintrag erforderlich. Sind ein
|
||||
mit einer bestimmten originalen ID im Durchschnitt $n=30; \frac{n}{2} = 15$ Sekunden. Im langsamsten Fall wären es $n=30$ Sekunden.
|
||||
Ein Kopierforgang stellt zwei Aufrufe dar (=\textit{lesen,erstellen}), also dauert das Kopieren von 30 Einträgen $n=30; 2n = 60$ Sekunden.
|
||||
Das \ac{1P}-CLI kann zwar für Detail-Aufrufe mehrere Eintrags-IDs auf Standard-Input annehmen und bearbeiten, jedoch zeigen Versuche des Autors dies zu implementieren, dass das nicht die
|
||||
Zeitkomplexität von $O(n)$ verändert. Das heisst, eine Anfrage für 10 Einträge zu stellen, dauert in etwa zehn mal so lange,
|
||||
Zeitkomplexität von $O(n)$ verändert. Das heißt, eine Anfrage für 10 Einträge zu stellen, dauert in etwa zehn mal so lange,
|
||||
wie zehn Anfragen für jeweils einen Eintrag zu stellen.
|
||||
|
||||
Eine spätere Ergänzung, um die programmatische Auslesung der Einträge in $O(n)$ anstatt $O(n^2)$ zu gewährleisten, ist die Unterhaltung von Mapping-Objekten in Entwickler*innen-Vaults.
|
||||
@ -210,47 +210,112 @@ Ein Beispiel mit dem im Rahmen dieser Ausarbeitung bereitgestellten Filtermodul
|
||||
\label{fig:flowchart-filtermodule-resolve-1p-secret}
|
||||
\end{nicepic}
|
||||
|
||||
Die generelle Funktionsweise des Filtermoduls ist es, drei Arten von Eingabeformaten zu unterstützen.
|
||||
Diese sind:
|
||||
\subsection*{Kein erkanntes Format}
|
||||
Wird kein bekanntes Format, wird der Wert unverändert zurückgegeben. Das ermöglicht Rückwärtskompatibilät, dass
|
||||
nach-wie-vor hardgecodede Secrets weiterhin funktionieren, und nicht versehentlich als \ac{UUID} interpretiert werden.
|
||||
\subsection{Akzeptierte Formate}
|
||||
Das Filtermodul akzeptiert mehrere, verschiedene Eingabeformate und ist rückwärtskompatibil.
|
||||
|
||||
\subsection*{1P:<...>}
|
||||
Beginnt der Wert mit \enquote{1P:}, so wird alles nach danach als \ac{UUID} interpretiert.
|
||||
\subsubsection*{Kein erkanntes Format}
|
||||
Wird kein bekanntes Format erkannt, wird der Wert unverändert zurückgegeben. Das ermöglicht Rückwärtskompatibilä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.
|
||||
|
||||
\subsubsection*{1P:<...>}
|
||||
Beginnt der Wert mit \enquote{1P:}, so wird alles Nachfolgende als \ac{UUID} interpretiert.
|
||||
Es wird versucht, das Feld \enquote{password} aus diesem Eintrag zu dereferenzieren.
|
||||
|
||||
\subsection*{Objektformat}
|
||||
Wird ein Yaml-Objekt übergeben, werden die Keys \enquote{1P\_secret\_uuid} und \enquote{1P\_field\_id} erwartet,
|
||||
die die \ac{UUID} und eine Feld-ID für den Eintrag erwarten. 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, wird auf den Standardwert \enquote{password} zurückgefallen.
|
||||
\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.
|
||||
|
||||
|
||||
\subsection{Übersetzung der UUIDs}
|
||||
Um die für eine*n Entwickler*in gegebene, private \ac{UUID} für eine öffentliche, sich in der Host-Konfiguration gesetzte
|
||||
\ac{UUID} zu ermitteln, frägt das Filtermodul zunächst den Mapping-Eintrag aus dem Entwickler*innen-Vault ab und schlägt
|
||||
hierin die öffentliche \ac{UUID} nach.
|
||||
Um die private \ac{UUID} zu ermitteln, die zu der öffentlichen \ac{UUID} gehört, die in der Host-Konfiguration steht,
|
||||
frägt das Filtermodul den Mapping-Eintrag aus dem jeweiligen Entwickler*innen-Vault an und schlägt die öffentliche \ac{UUID} darin nach.
|
||||
Die daraus resultierende \ac{UUID} kann von einem*r externen Entwickler*in angefragt werden.
|
||||
|
||||
\subsection{Unterscheidung zwischen internen und externen Entwickler*innen}
|
||||
Ist in der Docker-Ansible-Konfigurationsdatei eine Entwickler*innen-Vault-\ac{UUID} definiert, wird von einem*r externe*n Entwickler*in ausgegangen.
|
||||
Ist in der Docker-Ansible-Konfigurationsdatei eine Entwickler*innen-Vault-\ac{UUID} definiert, so wird von einem*r externe*n Entwickler*in ausgegangen.
|
||||
Ist stattdessen definiert, dass die in den Host-Konfigurationen angegebenen, öffentlichen \acp{UUID} direkt angefragt werden sollen, wird
|
||||
von einem*r interne*n Entwickler*in ausgegangen. Sind beide Konfigurationen gegeben, wird ein Inkompatibilitätsfehler erhoben.
|
||||
von einem*r interne*n Entwickler*in ausgegangen. Sind beide Konfigurationen zugleich gegeben, wird ein Inkompatibilitätsfehler erhoben.
|
||||
Ist ein*e interne*r Entwickler*in angenommen, so wird der Mapping-Schritt übersprungen. Der verbleibende Prozess bleibt unberührt.
|
||||
|
||||
\subsection{Kommunikation mit 1Password}
|
||||
Ist eine \ac{UUID} ermittelt, auf die der*ie Nutzer*in Zugriff hat, wird diese über das \ac{1P}-CLI angefragt.
|
||||
Das geht via \textit{op item get <UUID>} mit dem Zusatz \textit{--format json}, um die Ausgabe programmatisch auswertbar zu machen.
|
||||
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:
|
||||
\begin{itemize}
|
||||
\item[Datenbank-Host]
|
||||
\item[Datenbank-Port]
|
||||
\item[Datenbank-Benutzername]
|
||||
\item[Datenbank-Passwort]
|
||||
\item[Datenbank-Name]
|
||||
\item Datenbank-Host
|
||||
\item Datenbank-Port
|
||||
\item Datenbank-Benutzername
|
||||
\item Datenbank-Passwort
|
||||
\item Datenbank-Name
|
||||
\end{itemize}
|
||||
Diese Einträge abzufragen dauert durch das imperformante \ac{1P}-CLI rund 17 Sekunden.
|
||||
|
||||
\subsection{Optimierung}
|
||||
Es bieten sich einige Möglichkeiten an den in \fullref{fig:flowchart-resolve-1p-secret} zu beschleunigen.
|
||||
Es bieten sich zwei Möglichkeiten an, den in \fullref{fig:flowchart-filtermodule-resolve-1p-secret} abgebildeten Prozess zu beschleunigen.
|
||||
Diese beschäftigen sich damit, zu limitieren, wie oft das \ac{1P}-CLI angefragt wird:
|
||||
|
||||
\begin{description}
|
||||
\item [Das Mapping-Objekt zwischenspeichern] \hfill \\
|
||||
Anstatt das Mapping-Objekt für jedes angefragte Secret erneut abzufragen, könnte 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üsse 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.
|
||||
E.g. nach jedem angefragten Secret, verliert er seinen internen Zustand.
|
||||
Daher muss dieses zwischengespeichert in einer Datei stattfinden. 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}
|
||||
\includegraphics[width=1\textwidth]{images/flowchart-resolve-1p-secret-with-caching.png}
|
||||
\captionof{figure}{Flussdiagramm: Businesslogik des 1P-Resolver-Filtermoduls, mit Zwischenspeicher}
|
||||
\caption*{Quelle: Eigene Darstellung}
|
||||
\label{fig:flowchart-filtermodule-resolve-1p-secret-with-caching}
|
||||
\end{nicepic}
|
||||
|
||||
\subsubsection{Mapping-Zwischenspeicher}
|
||||
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.
|
||||
Das deckt folgenden Problemfall ab:
|
||||
|
||||
\begin{enumerate}
|
||||
\item Zwischenspeicher wird erstellt
|
||||
\item Entwickler*in erhält mehr Berechtigungen
|
||||
\item Entwickler*in will diese Berechtungen nutzen
|
||||
\item Der Zwischenspeicher wird verwendet, spiegelt diese neuen Berechtigungen aber nicht wider
|
||||
\item Der Prozess schlägt zu Unrecht fehl
|
||||
\end{enumerate}
|
||||
|
||||
Dieser Prozess würde durch diese Vorkehrung so aussehen:
|
||||
\begin{enumerate}
|
||||
\item Zwischenspeicher wird erstellt
|
||||
\item Entwickler*in erhält mehr Berechtigungen
|
||||
\item Entwickler*in will diese Berechtungen nutzen
|
||||
\item Der Zwischenspeicher wird verwendet, spiegelt diese neuen Berechtigungen aber nicht wider
|
||||
\item Das System erneuert den Zwischenspeicher
|
||||
\item Der Zwischenspeicher spiegelt nun die neuen Berechtiungen wider
|
||||
\item Der Prozess ist erfolgreich
|
||||
\end{enumerate}
|
||||
|
||||
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 wird dieser lokal zwischengespeichert. Das stellt ein Problem dar, sobald der Eintrag
|
||||
im Entwickler*innen-Vault manuell verändert wird. Das ist jedoch nicht angedacht.
|
||||
Die Entwickler*innen sollten keine Schreibberechtigung auf diesen haben und das Synchronisierungs-Werkzeug
|
||||
löscht Einträge und erstellt diese neu. Damit erhalten diese eine neue \ac{UUID} und sind somit im Zwischenspeicher nicht mehr repräsentiert.
|
||||
|
||||
\subsubsection{Eintrags-Zwischenspeicher}
|
||||
Durch das implementieren des Eintrags-Zwischenspeichers wird die Ausführzeit von acht Sekunden auf zwei Sekunden reduziert.
|
||||
|
||||
\subsubsection{Sicherheit}
|
||||
Um zu vermeiden, dass sensible Daten, wie zum Beispiel die Secrets in den Eintrags-Daten 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}
|
||||
|
@ -42,3 +42,15 @@
|
||||
year = {2025},
|
||||
note = {Zugriff: Februar 2025}
|
||||
}
|
||||
|
||||
@techreport{bib:BSI-TR-02102-1-2024,
|
||||
author = {{ BSI }},
|
||||
title = {Cryptographic Mechanisms: Recommendations and Key Lengths},
|
||||
institution = {Federal Office for Information Security (BSI)},
|
||||
type = {Technical Guideline TR-02102},
|
||||
version = {2024-1},
|
||||
number = {TR-02102-1},
|
||||
date = {2024-02-02},
|
||||
year = {2024},
|
||||
note = {Provides an assessment of the security and long-term orientation for selected cryptographic mechanisms.},
|
||||
}
|
||||
|
BIN
images/flowchart-resolve-1p-secret-with-caching.png
Normal file
BIN
images/flowchart-resolve-1p-secret-with-caching.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 136 KiB |
Loading…
x
Reference in New Issue
Block a user