[ English | Indonesia | Deutsch | 日本語 ]
Anpassen der Middleware für die Objektspeicherung (Swift)¶
OpenStack Object Storage, bekannt als swift beim Lesen des Codes, basiert auf dem Python Paste Framework. Die beste Einführung in seine Architektur ist auf Read The Docs. Aufgrund der schnellen Nutzung dieses Frameworks durch das Projekt können Sie einem Projekt Funktionen hinzufügen, indem Sie benutzerdefinierten Code in die Pipeline eines Projekts einfügen, ohne den Kerncode ändern zu müssen.
Stellen Sie sich ein Szenario vor, in dem Sie öffentlichen Zugriff auf einen Ihrer Container haben, aber was Sie wirklich wollen, ist, den Zugriff darauf auf eine Reihe von IPs basierend auf einer Whitelist zu beschränken. In diesem Beispiel erstellen wir eine Middleware für Swift, die den Zugriff auf einen Container nur von einer Reihe von IP-Adressen aus ermöglicht, wie sie durch die Metadatenelemente des Containers bestimmt werden. Nur die IP-Adressen, die Sie explizit mit den Metadaten des Containers auf die Whitelist setzen, können auf den Container zugreifen.
Warnung
Dieses Beispiel dient nur zur Veranschaulichung. Es sollte nicht als Container-IP-Whitelist-Lösung ohne Weiterentwicklung und umfangreiche Sicherheitstests verwendet werden.
Wenn Sie der Bildschirmsitzung beitreten, die stack.sh
mit screen -r stack
beginnt, sehen Sie einen Bildschirm für jeden laufenden Dienst, der einige oder mehrere sein kann, je nachdem, wie viele Dienste Sie DevStack zum Ausführen konfiguriert haben.
Das Sternchen * zeigt an, welches Bildschirmfenster Sie gerade betrachten. Dieses Beispiel zeigt, dass wir das Key (für Keystone) Bildschirmfenster betrachten:
0$ shell 1$ key* 2$ horizon 3$ s-proxy 4$ s-object 5$ s-container 6$ s-account
Die Bildschirmfenster haben folgenden Zweck:
shell
Eine Shell, in der Sie etwas Arbeit erledigen können
key*
Der Keystone-Service
horizon
Die Webanwendung des Horizon Dashboards
s-{name}
Die swift Dienste
Um die Middleware zu erstellen und über die Konfiguration Einfügen einzubinden:
Der gesamte Code für OpenStack lebt in /opt/stack
. Gehen Sie in das Swift-Verzeichnis im shell
Bildschirm und bearbeiten Sie Ihr Middleware-Modul.
Wechseln Sie in das Verzeichnis, in dem der Objektspeicher installiert ist:
$ cd /opt/stack/swift
Erstellen Sie die
ip_whitelist.py
Python-Quelltextdatei:$ vim swift/common/middleware/ip_whitelist.py
Kopieren Sie den Code wie unten gezeigt in
ip_whitelist.py
. Der folgende Code ist ein Middleware-Beispiel, das den Zugriff auf einen Container basierend auf der IP-Adresse einschränkt, wie am Anfang des Abschnitts erläutert. Die Middleware leitet die Anforderung an eine andere Anwendung weiter. In diesem Beispiel wird die swift „swob“-Bibliothek verwendet, um Web Server Gateway Interface (WSGI)-Anfragen und -Antworten in Objekte zu wickeln, mit denen swift interagieren kann. Wenn Sie fertig sind, speichern und schließen Sie die Datei.# vim: tabstop=4 shiftwidth=4 softtabstop=4 # Copyright (c) 2014 OpenStack Foundation # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import socket from swift.common.utils import get_logger from swift.proxy.controllers.base import get_container_info from swift.common.swob import Request, Response class IPWhitelistMiddleware(object): """ IP Whitelist Middleware Middleware that allows access to a container from only a set of IP addresses as determined by the container's metadata items that start with the prefix 'allow'. E.G. allow-dev=192.168.0.20 """ def __init__(self, app, conf, logger=None): self.app = app if logger: self.logger = logger else: self.logger = get_logger(conf, log_route='ip_whitelist') self.deny_message = conf.get('deny_message', "IP Denied") self.local_ip = socket.gethostbyname(socket.gethostname()) def __call__(self, env, start_response): """ WSGI entry point. Wraps env in swob.Request object and passes it down. :param env: WSGI environment dictionary :param start_response: WSGI callable """ req = Request(env) try: version, account, container, obj = req.split_path(1, 4, True) except ValueError: return self.app(env, start_response) container_info = get_container_info( req.environ, self.app, swift_source='IPWhitelistMiddleware') remote_ip = env['REMOTE_ADDR'] self.logger.debug("Remote IP: %(remote_ip)s", {'remote_ip': remote_ip}) meta = container_info['meta'] allow = {k:v for k,v in meta.iteritems() if k.startswith('allow')} allow_ips = set(allow.values()) allow_ips.add(self.local_ip) self.logger.debug("Allow IPs: %(allow_ips)s", {'allow_ips': allow_ips}) if remote_ip in allow_ips: return self.app(env, start_response) else: self.logger.debug( "IP %(remote_ip)s denied access to Account=%(account)s " "Container=%(container)s. Not in %(allow_ips)s", locals()) return Response( status=403, body=self.deny_message, request=req)(env, start_response) def filter_factory(global_conf, **local_conf): """ paste.deploy app factory for creating WSGI proxy apps. """ conf = global_conf.copy() conf.update(local_conf) def ip_whitelist(app): return IPWhitelistMiddleware(app, conf) return ip_whitelist
Es gibt viele nützliche Informationen in
env
undconf`
, mit denen Sie entscheiden können, was mit der Anfrage geschehen soll. Um mehr darüber zu erfahren, welche Eigenschaften verfügbar sind, können Sie die folgende Log-Anweisung in die Methode__init__
einfügen:self.logger.debug("conf = %(conf)s", locals())
und die folgende Log-Anweisung in das
__call__
Verfahren:self.logger.debug("env = %(env)s", locals())
Um diese Middleware in die swift Paste Pipeline einzubinden, bearbeiten Sie eine Konfigurationsdatei,
/etc/swift/proxy-server.conf
:$ vim /etc/swift/proxy-server.conf
Suchen Sie den Abschnitt
[filter:ratelimit]
in/etc/swift/proxy-server.conf
, und kopieren Sie ihn danach in den folgenden Konfigurationsabschnitt:[filter:ip_whitelist] paste.filter_factory = swift.common.middleware.ip_whitelist:filter_factory # You can override the default log routing for this filter here: # set log_name = ratelimit # set log_facility = LOG_LOCAL0 # set log_level = INFO # set log_headers = False # set log_address = /dev/log deny_message = You shall not pass!
Suchen Sie den Abschnitt
[pipeline:main]
in/etc/swift/proxy-server.conf
, und fügen Sieip_whitelist
nach Tarifbeschränkung der Liste so hinzu. Wenn Sie fertig sind, speichern und schließen Sie die Datei:[pipeline:main] pipeline = catch_errors gatekeeper healthcheck proxy-logging cache bulk tempurl ratelimit ip_whitelist ...
Starten Sie den Dienst
swift proxy
neu, um Ihre Middleware schnell zu nutzen. Wechseln Sie zunächst zum Bildschirm „swift-proxy“:Drücken Sie Strg+A gefolgt von 3.
Drücken Sie Strg+C, um den Dienst zu beenden.
Drücken Sie Pfeil nach oben, um den letzten Befehl aufzurufen.
Drücken Sie die Eingabetaste, um es auszuführen.
Testen Sie Ihre Middleware mit der
swift
CLI. Beginnen Sie, indem Sie zum Shell-Bildschirm wechseln und beenden Sie ihn, indem Sie zumswift-proxy
Bildschirm zurückkehren, um die Protokollausgabe zu überprüfen:Drücken Sie Strg+A gefolgt von 0.
Stellen Sie sicher, dass Sie sich im Verzeichnis
devstack`
befinden:$ cd /root/devstack
Quelle openrc, um Ihre Umgebungsvariablen für die CLI einzurichten:
$ . openrc
Erstellen Sie einen Container mit dem Namen
Middleware-Test
:$ swift post middleware-test
Drücken Sie Ctrl+A gefolgt von 3**, um die Protokollausgabe zu überprüfen.
Unter den Protokollanweisungen sehen Sie die Zeilen:
proxy-server Remote IP: my.instance.ip.address (txn: ...) proxy-server Allow IPs: set(['my.instance.ip.address']) (txn: ...)
Diese beiden Anweisungen werden von unserer Middleware erzeugt und zeigen, dass die Anfrage von unserer DevStack-Instanz gesendet wurde und erlaubt war.
Testen Sie die Middleware von außerhalb von DevStack auf einem entfernten Computer, der Zugriff auf Ihre DevStack-Instanz hat:
Installieren Sie die Clients
keystone
undswift
auf Ihrem lokalen Rechner:# pip install python-keystoneclient python-swiftclient
Versuchen Sie, die Objekte im Container
Middleware-Test
aufzulisten:$ swift --os-auth-url=http://my.instance.ip.address:5000/v2.0/ \ --os-region-name=RegionOne --os-username=demo:demo \ --os-password=devstack list middleware-test Container GET failed: http://my.instance.ip.address:8080/v1/AUTH_.../ middleware-test?format=json 403 Forbidden You shall not pass!
Drücken Sie Ctrl+A gefolgt von 3**, um die Protokollausgabe zu überprüfen. Betrachten Sie die Swift-Log-Anweisungen noch einmal, und unter den Log-Anweisungen sehen Sie die Zeilen:
proxy-server Authorizing from an overriding middleware (i.e: tempurl) (txn: ...) proxy-server ... IPWhitelistMiddleware proxy-server Remote IP: my.local.ip.address (txn: ...) proxy-server Allow IPs: set(['my.instance.ip.address']) (txn: ...) proxy-server IP my.local.ip.address denied access to Account=AUTH_... \ Container=None. Not in set(['my.instance.ip.address']) (txn: ...)
Hier sehen wir, dass die Anfrage abgelehnt wurde, weil die entfernte IP-Adresse nicht im Satz der erlaubten IPs enthalten war.
Fügen Sie in Ihrer DevStack-Instanz auf dem Shell-Bildschirm einige Metadaten zu Ihrem Container hinzu, um die Anforderung von der entfernten Maschine zu ermöglichen:
Drücken Sie Strg+A gefolgt von 0.
Fügen Sie dem Container Metadaten hinzu, um die IP zu ermöglichen:
$ swift post --meta allow-dev:my.local.ip.address middleware-test
Versuchen Sie nun den Befehl aus Schritt 10 erneut und er ist erfolgreich. Es gibt keine Objekte im Container, also gibt es nichts aufzulisten, aber es gibt auch keinen Fehler zu melden.
Warnung
Funktionstests wie dieser sind kein Ersatz für richtige Geräte- und Integrationstests, aber sie dienen dazu, Ihnen den Einstieg zu erleichtern.
Sie können ein ähnliches Muster in anderen Projekten verfolgen, die das Python Paste Framework verwenden. Erstellen Sie einfach ein Middleware-Modul und schließen Sie es über die Konfiguration an. Die Middleware läuft im Rahmen der Projektpipeline nacheinander und kann bei Bedarf weitere Dienste aufrufen. Es wird kein Projektkern-Code berührt. Suchen Sie nach einem Pipeline
Wert in den Konfigurationsdateien des Projekts conf
oder ini
in /etc/<project>`, um Projekte zu identifizieren, die Paste verwenden.
Wenn Ihre Middleware fertig ist, empfehlen wir Ihnen, sie Open Source zu verwenden und die Community auf der OpenStack-Mailingliste darüber zu informieren. Vielleicht benötigen andere die gleiche Funktionalität. Sie können Ihren Code verwenden, Feedback geben und möglicherweise einen Beitrag leisten. Wenn es genügend Unterstützung dafür gibt, können Sie vielleicht vorschlagen, dass sie dem offiziellen Swift Middleware hinzugefügt wird.