Kapitel 1. Einführung

Diese Arbeit wurde mithilfe von KI übersetzt. Wir freuen uns über dein Feedback und deine Kommentare: translation-feedback@oreilly.com

Erkunde mit uns die vielen gefährlichen Wege durch einen Pod und in Kubernetes. Sieh das System aus der Perspektive eines Gegners: Lerne die zahlreichen Verteidigungsansätze und ihre Schwachstellen kennen und betrachte historische Angriffe auf cloud-native Systeme durch die piratische Brille deines Erzfeindes: Dread Pirate Captain Hashjack.

Kubernetes ist schnell gewachsen und galt bisher nicht als "standardmäßig sicher". Das liegt vor allem daran, dass Sicherheitskontrollen wie Netzwerk- und Pod Sicherheitsrichtlinien auf Vanilla Clustern nicht standardmäßig aktiviert sind.

Hinweis

Als Autoren sind wir unendlich dankbar, dass unser Bogen dieCloud Native Erleuchtung gesehen hat, und wir bedanken uns herzlich bei den Freiwilligen, den Kernmitwirkenden und den Mitgliedern der Cloud Native Computing Foundation (CNCF) , die an der Vision und der Entwicklung von Kubernetes beteiligt waren. Dokumentation und Fehlerkorrekturen schreiben sich nicht von selbst, und die unglaublichen selbstlosen Beiträge, die die Open-Source-Gemeinschaften vorantreiben, wurden noch nie so freizügig gegeben oder so dankbar angenommen.

Sicherheitskontrollen sind in der Regel schwieriger zu bewerkstelligen als die komplexe Orchestrierung und die verteilten Systemfunktionen, für die Kubernetes bekannt ist. Besonders den Sicherheitsteams danken wir für ihre harte Arbeit! Dieses Buch ist eine Reflexion über die Pionierfahrt des guten Schiffes Kubernetes auf den kabbeligen und gefährlichen Meeren des Internets.

Der Schauplatz

Um in die Fantasie einzutauchen: Du bist gerade Chief Information Security Officer (CISO) des Start-up-Frachtunternehmens Boats, Cranes & Trains Logistics, im Folgenden BCTL genannt, geworden, das gerade seineKubernetes-Migration abgeschlossen hat.

captain

Das Unternehmen wurde schon einmal gehackt und "nimmt die Sicherheit ernst". Du hast die Befugnis, das zu tun, was getan werden muss, um das Unternehmen über Wasser zu halten - im übertragenen und im wörtlichen Sinne.

Willkommen im Job! Es ist dein erster Tag und du wurdest auf eine glaubwürdige Bedrohung deiner Cloud-Systeme aufmerksam gemacht. Der Container-hungrige Pirat Captain Hashjack und seine geheime Hacker-Crew planen einen Überfall auf die Kubernetes-Cluster von BCTL.

Wenn sie sich Zugang verschaffen, werden sie Bitcoin schürfen oder alle wertvollen Daten, die sie finden können, verschlüsseln. Du hast noch kein Bedrohungsmodell für deine Cluster und Anwendungen erstellt oder sie gegen diese Art von Angreifern gehärtet. Deshalb werden wir dich auf deiner Reise begleiten, um sie vor der Reise des salzigen Kapitäns zu schützen, der alles verschlüsselt, exfiltriert oder plündert, was er an Wertvollem finden kann.

Der BCTL-Cluster ist eine Vanilla-Kubernetes-Installation mit kubeadmauf einem öffentlichen Cloud-Provider. Zu Beginn sind alle Einstellungen auf die Standardwerte gesetzt.

Tipp

Historische Beispiele für die Instabilität von Schiffskontrollsystemen sind in dem Film Hackers (1995) zu sehen, in dem die Öltanker der Ellingson Mineral CompanyOpfer eines internen Angriffs durch den CISO des Unternehmens,Eugene "The Plague" Belford, werden.

Um die Härtung eines Clusters zu demonstrieren, nehmen wir ein unsicheres Beispielsystem. Es wird vom BCTL Site Reliability Engineering (SRE) Team verwaltet, was bedeutet, dass das Team für die Sicherung der Kubernetes Master Nodes verantwortlich ist. Dadurch wird die potenzielle Angriffsfläche des Clusters vergrößert: Ein verwalteter Dienst hostet die Kontrollebene (Masterknoten und etcd) separat, und ihre gehärtete Konfiguration verhindert einige Angriffe (wie eine direkte etcd Kompromittierung), aber beide Ansätze hängen von der sicheren Konfiguration des Clusters ab, um deine Workloads zu schützen.

