Django-tastypie: Benötigen Sie einen viel sichereren Standard: `DjangoAuthorization` sollte keinen Lesezugriff auf alle Modellobjekte ermöglichen

Erstellt am 6. Jan. 2016  ·  10Kommentare  ·  Quelle: django-tastypie/django-tastypie

Betrachtet man tastypie/authorization.py (ungefähr wie 133 - Hauptniederlassung am 04.01.2016), so ist die Standardeinstellung, dass sowohl read_list als auch read_details user.has_perm() Scheck umgehen, Das ist ziemlich unsicher und ein schlechter Standard.

Djangos Admin-Standard ist unkonventionell. So konnte ich sehen, wie es falsch interpretiert wurde.

https://docs.djangoproject.com/es/1.9/topics/auth/default/#permissions -and-authorisation

The Django admin site uses permissions as follows:
*   ... 
* Access to view the change list, view the “change” form and change an object is limited to users with the “change” permission for that type of object.

Im Wesentlichen ist "change_xyz" der Berechtigungscode für "read" und "update". Ich denke, die bessere Standardeinstellung wäre, Djangos Admin zu folgen:

diff --git a/tastypie/authorization.py b/tastypie/authorization.py
index 1d6f5aa..44b2d56 100644
--- a/tastypie/authorization.py
+++ b/tastypie/authorization.py
@@ -151,22 +151,14 @@ class DjangoAuthorization(Authorization):
         return model_klass

     def read_list(self, object_list, bundle):
-        klass = self.base_checks(bundle.request, object_list.model)
-
-        if klass is False:
-            return []
+        # By default, follows `ModelAdmin` "convention" to use `app.change_model`
+        # `django.contrib.auth.models.Permission` for both viewing and updating.
+        # https://docs.djangoproject.com/es/1.9/topics/auth/default/#permissions-and-authorization

-        # GET-style methods are always allowed.
-        return object_list
+        return self.update_list(object_list, bundle)

     def read_detail(self, object_list, bundle):
-        klass = self.base_checks(bundle.request, bundle.obj.__class__)
-
-        if klass is False:
-            raise Unauthorized("You are not allowed to access that resource.")
-
-        # GET-style methods are always allowed.
-        return True
+        return self.update_detail(object_list, bundle)

bug immediate

Hilfreichster Kommentar

Können Sie dies zumindest bei der Versionierung berücksichtigen, wenn Sie produktionsbrechende Änderungen vornehmen?
Die x.y.z -Versionierung von Tastypie ähnelt sehr dem, was die meisten Leute erwarten , das heißt normalerweise:

Erhöhen Sie bei gegebener Versionsnummer MAJOR.MINOR.PATCH Folgendes:
..
PATCH-Version, wenn Sie abwärtskompatible Fehlerbehebungen vornehmen.

Ich habe gerade eine sehr unangenehme Stunde damit verbracht, dies während einer neuen Produktionsbereitstellung zu verfolgen.

Alle 10 Kommentare

Ich schätze, dass dies bereits zusammengeführt wurde, aber ich habe immer noch Probleme damit. Bevor ich eine neue Anfrage öffne, ist hier mein Anliegen:

Diese Änderung bricht leider vorhandenen Code und ist daher abwärtskompatibel (zuvor haben alle GET-Anforderungen DjangoAuthorization bestanden). Um den eigenen Code zu korrigieren, bestehen die einzigen beiden Optionen darin, entweder allen Benutzern die Berechtigung zum Ändern (schlecht) zu erteilen oder DjangoAuthorization für eine benutzerdefinierte Implementierung der Leseaktionen zu unterordnen (möglicherweise viel Arbeit). War das beabsichtigt?

Ich schätze die Gründe dafür im Django-Administratorkontext, aber ich bezweifle, dass das Setzen von "Lesen" als Äquivalent zu "Ändern" in einem API-Kontext eine vernünftige Standardannahme ist, da es nicht das erwartete Verhalten ist. Wenn GET zusammen mit DjangoAuthorization eine zulässige Methode ist, warum sollte es dann den Zugriff verweigern, weil der Benutzer nicht über die Berechtigung change ?

