Kubernetes RBAC -Analyse machte einfach
Krane ist ein einfaches Tool aus statischer Analyse von Kubernetes RBAC. Es identifiziert potenzielle Sicherheitsrisiken im K8S -RBAC -Design und macht Vorschläge zur Minderung dieser Minderung. Krane Dashboard präsentiert die aktuelle RBAC -Sicherheitspflicht und ermöglicht die Definition durch die Definition.
Sie können mit Krane beginnen, indem Sie es über das Helm -Diagramm in Ihrem Zielkubernetes -Cluster installieren oder lokal mit Docker ausgeführt werden.
Es wird angenommen, dass Sie Helm CLI auf Ihrem Computer installiert haben.
$ helm repo add appvia https://appvia.github.io/krane
$ helm repo update
$ helm install krane appvia/krane --namespace krane --create-namespaceFolgen Sie die Ausgabe des Helm-Diagramm-Installationsausgangs zum Anschluss von Krane Dashboard.
Es wird angenommen, dass Sie Docker auf Ihrer lokalen Maschine laufen lassen. Installieren Sie Docker-Compose, wenn Sie es noch nicht getan haben.
Krane hängt von Redisgraph ab. docker-compose Stack definiert alles, was erforderlich ist, um den Krane -Service lokal zu erstellen und zu betreiben. Es wird sich auch um seine Redisgraph -Abhängigkeit kümmern.
docker-compose up -d
Krane Docker Image wird automatisch vorgefertigt, wenn sie nicht bereits auf lokaler Maschine vorhanden sind.
Beachten Sie, dass Krane beim Ausführen docker-compose den RBAC- Bericht und das Dashboard nicht automatisch starten. Stattdessen schläft der Container standardmäßig 24 Stunden - dieser Wert kann in docker-compose.override.yml angepasst werden. Exec in einen laufenden Krane -Container, um Befehle auszuführen. Lokale docker-compose montiert Kube Config ( ~/.kube/config ) im Container, in dem Sie Berichte gegen alle Kubernetes-Cluster ausführen können, auf die Sie bereits Zugriff haben.
Exec in einen laufenden Krane -Container.
docker-compose exec krane bash Sobald Sie im Container anfangen können, können Sie krane -Befehle verwenden. Probieren Sie krane -help .
krane -hUm zu untersuchen, welche Dienste ausgeführt werden und welche zugehörigen Ports:
docker-compose ps
Krane und seine Abhängigkeitsdienste zu stoppen:
docker-compose down
$ krane --help
NAME:
krane
DESCRIPTION:
Kubernetes RBAC static analysis & visualisation tool
COMMANDS:
dashboard Start K8s RBAC dashboard server
help Display global or [command] help documentation
report Run K8s RBAC report
GLOBAL OPTIONS:
-h, --help
Display help documentation
-v, --version
Display version information
-t, --trace
Display backtrace when an error occurs
AUTHOR:
Marcin Ciszak <[email protected]> - Appvia Ltd <appvia.io>
kubectl -KontextUm einen Bericht gegen einen laufenden Cluster auszuführen, müssen Sie einen Kubectl -Kontext bereitstellen
krane report -k <context>
Sie können auch -c <cluster-name> -Flag übergeben, wenn Sie das Tool gegen mehrere Cluster ausführen und für jeden Clusternamen separat in den Index -RBAC -Diagramm ausführen möchten.
Um einen Bericht gegen lokale RBAC YAML/JSON -Dateien auszuführen, geben Sie einen Verzeichnispfad an
krane report -d </path/to/rbac-directory>
Hinweis: Krane erwartet, dass die folgenden Dateien (entweder im YAML- oder JSON -Format) im angegebenen Verzeichnispfad vorhanden sein werden:
Wenn die Richtlinien für POD -Sicherheit nicht verwendet werden, können Sie die obige Erwartung umgehen, indem Sie eine psp -Datei manuell mit dem folgenden Inhalt erstellen:
{
"items" : []
} Beachten Sie, dass PodSecurityPolicy in Kubernetes v1.21 veraltet und in V1.25 aus Kubernetes entfernt wurde.
Ausführen eines Berichts von einem Container, der in Kubernetes -Cluster ausgeführt wird
krane report --incluster
Hinweis: Das von Krane verwendete Servicekonto erfordert Zugriff auf RBAC -Ressourcen. Einzelheiten finden Sie unter den Voraussetzungen.
Validierung der RBAC -Definition als Schritt in der CI/CD -Pipeline
krane report --ci -d </path/to/rbac-directory>
HINWEIS: Krane erwartet, dass eine bestimmte Namenskonvention für lokal gespeicherte RBAC -Ressourcendateien befolgt wird. Siehe Abschnitt oben. Um krane -Befehle auszuführen, wird empfohlen, dass CI Executor References quay.io/appvia/krane:latest docker Image.
Der CI -Modus wird durch das Flag --ci -Flag aktiviert. Krane gibt den Nicht -Null -Statuscode zusammen mit den Details zu den Risikoregeln des Brechens zurück, wenn eine oder mehrere Gefahren erkannt wurden.
Um RBAC Facettenbaum, Netzwerkdiagramm und neueste Berichtsergebnisse anzuzeigen, müssen Sie zuerst den Dashboard -Server starten.
krane dashboard
Cluster Flag -c <cluster-name> kann übergeben werden, wenn Sie das Dashboard gegen einen bestimmten Clusternamen ausführen möchten. Das Dashboard sucht nach Daten, die sich auf den angegebenen Clusternamen beziehen, der auf dem Dateisystem zwischengespeichert wird.
Der obige Befehl startet den lokalen Webserver auf der Standard -Port 8000 und zeigt den Dashboard -Link an.
Krane Indizes RBAC leistet in Redisgraph. Auf diese Weise können wir das Netzwerk von Abhängigkeiten effizient abfragen und einfach die Teilmenge von Cypherql verwenden, die von RedisGraph unterstützt werden.
Die folgenden Knoten werden in der Grafik für die relevanten RBAC -Objekte erstellt:
Psp - Ein PSP -Knoten, der Attribute rund um die POD -Sicherheitsrichtlinie enthält. Nur bei der Arbeit mit K8S <1,25 anwendbar.Rule - Regelknoten repräsentiert die Zugriffskontrollregel um Kubernetes -Ressourcen.Role - Rollenknoten repräsentiert eine bestimmte Rolle oder Clusterrole. kind -Attribut definiert die Art der Rolle.Subject - Subjekt repräsentiert alle möglichen Akteure im Cluster ( kind : Benutzer, Gruppen und serviceAccount)Namespace - Kubernetes Namespace -Knoten. :SECURITY - Definiert eine Verbindung zwischen Regel- und PSP -Knoten. Nur bei der Arbeit mit K8S <1,25 anwendbar.:GRANT - definiert einen Zusammenhang zwischen Rolle und Regel, der mit dieser Rolle verbunden ist.:ASSIGN - Definiert einen Zusammenhang zwischen einem Akteur (Subjekt) und gegebener Rolle/Clusterrole (Rollenknoten).:RELATION - definiert einen Zusammenhang zwischen zwei verschiedenen Akteurknoten (Subjekt).:SCOPE - Definiert eine Verbindung zwischen Rollen- und Namespace -Knoten.:ACCESS - Definiert eine Verbindung zwischen Subjekt- und Namespace -Knoten.:AGGREGATE -Definiert eine Verbindung zwischen Clusterrolen (ein Clusterrol-Aggregation ein anderer) A-(aggregates)->B:COMPOSITE -Definiert eine Verbindung zwischen Clusterrolen (eine Clusterrole kann in einer anderen aggregiert werden) A<-(is a composite of)-B Alle Kanten sind bidirektional, was bedeutet, dass Diagramm in beide Richtungen abgefragt werden kann. Nur Ausnahmen sind :AGGREGATE und :COMPOSITE Beziehungen, die unisch lichtet, obwohl sie sich mit denselben Kantenknoten befassen.
Um das Diagramm direkt abzufragen, können Sie in einen ausgeführten redisgraph Container ausführen, redis-cli starten und Ihre willkürlichen Abfragen ausführen. Befolgen Sie die offiziellen Anweisungen für Beispiele für Befehle.
Sie können die Grafik auch von der Krane -Konsole abfragen. Zuerst Exec in das Ausführen von Krane Container, dann
# Start Krane console - this will open interactive ruby shell with Krane code preloaded
console
# Instantiate Graph client
graph = Krane :: Clients :: RedisGraph . client cluster : 'default'
# Run arbitrary CypherQL query against indexed RBAC Graph
res = graph . query ( %Q(
MATCH (r:Rule {resource: "configmaps", verb: "update"})<-[:GRANT]-(ro:Role)<-[:ASSIGN]-(s:Subject)
RETURN s.kind as subject_kind, s.name as subject_name, ro.kind as role_kind, ro.name as role_name) )
# Print the results
res . print_resultset # Results...
+----------------+--------------------------------+-----------+------------------------------------------------+
| subject_kind | subject_name | role_kind | role_name |
+----------------+--------------------------------+-----------+------------------------------------------------+
| ServiceAccount | bootstrap-signer | Role | system:controller:bootstrap-signer |
| User | system:kube-controller-manager | Role | system::leader-locking-kube-controller-manager |
| ServiceAccount | kube-controller-manager | Role | system::leader-locking-kube-controller-manager |
| User | system:kube-scheduler | Role | system::leader-locking-kube-scheduler |
| ServiceAccount | kube-scheduler | Role | system::leader-locking-kube-scheduler |
+----------------+--------------------------------+-----------+------------------------------------------------+
HINWEIS: Beispielabfrage oben wählt alle Probanden mit zugewiesenen Rollen/Clusterrolen aus, die Zugriff auf update configmaps gewähren.
RBAC -Risikoregeln sind in der Regeln -Datei definiert. Die Struktur jeder Regel ist weitgehend selbsterklärend. Der integrierte Satz kann erweitert / überschrieben werden, indem zusätzliche benutzerdefinierte Regeln in die Cutom-Regeln-Datei hinzugefügt werden.
Makros sind "Container" für eine Reihe von gemeinsamen/gemeinsam genutzten Attributen und auf eine oder mehrere Risikoregeln verwiesen. Wenn Sie sich für die Verwendung von Makro in einer bestimmten Risikoregel entscheiden, müssten Sie es mit Namen verweisen, z. B. macro: <macro-name> . Beachten Sie, dass die im referenzierten macro definierten Attribute Vorrang vor denselben auf der Regelebene definierten Attributen haben.
Makro kann die folgenden Attribute enthalten:
query - Redisgraph Abfrage. Hat Vorrang vor template . Erfordert writer definiert.writer - Writer ist ein Ruby -Ausdruck, der zum Formatieren query verwendet wird. Der Schriftsteller hat Vorrang vor template .template - integrierte Abfrage-/Schriftsteller -Vorlagenname. Wenn query & writer nicht angegeben werden, wird ausgewählter Abfragetorner zusammen mit dem passenden Schriftsteller verwendet. Regel kann die folgenden Attribute enthalten:
id [Erforderliche] Regel -ID ist eine eindeutige Regelkennung.
group_title [Erforderlich] Titel, der für alle Elemente, die unter diese Risikoprüfung fallen, gilt.
severity [erforderlich] Schweregrad, wie einer von: Gefahr,: Warnung ,: Info.
info [Erforderlich] Textinformationen über die Überprüfung und Vorschläge zur Minderung des Risikos.
query [Conditonal] Redisgraph Abfrage.
template . Erfordert writer definiert. writer [Conditonal] Writer ist ein Ruby -Ausdruck, der zum Format von Abfragenergebnissen verwendet wird.
template . Erfordert, dass query definiert werden muss. template [Conditonal] Integrierte Abfrage/Schriftsteller-Vorlagenname. Wenn query & writer nicht angegeben werden, wird ausgewählter Abfragetorner zusammen mit dem passenden Schriftsteller verwendet.
Einige integrierte Vorlagen erfordern das Attribut match_rules auf einzelnen Regelebene, um eine korrekte Abfrage zu erstellen. Vorlagen benötigen es derzeit:
match_rules angegebenen Zugriffsregeln. Die generierte Graph -Abfrage gibt die folgenden Spalten zurück: match_rules [Conditonal] erforderlich, wenn template auf Match -Regeln angewiesen ist, um eine Abfrage zu erstellen.
match_rules :
- resources : ['cronjobs']
verbs : ['update'] custom_params [optional] Liste der benutzerdefinierten Schlüsselwertpaare, die in einer query und writer ersetzt werden sollen.
custom_params :
- attrA : valueA
- attrB : valueB{{attrA}} und {{attrB}} werden durch valueA bzw. valueB ersetzt. threshold [optional] numerischer Wert. Wenn dies definitiv ist, wird dies als Vorlagen -Platzhalter {{threshold}} im writer verfügbar.
macro [optional] Verweis auf gemeinsame Parameter, die in einem benannten Makro definiert sind.
disabled [optional] Wenn auf true festgelegt wird, deaktiviert es die angegebene Regel und schließt sie von der Bewertung aus. Standardmäßig sind alle Regeln aktiviert.
- id : verbose-rule-example
group_title : Example rule
severity : :danger
info : Risk description and instructions on how to mitigate it goes here
query : |
MATCH
(s:Subject)-[:ACCESS]->(ns:Namespace)
WHERE
NOT s.name IN {{whitelist_subject_names}}
RETURN
s.kind as subject_kind,
s.name as subject_name,
COLLECT(ns.name) as namespace_names
ORDER BY
subject_kind,
subject_name,
namespace_names DESC
threshold : 2
writer : |
if result.namespace_names.count > {{threshold}}
"#{result.subject_kind} #{result.subject_name} can access namespaces: #{result.namespace_names.join(', ')}"
end
disabled : true Das obige Beispiel oben definiert explizit eine Graph query , mit der das RBAC -Risiko bewertet wird, und einen writer , der zum Format -Abfrageergebnissatz verwendet wird. Die Abfrage wählt lediglich alle Subjects (mit Ausnahme von Whitelisted) und Namespaces aus, auf die sie Zugriff haben. Beachten Sie, dass das Ergebnissatz nur Subjects enthalten, die Zugriff auf mehr als 2 Namespaces (festgestellt haben, dass threshold dort festgestellt wurde?). Der Ausdruck des letzten writer wird als formatierte Ergebniselementausgabe erfasst.
writer kann über das Ergebnisobjekt über result zugreifen, wobei Methoden, die von den von der Abfrage zurückgegebenen Elementen, z. B. result.subject_kind , entsprechend, result.subject_name usw. zugreifen, usw.
Notiz:
{{threshold}} Platzhalter im writer wird durch den Keyword -Wert der Regel durch den threshold ersetzt.{{whitelist_subject_names}} repräsentiert ein benutzerdefiniertes Feld, das mit Whitelist -Werten interpoliert wird, die für eine bestimmte Regel id definiert sind. Wenn ein Platzhalterfeldname in der Whitelist nicht definiert ist, wird er standardmäßig durch ein leeres Array [''] ersetzt. Lesen Sie unten mehr über die Whitelisting. Eingebaute Vorlagen vereinfachen die Definition der Risikoregel erheblich. Sie sind jedoch so konzipiert, dass sie bestimmte Art von Informationen extrahieren und möglicherweise nicht gut zu Ihren benutzerdefinierten Regeln geeignet sind. Wenn Sie dieselbe query oder writer in mehreren Regeln wiederverwenden, sollten Sie in Betracht ziehen, diese an ein macro zu extrahieren und sie in Ihren benutzerdefinierten Regeln zu verweisen, um sie zu trocknen.
- id : risky-any-verb-secrets
group_title : Risky Roles/ClustersRoles allowing all actions on secrets
severity : :danger
info : Roles/ClusterRoles allowing all actions on secrets. This might be dangerous. Review listed Roles!
template : risky-role
match_rules :
- resources : ['secrets']
verbs : ['*'] Das obige Beispiel zeigt eine der integrierten Regeln. Es verweist risky-role , die bei der Verarbeitung die Regel erweitern wird, indem query und writer vor der Evalutation ausgelöst werden. match_rules werden verwendet, um eine entsprechende Übereinstimmungsabfrage zu erstellen.
Die optionale Whitelist enthält einen Satz benutzerdefinierter Attributnamen und die jeweiligen (Whitelist )werte.
Attributnamen und ihre Werte sind willkürlich. Sie sind in der Whitelist -Datei definiert und in drei separate Abschnitte unterteilt:
global - Top -Bereich. Hier definierte benutzerdefinierte Attribute gelten für alle Risikoregeln, unabhängig vom Cluster -Namen.common - benutzerdefinierte Attribute werden unabhängig vom Clusternamen auf eine spezifische Risikolegel id gescopt.cluster (mit verschachtelten Liste der Clusternamen) - Benutzerdefinierte Attribute gelten für eine bestimmte Risikolegel id für einen bestimmten Clusternamen. Bei jeder Risikoregie wird bei der Bewertung versucht, alle in der query verwendeten Parameter -Platzhalter, z. {{your_whitelist_attribute_name}} , zu interpolieren. Wenn ein Platzhalter -Parametername (dh ein Name zwischen den doppelten lockigen Klammern) einem der auf den Whitelisted Attributnamen für diese Risikoregel id entspricht, wird er durch den berechneten Wert ersetzt. Wenn für einen bestimmten Platzhalter keine Werte gefunden werden, wird es durch [''] ersetzt.
Beispiel Whitelist unten erzeugt das folgende placeholder-key => value Mapping für eine Risikoregel mit id Attributwert , das "etwas Risiko-RULE-ID" entspricht.
{{whitelist_role_names}} => ['acp:prometheus:operator']
{{whitelist_subject_names}} => ['privileged-psp-user', 'another-user']
Die oben genannten Platzhalterschlüssel, wenn sie in den benutzerdefinierten Grafikabfragen verwendet werden, werden durch ihre jeweiligen Werte bei der Bewertung der Risikoregel ersetzt.
Beispiel:
---
rules :
global : # global scope - applies to all risk rule and cluster names
whitelist_role_names : # custom attribute name
- acp:prometheus:operator # custom attribute values
common : # common scope - applies to specific risk rule id regardless of cluster name
some-risk-rule-id : # this corresponds to risk rule id defined in config/rules.yaml
whitelist_subject_names : # custom attribute name
- privileged-psp-user # custom attribute values
cluster : # cluster scope - applies to speciifc risk rule id and cluster name
default : # example cluster name
some-risk-rule-id : # risk rule id
whitelist_subject_names : # custom attribute nane
- another-user # custom attribute values Krane kann leicht in einem lokalen oder entfernten Kubernetes -Cluster eingesetzt werden.
Kubernetes -Namespace, Servicekonto zusammen mit geeignetem RBAC muss im Cluster vorhanden sein. Siehe die Voraussetzungen als Referenz.
Standard -Krane- EintragsPoint führt Bin/In-Cluster-Run aus, das darauf wartet, dass die RedisGraph-Instanz verfügbar ist, bevor die RBAC- Berichtsschleife und das Dashboard- Webserver gestartet werden.
Sie können bestimmte Aspekte der In-Cluster-Ausführung mit den folgenden Umgebungsvariablen steuern:
KRANE_REPORT_INTERVAL - definiert Intervall in Sekunden lang für den Bericht über statische Analyse von RBAC. Standard: 300 (in Sekunden, dh 5 Minuten).KRANE_REPORT_OUTPUT - definiert das RBAC -Risikobericht -Ausgangsformat. Mögliche Werte :json , :yaml , :none . Standard :: :json .Bevor wir beginnen, benötigen Sie die folgenden Tools:
Helmdiagramm installieren:
$ helm repo add appvia https://appvia.github.io/krane
$ helm repo update
$ helm install krane appvia/krane --namespace krane --create-namespaceSiehe Werte.YAML -Datei für weitere setzbare Optionen und Parameter.
kubectl create
--context < docker-desktop >
--namespace krane
-f k8s/redisgraph-service.yaml
-f k8s/redisgraph-deployment.yaml
-f k8s/krane-service.yaml
-f k8s/krane-deployment.yamlBeachten Sie, dass Krane Dashboard -Dienst standardmäßig nicht freigelegt ist!
kubectl port-forward svc/krane 8000
--context= < docker-desktop >
--namespace=krane
# Open Krane dashboard at http://localhost:8000Sie finden die Beispiele für die Bereitstellung im K8S -Verzeichnis.
Ändern Sie Manifests nach Bedarf für Ihre Bereitstellungen. Stellen Sie sicher, dass Sie auf die richtige Version des Krane Docker -Images in seiner Bereitstellungsdatei verweisen. Siehe Krane Docker Registry für verfügbare Tags oder verwenden Sie einfach latest .
Wenn Ihr K8S-Cluster mit integriertem Kompose-auf-Kubernetes-Controller-Support ausgestattet ist ( docker-desktop unterstützt es standardmäßig), können Sie Krane und seine Abhängigkeiten mit einem einzigen Docker-Stack-Befehl bereitstellen:
docker stack deploy
--orchestrator kubernetes
--namespace krane
--compose-file docker-compose.yml
--compose-file docker-compose.k8s.yml kraneHinweis: Stellen Sie sicher, dass Ihr aktueller Kube -Kontext vor dem Ausführen des obigen Befehls korrekt festgelegt ist!
Der Anwendungsstapel sollte jetzt in einem Kubernetes -Cluster und allen Diensten bereitgestellt werden, die bereit und freigelegt sind. Beachten Sie, dass Krane seine Berichtsschleife und den Dashboard -Server automatisch startet.
docker stack services --orchestrator kubernetes --namespace krane kraneDer obige Befehl erzeugt die folgende Ausgabe:
ID NAME MODE REPLICAS IMAGE PORTS
0de30651-dd5 krane_redisgraph replicated 1/1 redislabs/redisgraph:1.99.7 *:6379->6379/tcp
aa377a5f-62b krane_krane replicated 1/1 quay.io/appvia/krane:latest *:8000->8000/tcp
Überprüfen Sie Ihre Kubernetes -Cluster -RBAC -Sicherheitshaltung, indem Sie http: // localhost: 8000 besuchen.
Beachte
kubectl --context=my-remote-cluster --namespace=krane port-forward svc/krane 8000Um den Stapel zu löschen
docker stack rm krane
--orchestrator kubernetes
--namespace kraneKrane benachrichtigt Sie über erkannte Anomalien mit mittlerer und hoher Schwere über seine Slack -Integration.
Um Benachrichtigungen zu aktivieren, geben Sie Slack webhook_url & channel in der Datei config/config.yaml an oder setzen Sie alternativ sowohl SLACK_WEBHOOK_URL als auch SLACK_CHANNEL -Umgebungsvariablen. Umgebungsvariablen haben Vorrang vor Konfigurationsdateiwerten.
In diesem Abschnitt werden Schritte beschrieben, um die lokale Entwicklung zu ermöglichen.
Installieren Sie Krane -Code -Abhängigkeiten mit
./bin/setup Krane hängt von Redisgraph ab. docker-compose ist der schnellste Weg, um Kranes Abhängigkeiten lokal zum Laufen zu bringen.
docker-compose up -d redisgraphUm den Redisgraph -Service zu inspizieren, ist:
docker-compose psDienste zu stoppen:
docker-compose downZu diesem Zeitpunkt sollten Sie in der Lage sein, Krane -Codebasi- und Testen der Ergebnisse zu ändern, indem Sie Befehle in lokaler Shell aufrufen.
$ ./bin/krane --help # to get help
$ ./bin/krane report -k docker-desktop # to generate your first report for
# local docker-desktop k8s cluster
...So aktivieren Sie den lokalen Entwicklungsmodus der Dashboard UI
$ cd dashboard
$ npm install
$ npm startDadurch wird der Dashboard -Server automatisch gestartet, den Standardbrowser geöffnet und nach Quellendateien ändert.
Krane ist vorkonfiguriert, um mit Skoffold ein verbessertes Entwicklererlebnis zu erzielen. Iterieren im Projekt und die Validierung der Anwendung durch Ausführen des gesamten Stapels in lokaler oder Fernkubernetes -Cluster wurde einfach einfacher. Mit Code Hot-Reload können lokale Änderungen automatisch an den laufenden Container für einen schnelleren Entwicklungslebenszyklus verbreitet werden.
skaffold dev --kube-context docker-desktop --namespace krane --port-forwardTesten vor Ort mit
bundle exec rspecWir begrüßen alle Beiträge der Community! Schauen Sie sich unseren Beitragsführer an, um weitere Informationen zum Einstieg zu erhalten. Wenn Sie Krane verwenden, finden Sie es nützlich oder interessieren Sie sich im Allgemeinen für Kubernetes -Sicherheit, bitte wissen Sie es uns, indem Sie dieses Repo mitspielt . Danke!
Schließen Sie sich einer Diskussion über unseren Community -Kanal an.
Krane ist ein Community -Projekt und wir begrüßen Ihre Beiträge. Um einen Fehler zu melden, eine Verbesserung vorzuschlagen oder eine neue Funktion anzufordern, öffnen Sie bitte ein GitHub -Problem. Weitere Informationen darüber finden Sie in unserem beitragenden Leitfaden, wie Sie helfen können.
Weitere Informationen zu unseren Plänen für das Projekt finden Sie in unserer Roadmap.
Autor: marcin ciszak [email protected]
Copyright (C) 2019-2020 Appvia Ltd.
Dieses Projekt wird unter der Apache -Lizenz, Version 2.0, verteilt.