Lass uns über deinen Cluster sprechen. Die Knoten befinden sich in einem privaten Netzwerksegment, sodass der öffentliche (Internet-)Verkehr sie nicht direkt erreichen kann. Der öffentliche Verkehr zu deinem Cluster wird über einen dem Internet zugewandten Load Balancer geleitet: Das bedeutet, dass die Ports auf deinen Knoten nicht direkt für die Welt zugänglich sind, es sei denn, der Load Balancer zielt darauf ab.

Auf dem Cluster laufen ein SQL-Datenspeicher sowie ein Frontend, eine API und ein Batch-Prozessor.

Die gehostete Anwendung - ein Buchungsservice für die Kunden deines Unternehmens - wird mit GitOps in einem einzigen Namensraum bereitgestellt, jedoch ohne Netzwerkrichtlinie oder Pod-Sicherheitsrichtlinie, wie in Kapitel 8 beschrieben.

Hinweis

GitOps ist ein deklaratives Konfigurations-Deployment für Anwendungen: Stell es dir wie das traditionelle Konfigurationsmanagement für Kubernetes-Cluster vor. Auf gitops.techkannst du mehr darüber lesen und indiesem Whitepaper erfährst du, wie du Git für GitOps härten kannst.

Abbildung 1-1 zeigt ein Netzwerkdiagramm des Systems.

System architecture diagram
Abbildung 1-1. Die Systemarchitektur deines neuen Unternehmens, BCTL

Das RBAC-System des Clusters wurde von Ingenieuren konfiguriert, die inzwischen weitergezogen sind. Die übernommenen Sicherheitsdienste verfügen über Intrusion Detection und Härtung, aber das Team hat sie von Zeit zu Zeit deaktiviert, weil sie "zu viel Lärm machten". Wir werden diese Konfiguration im weiteren Verlauf der Reise ausführlich besprechen. Doch zunächst wollen wir uns ansehen, wie wir Sicherheitsbedrohungen für deine Cluster vorhersagen können.

Einstieg in das Bedrohungsmodell

Zu verstehen, wie ein System angegriffen wird, ist für seine Verteidigung von grundlegender Bedeutung. Ein Bedrohungsmodell ermöglicht ein umfassenderes Verständnis eines komplexen Systems und bietet einen Rahmen für die Rationalisierung von Sicherheit und Risiko. Bedrohungsakteure kategorisieren die potenziellen Angreifer, gegen die sich ein System verteidigen soll.

Hinweis

Ein Bedrohungsmodell ist wie ein Fingerabdruck: Jeder ist anders. Ein Bedrohungsmodell basiert auf den Auswirkungen der Kompromittierung eines Systems: Ein Raspberry Pi Hobby-Cluster und die Cluster deiner Bank speichern unterschiedliche Daten, haben unterschiedliche potenzielle Angreifer und sehr unterschiedliche potenzielle Probleme, wenn in sie eingebrochen wird.

Bedrohungsmodelle können Einblicke in dein Sicherheitsprogramm und deine Konfiguration geben, aber sie lösen nicht alles - siehe Mark Mannings Kommentare zu CVEs in Abbildung 1-2. Du solltest sicherstellen, dass du die grundlegende Sicherheitshygiene (wie Patchen und Testen) befolgst, bevor du dich mit den fortgeschritteneren und technischen Angriffen befasst, die ein Bedrohungsmodell aufzeigen kann. Das Gleiche gilt für alle Sicherheitsratschläge.

Mark Manning on CVEs
Abbildung 1-2. Mark Mannings Einblick in die Schwachstellenbewertung und CVEs

Wenn deine Systeme durch veröffentlichte CVEs und eine Kopie von Kali Linux kompromittiert werden können, wird dir ein Bedrohungsmodell nicht helfen!

Akteure der Bedrohung

Deine Bedrohungsakteure sind entweder zufällig oder motiviert. Zu den zufälligen Gegnern gehören:

  • Vandalen (die Graffiti-Kids der Internet-Generation)

  • Unbeabsichtigte Eindringlinge auf der Suche nach einem Schatz (der meist deine Daten sind)

  • Vorbeifahrende "Skript-Kiddies", die jeden Code ausführen, den sie im Internet finden, wenn er behauptet, ihnen beim Hacken zu helfen

Gelegenheitsangreifer sollten für die meisten Systeme, die gepatcht und gut konfiguriert sind, kein Problem darstellen.

Motivierte Personen sind diejenigen, um die du dir Sorgen machen solltest. Dazu gehören Insider wie vertrauenswürdige Mitarbeiter, organisierte Verbrechersyndikate, die von weniger gut überwachten Staaten aus operieren, und staatlich geförderte Akteure, die sich mit dem organisierten Verbrechen überschneiden oder es direkt sponsern können. "Internetverbrechen" werden von internationalen Gesetzen nicht gut abgedeckt und können schwer zu kontrollieren sein.

Tabelle 1-1 kann als Leitfaden verwendet werden Bedrohungsmodellierung.

Tabelle 1-1. Taxonomie der Bedrohungsakteure
Schauspieler Motivation Fähigkeit Beispielhafte Angriffe

Vandale: Skript-Kiddie, Eindringling

Neugierde, persönlicher Ruhm.

Berühmtheit von den Dienst zum Erliegen bringen oder vertrauliche Daten eines hochrangigen Unternehmens kompromittieren.

Nutzt öffentlich verfügbare Tools und Anwendungen (Nmap, Metasploit, CVE PoCs). Einige Experimente. Die Angriffe sind schlecht versteckt. Geringes Maß an Zielgenauigkeit.

DOS im kleinen Maßstab.

Pflanzt Trojaner.

Startet vorgefertigte Exploits für Zugang, Krypto-Mining.

Motivierte Person: politischer Aktivist, Dieb, Terrorist

Persönliche, politische oder ideologische Vorteile.

Persönlicher Gewinn durch das Exfiltrieren und Verkaufen großer Mengen persönlicher Daten zu Betrugszwecken, vielleicht durch die Manipulation von Code in der Versionskontrolle oder der Speicherung von Artefakten oder durch das Ausnutzen verwundbarer Anwendungen aufgrund von Kenntnissen aus Ticketing- und Wiki-Systemen, OSINT oder anderen Teilen des Systems.

Persönliche Anerkennung durch DDOS eines großen, öffentlich zugänglichen Webdienstes.

Die Verunstaltung der öffentlich zugänglichen Dienste durch Manipulation von Code in der Versionskontrolle oder auf öffentlichen Servern kann politische Botschaften an ein großes Publikum verbreiten.

Kann öffentlich verfügbare Exploits gezielt kombinieren. Open-Source-Lieferketten modifizieren. Angriffe von geringem Interesse verbergen.

Phishing.

DDOS.

Bekannte Schwachstellen ausnutzen, um sensible Daten aus Systemen zu erlangen, um daraus Profit zu schlagen oder um Websites zu verunstalten.

Sie kompromittieren Open-Source-Projekte, um Code einzubetten, der Umgebungsvariablen und Geheimnisse ausspäht, wenn der Code von Benutzern ausgeführt wird. Die exportierten Werte werden verwendet, um Zugang zum System zu erhalten und Krypto-Mining durchzuführen.

Insider: Arbeitnehmer, externe Auftragnehmer, Zeitarbeiter

Unzufriedenheit, Profit.

Persönlicher Gewinn durch Exfiltration und Verkauf großer Mengen persönlicher Daten zu Betrugszwecken oder durch kleine Änderungen an der Integrität von Daten, um die Authentifizierung zu umgehen.

Verschlüsselte Datenmengen gegen Lösegeld.

Er kennt das System genau, weiß, wie man es ausnutzt, und verbirgt seine Handlungen.

Nutzt Privilegien, um Daten zu exfiltrieren (um sie weiterzuverkaufen).

Fehlkonfiguration/"Codebomben", um den Dienst als Vergeltung lahmzulegen.

Organisiertes Verbrechen: Syndikate, staatsnahe Gruppen

Lösegeld, Massenabzug von PII/Credentials/PCI-Daten.

Manipulation von Transaktionen zum finanziellen Vorteil.

Hohe Motivation, auf Datensätze zuzugreifen oder Anwendungen zu ändern, um Betrug im großen Stil zu erleichtern.

Krypto-Ransomware verschlüsselt z.B. Datenmengen und verlangt Geld.

Die Fähigkeit, beträchtliche Ressourcen zu investieren und "Autoren" anzuheuern, die die für ihre Zwecke erforderlichen Tools und Exploits schreiben. Gewisse Möglichkeiten zur Bestechung, Nötigung und Einschüchterung von Personen. Das Ausmaß der Zielsetzung variiert. Verbirgt sich, bis die Ziele erreicht sind.

Social Engineering/Phishing.

Ransomware (wird immer gezielter).

Kryptojacking.

RATTEN (im Rückgang).

Koordinierte Angriffe mit mehreren Exploits, die möglicherweise einen einzigen Zero-Day nutzen oder von einer abtrünnigen Person unterstützt werden, um die Infrastruktur zu durchbrechen (z. B. Carbanak).

Cloud-Service-Insider: Angestellter, externer Auftragnehmer, Zeitarbeiter

Persönlicher Gewinn, Neugierde.

Unbekannte Motivation, der Zugriff auf Daten sollte durch die Aufgabentrennung und technische Kontrollen des Cloud-Providers eingeschränkt werden.

Hängt von der Aufgabentrennung und den technischen Kontrollen beim Cloud-Provider ab.

Zugriff auf oder Manipulation von Datenspeichern.

Ausländische Nachrichtendienste (FIS): Nationalstaaten

Nachrichtendienstliche Erfassung, Störung kritischer nationaler Infrastruktur, unbekannt.

Sie können geistiges Eigentum stehlen, sich Zugang zu sensiblen Systemen verschaffen, massenhaft persönliche Daten auswerten oder bestimmte Personen anhand der im System gespeicherten Standortdaten aufspüren.

Hardware-/Software-Lieferketten unterbrechen oder verändern. Die Fähigkeit, Organisationen/Lieferanten zu infiltrieren, Forschungsprogramme in Anspruch zu nehmen und mehrere Zero-Days zu entwickeln. Hochgradig zielgerichtet. Hohe Verschleierungstiefe.

Stuxnet (mehrere Zero-Days, Infiltration von 3 Organisationen, darunter 2 PKI-Infrastrukturen mit Offline-Root-CAs).

SUNBURST (gezielter Angriff auf die Lieferkette, Infiltration von Hunderten von Organisationen).

Hinweis

Bedrohungsakteure können eine Mischung aus verschiedenen Kategorien sein. Eugene Belford zum Beispiel war ein Insider, der sich fortschrittlicher Methoden des organisierten Verbrechens bediente.

Captain Hashjack ist ein motivierter krimineller Gegner, der Erpressung oder Raub im Sinn hat. Wir sind mit ihren Taktiken nicht einverstanden - sie spielen nicht fair und sind Schmarotzer - also werden wir unser Möglichstes tun, um ihre unwillkommenen Interventionen zu vereiteln.

Die Piraten-Crew ist auf der Suche nach allen vorteilhaften Informationen, die sie im Internet finden kann, und hat bereits Aufklärungsarbeit gegen BCTL geleistet. Mithilfe von Open-Source-Intelligence (OSINT)-Techniken wie dem Durchsuchen von Stellenausschreibungen und LinkedIn-Skills der aktuellen Mitarbeiter haben sie die Technologien identifiziert, die in der Organisation verwendet werden. Sie wissen, dass du Kubernetes verwendest, und können erraten, mit welcher Version du angefangen hast.

Dein erstes Bedrohungsmodell

Um einen Kubernetes-Cluster zu modellieren, beginnst du mit einer Architektur des Systems, wie in Abbildung 1-3 dargestellt. Sammle so viele Informationen wie möglich, damit alle Beteiligten auf dem gleichen Stand sind, aber es gibt ein Gleichgewicht: Achte darauf, dass du die Leute nicht mit zu vielen Informationen überforderst.

Example Kubernetes attack vectors
Abbildung 1-3. Beispiele für Kubernetes-Angriffsvektoren(Aqua)
Tipp

Mehr über die Bedrohungsmodellierung von Kubernetes erfährst du in dem O'Reilly-Kurs von ControlPlane: Kubernetes-Bedrohungsmodellierung.