Ich schlage ihm folgende alternative Implementierung vor:

_für read_detail_

  • Wenn das Modell eine view Berechtigung hat, überprüfen Sie dies (= Verbesserung für diejenigen, die es benötigen)
  • Wenn es keine view Berechtigung gibt, erlauben Sie immer (= abwärtskompatibel)

_für read_list_

  • Wenn das Modell eine list Berechtigung hat, überprüfen Sie dies (= Verbesserung für diejenigen, die es benötigen)
  • Wenn es keine list Berechtigung gibt, erlauben Sie immer (= abwärtskompatibel)

Auf diese Weise fügt tastypie einen Standard hinzu, der mit den Berechtigungsstandards von Django kompatibel ist, und bietet gleichzeitig einen einfachen Weg zur Verbesserung, indem Ansichts- und Listenberechtigungen für diejenigen hinzugefügt werden, die ihn benötigen, ohne eine benutzerdefinierte Implementierung von DjangoAuthorization zu schreiben.

Zumindest sollte es eine Möglichkeit geben, die Standardberechtigung anzugeben:

DjangoAuthorization(read_permission='view', # applies to both list, detail if not spec'd
                    read_list_permission='view', # list only
                    read_detail_permission='view') # detail only
# while we're at it, why not add the other permissions too
DjangoAuthorization(change_permission='change',
                    delete_permission='delete',
                    add_permission='add', 
                    # ... add options as per above for each
                    # <action>_<level> permission where 
                    # action is `change,delete,add,read`,  level is `list,detail`)

@ SeanHayes wird derjenige sein, der entscheidet.

Nur meine Meinung hier, ich denke, es war ein Sicherheitsproblem, standardmäßig das Lesen zuzulassen. Ich habe es überhaupt nicht erwartet, bis ich der Produktion sehr nahe war. Ich denke, dass es in diesem Zusammenhang notwendig ist, die Abwärtskompatibilität zu brechen.

Es sieht so aus, als ob für Ihren Vorschlag eine Änderung der Parameter in DjangoAuthorization für Ihren vorhandenen Code erforderlich ist. In diesem Fall ist es meiner Meinung nach einfacher, die Klasse etwas anderes zu nennen.

Betrachten Sie, read_permission='view' Fall, hier könnte genau das sein, was Sie brauchen. Ich verstehe nicht, warum es weniger optimal ist als

class ModifiedDjangoAuthorization(DjangoAuthorization):
    READ_PERM_CODE = 'view'

Wenn Sie andere ändern möchten, überschreiben Sie einfach die Methoden. Die Änderung sollte es wirklich sehr einfach machen.

class ModifiedDjangoAuthorization(DjangoAuthorization):
    def delete_list(self, object_list, bundle):
        return self.perm_list_checks(bundle.request, 'del', object_list)

    def delete_detail(self, object_list, bundle):
        return self.perm_obj_checks(bundle.request, 'del', bundle.obj)

Die Änderung hat Änderungen berücksichtigt und es einfach gemacht. Ich denke nicht, dass es als Init-Parameter gemacht werden sollte.

Ich denke, es war ein Sicherheitsproblem, das Lesen standardmäßig zuzulassen.

Ich stelle die Absicht der ursprünglichen Ausgabe nicht in Frage. Ich möchte nur darauf hinweisen, dass die zusammengeführte Implementierung den bestehenden Code und die Annahmen der Benutzer verletzt, ohne dies zu sagen und ohne eine effiziente Option zum Zurücksetzen.

Es sieht so aus, als ob Ihr Vorschlag erfordert, dass die Parameter an DjangoAuthorization in Ihren vorhandenen Code geändert werden.

Wenn Sie sich meine vorgeschlagene Lösung noch einmal ansehen, befürworte ich, den Menschen Optionen mit einem sicheren und abwärtskompatiblen Standard zu geben. In diesem Fall wären keine Änderungen am Benutzercode erforderlich.

Ich denke, dass es in diesem Zusammenhang notwendig ist, die Abwärtskompatibilität zu brechen.

Ich bin nicht einverstanden. Die Änderung, wie sie derzeit zusammengeführt wird, unterbricht nicht nur die Abwärtskompatibilität, sondern führt auch zu einem viel größeren potenziellen Sicherheitsproblem, da die offensichtliche Möglichkeit (impliziert durch die aktuelle Implementierung) darin besteht, die Änderungsberechtigung allen Benutzern zuzuweisen, denen GET gewährt werden soll.

Ehrlich gesagt kann ich nicht erkennen, wie die Berechtigung change für Leseaktionen die Sicherheit erhöht, da diese Berechtigung gleichzeitig auch PUT ermöglicht. Das Mischen von Berechtigungen für verschiedene Aktionen scheint keine gute Wahl zu sein.

Leider reicht Ihr vorgeschlagenes ModifiedDjangoAuthorization nur dann aus, wenn Sie dem Modell tatsächlich die Berechtigung view hinzufügen, sodass die Abwärtskompatibilität erneut beeinträchtigt wird. Zumindest muss der Code geändert werden - daher brechen wir die Abwärtskompatibilität und zwingen Benutzer, ihre Codebasis zu überarbeiten.

Natürlich ist das Überschreiben immer eine Option, um die spezifischen Anforderungen zu erfüllen. Ich denke jedoch, dass die allgemeine Idee bei tastypie darin besteht, vernünftige und sichere Standardeinstellungen bereitzustellen, für die kein benutzerdefinierter Code hinzugefügt werden muss ...

Kurz gesagt, ich denke, diese Änderung sollte für eine bessere Implementierung rückgängig gemacht werden.

Die change Erlaubnis kommt von Django selbst. Dies ist die Standardeinstellung von Django. So wird die Django Admin-App eingerichtet. Die Option view ist nicht. Ich persönlich habe meine als read .

Ich bin mir nicht sicher, was du meinst, indem du die model überprüfst. Wenn Sie das _meta überprüfen möchten, ist es möglicherweise unvollständig. Wenn Sie meinen, die Datenbank zu treffen, fand ich es unnötig teuer.

Nach meiner Präferenz scheint das, was Sie vorgeschlagen haben, für eine Standardautorisierung "zu viel Magie" zu sein. Nur eine sichere Standardeinstellung zu haben, die leicht überschreibbar ist, scheint genug zu sein. Aber das ist nur meine Meinung.

Die Änderung wurde hier dokumentiert: https://github.com/django-tastypie/django-tastypie/blob/master/docs/release_notes/v0.13.2.rst

Ehrlich gesagt sehe ich nicht, wie die Änderungsberechtigung für Leseaktionen die Sicherheit erhöht, da diese Berechtigung gleichzeitig auch PUT ermöglicht. Das Mischen von Berechtigungen für verschiedene Aktionen scheint keine gute Wahl zu sein.

Wir wissen, dass wenn ein Benutzer etwas ändern kann, er es lesen kann, der Django-Administrator die Dinge so macht.

Diese Version ist sicherer, da der Entwickler gezwungen ist, darüber nachzudenken, was er tut. Wenn der Entwickler, anstatt seine eigene "Lese" -Berechtigung zu erfinden, absichtlich jedem "Änderungs" -Berechtigungen erteilt, wenn er nur "Lese" -Berechtigungen haben sollte, ist dies sein Problem. Ich kann andere Entwickler nicht davon abhalten, absichtlich dumme Dinge zu tun. Ich bin hier, um Tastypie davon abzuhalten, dumme Dinge zu tun. Der Zweck dieser Änderung bestand darin, globale Leseberechtigungen für Ressourcen zu verhindern, die DjangoAuthorization verwendeten, was Entwickler möglicherweise nicht erwarten. Das neue Verhalten entspricht den Erfahrungen der Entwickler im Django-Administrator.

Wenn Sie das alte Verhalten wollen:

  1. Aktualisieren Sie nicht auf 0.13.2.
  2. Oder überschreiben Sie die Methoden read_list and read_detail`.

Wenn Sie der Meinung sind, dass die Dokumentation verbessert werden könnte, können Sie eine PR einreichen.

Ich bedanke mich für ihre Rückmeldung. Vielen Dank für den Link zum Dokument, fair genug, mein schlechtes, weil ich das verpasst habe (bitte beachten Sie, dass das Problem v0.13.4 zugewiesen ist, während sich die Dokumente in v0.13.2 befinden).

Lassen Sie mich noch einige abschließende Bemerkungen zu meinem POV machen:

Wir wissen, dass wenn ein Benutzer etwas ändern kann, er es lesen kann, der Django-Administrator die Dinge so macht.

Der Django-Administrator verwendet die Berechtigung change , da es sich bei der Administratoroberfläche um das Ändern von Objekten handelt. Dort macht es Sinn. Bei der GET-Anforderung für eine REST-API geht es per Definition um Lesen / Anzeigen. Ich würde denken, dass die meisten Entwickler einfach nicht erwarten, dass DjangoAuthorization das Lesen aufgrund einer fehlenden Berechtigung zum Ändern verweigert.

Diese Version ist sicherer, da der Entwickler gezwungen ist, darüber nachzudenken, was er tut.

Eine der von tastypie beworbenen Funktionen ist die Bereitstellung angemessener Standardeinstellungen. Wäre es nicht vernünftig anzunehmen, dass die GET- (per Definition: read) und PUT- (change) Methoden einer API, die in jeder Absicht und in jedem Zweck unterschiedliche Operationen sind, auch unterschiedliche Berechtigungen erfordern?

Ich werde gerne eine PR in Anlehnung an das, was ich geschrieben habe, beitragen, wenn ihr denkt, dass es eine wertvolle Ergänzung ist.

Die Änderungserlaubnis kommt von Django selbst. (...) Die Optionsansicht ist nicht.

In Django steht eine PR aus, um ein view permission hinzuzufügen, weshalb ich view verwendet habe.

Wir werden standardmäßig keine öffentlichen / globalen Lesevorgänge zulassen. Das ist endgültig. Und wir werden nicht versuchen zu erraten, wie Entwickler ihre Berechtigungen eingerichtet haben, wenn es derzeit keine Standardmethode dafür gibt. Wir sind uns nicht einmal sicher, ob wir es "Lesen" oder "Anzeigen" nennen sollen, und ich möchte nicht, dass ein paar Leute hierher kommen und sagen "Ich mache es so" oder "Die neue Django-Version nennt es etwas anderes". .

Wenn Django eine sofort einsatzbereite Lese- / Anzeigeberechtigung unterstützt, wechseln wir dazu. Im Moment müssen Entwickler nur benutzerdefinierten Code schreiben, um die benutzerdefinierte Art und Weise zu handhaben, wie sie mit Berechtigungen umgehen.

Ich weiß, dass dieses Problem geschlossen ist, aber ich möchte mich nur einschalten und sagen, dass diese Änderung mich grundsätzlich daran gehindert hat, ein vorhandenes Projekt auf 0.13.x zu migrieren.

@miraculixx Ich denke, Sie haben völlig

Können Sie dies zumindest bei der Versionierung berücksichtigen, wenn Sie produktionsbrechende Änderungen vornehmen?
Die x.y.z -Versionierung von Tastypie ähnelt sehr dem, was die meisten Leute erwarten , das heißt normalerweise:

Erhöhen Sie bei gegebener Versionsnummer MAJOR.MINOR.PATCH Folgendes:
..
PATCH-Version, wenn Sie abwärtskompatible Fehlerbehebungen vornehmen.

Ich habe gerade eine sehr unangenehme Stunde damit verbracht, dies während einer neuen Produktionsbereitstellung zu verfolgen.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen