[ English | Indonesia | Deutsch | 日本語 ]
Menyesuaikan Object Storage (Swift) Middleware¶
OpenStack Object Storage, dikenal sebagai swift ketika membaca kode, didasarkan pada Python Paste framework. Pengantar terbaik untuk arsitekturnya aktif di Read The Docs. Karena penggunaan framework proyek swift ini, Anda dapat menambahkan fitur ke proyek dengan menempatkan beberapa kode khusus dalam pipa proyek tanpa harus mengubah kode core apa pun.
Bayangkan sebuah skenario di mana Anda memiliki akses publik ke salah satu kontainer Anda, tetapi yang Anda inginkan adalah membatasi akses ke satu set IP berdasarkan daftar putih. Dalam contoh ini, kami akan membuat sepotong middleware untuk swift yang memungkinkan akses ke sebuah kontainer dari hanya satu set alamat IP, seperti yang ditentukan oleh item metadata dari kontainer. Hanya alamat IP yang Anda daftar putih secara eksplisit menggunakan metadata kontainer yang akan dapat mengakses kontainer.
Peringatan
Contoh ini hanya untuk tujuan ilustrasi. Seharusnya tidak digunakan sebagai solusi daftar putih IP kontainer tanpa pengembangan lebih lanjut dan pengujian keamanan yang luas.
Ketika Anda bergabung dengan sesi layar yang stack.sh
dimulai dengan screen -r stack
, Anda melihat layar untuk setiap layanan yang berjalan, yang bisa beberapa atau beberapa, tergantung pada berapa banyak layanan yang Anda konfigurasi DevStack untuk berlari.
Tanda bintang * menunjukkan jendela layar yang Anda lihat. Contoh ini menunjukkan kita sedang melihat jendela key kunci (untuk keystone):
0$ shell 1$ key* 2$ horizon 3$ s-proxy 4$ s-object 5$ s-container 6$ s-account
Tujuan dari layar windows adalah sebagai berikut:
shell
Shell tempat Anda bisa menyelesaikan pekerjaan
key*
Layanan keystone
horizon
Aplikasi web dasbor horizon
s-{name}
Layanan swift
To create the middleware and plug it in through Paste configuration:
Semua kode untuk OpenStack hidup di /opt/stack
. Buka direktori swift di layar shell
dan edit modul middleware Anda.
Ubah ke direktori tempat Object Storage diinstal:
$ cd /opt/stack/swift
Buat file kode sumber Python
ip_whitelist.py
:$ vim swift/common/middleware/ip_whitelist.py
Salin kode seperti yang ditunjukkan di bawah ini ke
ip_whitelist.py
. Kode berikut adalah contoh middleware yang membatasi akses ke sebuah kontainer berdasarkan alamat IP seperti yang dijelaskan di awal bagian. Middleware meneruskan permintaan ke aplikasi lain. Contoh ini menggunakan pustaka "swob" swift untuk membungkus permintaan dan respons Web Server Gateway Interface (WSGI) menjadi objek untuk berinteraksi dengan swift. Setelah selesai, simpan dan tutup file.# 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
Ada banyak informasi berguna dalam
env
danconf
yang dapat Anda gunakan untuk memutuskan apa yang harus dilakukan dengan permintaan tersebut. Untuk mengetahui lebih lanjut tentang properti apa yang tersedia, Anda dapat memasukkan pernyataan log berikut ke dalam metode__init__
:self.logger.debug("conf = %(conf)s", locals())
dan pernyataan log berikut ke dalam metode
__call__
:self.logger.debug("env = %(env)s", locals())
Untuk menghubungkan middleware ini ke swift Paste pipeline, Anda mengedit satu file konfigurasi,
/etc/swift/proxy-server.conf
:$ vim /etc/swift/proxy-server.conf
Temukan bagian
[filter: ratelimit] `` di ``/etc/swift/proxy-server.conf
, dan salin di bagian konfigurasi berikut setelahnya:[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!
Temukan bagian
[pipeline: main] `` di ``/etc/swift/proxy-server.conf
, dan tambahkanip_whitelist
setelah ratelimit ke daftar seperti itu. Setelah selesai, simpan dan tutup file:[pipeline:main] pipeline = catch_errors gatekeeper healthcheck proxy-logging cache bulk tempurl ratelimit ip_whitelist ...
Mulai ulang layanan
swift proxy
untuk menjadikan swift menggunakan middleware Anda. Mulailah dengan beralih ke layarswift-proxy
:Tekan Ctrl+A diikuti oleh 3.
Tekan Ctrl+C untuk membunuh layanan.
Tekan Up Arrow untuk memunculkan perintah terakhir.
Tekan Enter untuk menjalankannya.
Uji middleware Anda dengan CLI
swift
. Mulailah dengan beralih ke layar shell dan selesai dengan beralih kembali ke layarswift-proxy
untuk memeriksa output log:Teken Ctrl+A diikuti oleh 0.
Pastikan Anda berada di direktori
devstack
:$ cd /root/devstack
Sumber openrc untuk mengatur variabel lingkungan Anda untuk CLI:
$ . openrc
Buat kontainer yang disebut
middleware-test
:$ swift post middleware-test
Tekan Ctrl+A diikuti oleh 3 untuk memeriksa output log.
Di antara pernyataan log Anda akan melihat baris:
proxy-server Remote IP: my.instance.ip.address (txn: ...) proxy-server Allow IPs: set(['my.instance.ip.address']) (txn: ...)
Kedua pernyataan ini diproduksi oleh middleware kami dan menunjukkan bahwa permintaan dikirim dari instance DevStack kami dan diizinkan.
Uji middleware dari luar DevStack pada mesin jarak jauh yang memiliki akses ke instance DevStack Anda:
Instal klien
keystone
danswift
di mesin lokal Anda:# pip install python-keystoneclient python-swiftclient
Cobalah untuk membuat daftar objek dalam kontainer
middleware-test
:$ 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!
Tekan Ctrl+A diikuti oleh 3 untuk memeriksa output log. Lihatlah pernyataan log swift lagi, dan di antara laporan log, Anda akan melihat baris:
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: ...)
Di sini kita dapat melihat bahwa permintaan ditolak karena alamat IP jarak jauh tidak dalam set IP yang diizinkan.
Kembali ke instance DevStack Anda pada layar shell, tambahkan beberapa metadata ke kontainer Anda untuk memungkinkan permintaan dari mesin jarak jauh:
Tekan Ctrl+A diikuti oleh 0.
Tambahkan metadata ke kontainer untuk memungkinkan IP:
$ swift post --meta allow-dev:my.local.ip.address middleware-test
Sekarang coba perintah dari Langkah 10 lagi dan berhasil. Tidak ada benda di dalam kontainer, jadi tidak ada yang perlu didaftar; Namun, tidak ada kesalahan untuk dilaporkan.
Peringatan
Pengujian fungsional seperti ini bukan pengganti untuk pengujian unit dan integrasi yang tepat, tetapi berfungsi untuk membantu Anda memulai.
Anda bisa mengikuti pola serupa di proyek lain yang menggunakan framework Python Paste. Cukup buat modul middleware dan pasang melalui konfigurasi. Middleware berjalan secara berurutan sebagai bagian dari project's pipeline itu dan dapat memanggil layanan lain yang diperlukan. Tidak ada kode inti proyek yang disentuh. Cari nilai pipeline
di file konfigurasi conf
atau ini
proyek di /etc/<project>
untuk mengidentifikasi proyek yang menggunakan Paste.
Ketika middleware Anda selesai, kami menganjurkan Anda untuk membuka sumbernya dan memberi tahu komunitas di milis OpenStack. Mungkin orang lain membutuhkan fungsi yang sama. Mereka dapat menggunakan kode Anda, memberikan umpan balik, dan mungkin berkontribusi. Jika ada cukup dukungan untuk itu, mungkin Anda dapat mengusulkan agar itu ditambahkan ke swift resmi middleware<https://opendev.org/openstack/swift/src/branch/master/swift/common/middleware> _.