Dieses erste Diagramm kann das gesamte System abbilden, oder du entscheidest dich dafür, nur einen kleinen oder wichtigen Bereich zu betrachten, z. B. einen bestimmten Pod, Knoten oder die Kontrollebene.

Der "Anwendungsbereich" eines Bedrohungsmodells ist sein Ziel: die Teile des Systems, die uns derzeit am meisten interessieren.

Als Nächstes zoomst du auf in den von dir ausgewählten Bereich. Modelliere die Datenflüsse und Vertrauensgrenzen zwischen den Komponenten in einem Datenflussdiagramm wie in Abbildung 1-3. Wenn du die Vertrauensgrenzen festlegst, überlege dir, wie Captain Hashjack versuchen könnte, die Komponenten anzugreifen.

Eine erschöpfende Liste von Möglichkeiten ist besser als eine unvollständige Liste von Machbarkeiten.

Adam Shostack, Bedrohungsmodellierung

Jetzt, da du weißt, gegen wen du dich verteidigst, kannst du einige hochgradige Bedrohungen für das System aufzählen und prüfen, ob deine Sicherheitskonfiguration geeignet ist, sie abzuwehren.

Um mögliche Bedrohungen zu erzeugen, musst du die Denkweise der Angreifer verinnerlichen: ihre Instinkte nachahmen und ihren Taktiken zuvorkommen. Das bescheidene Datenflussdiagramm in Abbildung 1-4 ist die Verteidigungskarte deiner Siliziumfestung, und sie muss Hashjack und seinen finsteren Gesellen widerstehen können.

Kubernetes data flow diagram
Abbildung 1-4. Kubernetes-Datenflussdiagramm(GitHub)
Tipp

Die Modellierung von Bedrohungen sollte mit möglichst vielen Stakeholdern durchgeführt werden (Entwicklung, Betrieb, QS, Produkt, Geschäftsinteressenten, Sicherheit), um eine Vielfalt von Gedanken zu gewährleisten.

Du solltest versuchen, die erste Version eines Bedrohungsmodells ohne äußere Einflüsse zu erstellen, um eine flüssige Diskussion und eine organische Ideenentwicklung zu ermöglichen. Dann kannst du externe Quellen hinzuziehen, um die Gedanken der Gruppe zu überprüfen.

Jetzt, da du alle Informationen über dein System hast, die du sammeln kannst, machst du ein Brainstorming. Denke an Einfachheit, Hinterhältigkeit und Gerissenheit. Jeder denkbare Angriff kommt in Frage, und du bewertest die Wahrscheinlichkeit des Angriffs separat. Manche Leute verwenden dafür gerne Punkte und gewichtete Zahlen, andere ziehen es vor, die Angriffswege zu rationalisieren.

Halte deine Gedanken in einer Tabelle, einer Mindmap, einer Liste oder was auch immer für dich sinnvoll ist, fest. Es gibt keine Regeln, nur das Ausprobieren, Lernen und Wiederholen deiner eigenen Version des Prozesses. Versuche, Bedrohungen zu kategorisieren und stelle sicher, dass du deine erfassten Daten leicht überprüfen kannst. Wenn du den ersten Durchgang gemacht hast, überlege, was du übersehen hast und mache einen schnellen zweiten Durchgang.

Dann hast du deine ersten Bedrohungen erstellt - gut gemacht! Jetzt ist es an der Zeit, sie in einem Diagramm darzustellen, damit sie leichter zu verstehen sind. Das ist die Aufgabe eines Angriffsbaums: die Karte des Piratenschatzes.

Angriffsbäume

Ein Angriffsbaum zeigt mögliche Infiltrationsvektoren. Abbildung 1-5 zeigt, wie man die Kubernetes-Kontrollebene ausschalten kann.

Angriffsbäume können komplex sein und sich über mehrere Seiten erstrecken, also kannst du klein anfangen, wie dieser Zweig mit reduziertem Umfang.

Dieser Angriffsbaum konzentriert sich auf den Denial of Service (DoS), der den Zugriff auf das System ("Dienst") verhindert ("denies"). Das Ziel des Angreifers steht oben im Diagramm, und die ihm zur Verfügung stehenden Wege beginnen an der Wurzel (unten) des Baums. Der Schlüssel auf der linken Seite zeigt die Formen, die erforderlich sind, damit die logischen "ODER"- und "UND"-Knoten erfüllt werden, die sich bis zur Spitze des Baums aufbauen: das negative Ergebnis. Verwirrenderweise können Angriffsbäume sowohl von unten nach oben als auch von oben nach unten aufgebaut werden: In diesem Buch verwenden wir ausschließlich den Bottom-up-Ansatz. Wir gehen die Angriffsbäume später in diesem Kapitel durch.

Kubernetes attack tree
Abbildung 1-5. Kubernetes-Angriffsbaum(GitHub)
Tipp

Kelly Shortridgesbrowserinternes Sicherheitsentscheidungsbaum-Tool Deciduous kann verwendet werden, um diese Angriffsbäume als Code zu generieren.

Im weiteren Verlauf des Buches werden wir diese Techniken nutzen, um risikoreiche Bereiche von Kubernetes zu identifizieren und die Auswirkungen erfolgreicher Angriffe zu untersuchen.

Tipp

Ein Angriff auf die YAML-Deserialisierung Billion laughs in CVE-2019-11253betraf Kubernetes bis v1.16.1, indem der API-Server angegriffen wurde. Dieser Angriffsbaum ist nicht auf zu finden, da er gepatcht ist, aber das Hinzufügen historischer Angriffe zu deinen Angriffsbäumen ist eine nützliche Methode, um ihre Bedrohung zu erkennen, wenn du denkst, dass sie mit hoher Wahrscheinlichkeit in deinemSystem wieder auftauchen werden.

Beispiel-Angriffsbäume

Es ist auch nützlich , Angriffsbäume zu zeichnen, um sich ein Bild davon zu machen, wie das System angegriffen werden kann und um die Kontrollen einfacher zu verstehen. Glücklicherweise enthält unser erstes Bedrohungsmodell einige nützliche Beispiele.

Diese Diagramme verwenden eine einfache Legende, die in Abbildung 1-6 beschrieben wird.

Attack Tree Legend
Abbildung 1-6. Legende des Angriffsbaums

Das "Ziel" ist das Ziel des Angreifers und das, was wir mit dem Angriffsbaum verhindern wollen.

Die logischen "UND"- und "ODER"-Gatter legen fest, welche der untergeordneten Knotenpunkte vervollständigt werden müssen, um sie zu durchlaufen.

In Abbildung 1-7 siehst du einen Angriffsbaum, der mit der Remotecodeausführung durch einen Bedrohungsakteur in einem Container beginnt.

Attack Tree: Compromised Container
Abbildung 1-7. Angriffsbaum: kompromittierter Container

Du weißt jetzt, wovor du dich schützen willst und hast einige einfache Angriffsbäume, so dass du die Kontrollen, die du einsetzen willst, quantifizieren kannst.

Stand der Technik

An diesem Punkt hat dein Team eine Liste von Bedrohungen erstellt. Jetzt können wir sie mit einigen gängigen Bedrohungsmodellierungstechniken und Daten abgleichen:

Dies ist auch ein guter Zeitpunkt, um bereits existierende, verallgemeinerte Bedrohungsmodelle zu nutzen:

Kein Bedrohungsmodell ist jemals vollständig. Es ist eine punktuelle Bemühung deiner Stakeholder und sollte regelmäßig überarbeitet und aktualisiert werden, da sich die Architektur, die Software und die externen Bedrohungen ständig ändern werden.

Software ist nie fertig. Du kannst nicht einfach aufhören, an ihr zu arbeiten. Sie ist Teil eines Ökosystems, das in Bewegung ist.

Moxie Marlinspike

Fazit

Jetzt bist du mit den Grundlagen ausgestattet: Du kennst deinen Gegner, Captain Hashjack, und seine Fähigkeiten. Du weißt, was ein Bedrohungsmodell ist, warum es wichtig ist und wie du zu dem Punkt kommst, an dem du eine 360°-Sicht auf dein System hast. In diesem Kapitel haben wir uns mit Bedrohungsakteuren und Angriffsbäumen beschäftigt und sind ein konkretes Beispiel durchgegangen. Wir haben jetzt ein Modell im Kopf und werden die wichtigsten Kubernetes-Bereiche untersuchen. Lass uns ins kalte Wasser springen: Wir beginnen mit dem Pod.

Get Kubernetes hacken now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.