RHEL 8 Beta Workshop: Membangun Aplikasi Web Langsung

RHEL 8 Beta menawarkan banyak fitur baru kepada para pengembang, daftar di antaranya mungkin membutuhkan halaman, namun, selalu lebih baik untuk mempelajari hal-hal baru dalam praktiknya, jadi kami sarankan melalui lokakarya untuk benar-benar membuat infrastruktur aplikasi berdasarkan Red Hat Enterprise Linux 8 Beta.



Mari kita gunakan Python, kombinasi Django dan PostgreSQL, bundel yang cukup umum untuk membuat aplikasi, dan konfigurasikan RHEL 8 Beta untuk bekerja dengannya. Kemudian tambahkan beberapa bahan lagi (tidak terklasifikasi).

Lingkungan pengujian akan berubah, karena menarik untuk mempelajari kemampuan otomatisasi, bekerja dengan wadah dan mencoba lingkungan dengan beberapa server. Untuk mulai bekerja dengan proyek baru, Anda dapat mulai dengan membuat prototipe kecil sederhana secara manual - dengan cara ini Anda dapat melihat apa yang sebenarnya perlu terjadi dan bagaimana interaksi dilakukan, dan kemudian beralih ke otomatisasi dan membuat konfigurasi yang lebih kompleks. Hari ini adalah kisah membuat prototipe seperti itu.

Mari kita mulai dengan menggunakan image mesin virtual RHEL 8 Beta VM. Anda dapat menginstal mesin virtual dari awal, atau menggunakan gambar tamu KVM, tersedia dengan berlangganan Beta. Saat menggunakan gambar tamu, Anda harus mengkonfigurasi CD virtual, yang akan berisi metadata dan data pengguna untuk inisialisasi cloud (cloud-init). Anda tidak perlu melakukan sesuatu yang istimewa dengan struktur disk atau paket yang tersedia, konfigurasi apa pun akan dilakukan.

Mari kita lihat keseluruhan proses secara lebih rinci.

Instal Django


Dengan Django versi terbaru, Anda akan membutuhkan lingkungan virtual (virtualenv) dengan Python 3.5 atau lebih baru. Di catatan untuk Beta, Anda dapat melihat bahwa Python 3.6 tersedia, mari kita periksa apakah ini benar:

[cloud-user@8beta1 ~]$ python -bash: python: command not found [cloud-user@8beta1 ~]$ python3 -bash: python3: command not found 

Red Hat secara aktif menggunakan Python sebagai toolkit sistem di RHEL, jadi mengapa Anda mendapatkan hasil ini?

Faktanya adalah bahwa banyak pengembang yang menggunakan Python masih berpikir untuk beralih dari Python 2 ke Python 3, sementara Python 3 sendiri sedang dalam pengembangan aktif, dan semakin banyak versi baru yang terus muncul. Oleh karena itu, untuk memenuhi kebutuhan alat sistem yang stabil, dan pada saat yang sama menawarkan pengguna akses ke berbagai versi Python baru, sistem Python dipindahkan ke paket baru dan memberikan kemampuan untuk menginstal Python 2.7 dan 3.6. Informasi lebih lanjut tentang perubahan dan mengapa ini dilakukan dapat ditemukan di posting blog Langdon White .

Jadi, agar Python berfungsi, Anda hanya perlu menginstal dua paket, sementara python3-pip akan berhenti sebagai dependensi.

 sudo yum install python36 python3-virtualenv 

Mengapa tidak menggunakan panggilan modul langsung, seperti yang disarankan Langdon, dan tidak menginstal pip3? Dengan mengingat otomasi yang akan datang, diketahui bahwa Ansible akan membutuhkan pip yang diinstal, karena modul pip tidak mendukung lingkungan virtual (virtualenvs) dengan custom pip executable.

Dengan juru bahasa python3 yang berfungsi siap membantu Anda, Anda dapat melanjutkan proses instalasi Django dan mendapatkan sistem kerja bersama dengan komponen kami yang lain. Jaringan menyajikan banyak opsi untuk implementasi. Satu versi disajikan di sini, tetapi pengguna dapat menggunakan proses mereka sendiri.

Versi PostgreSQL dan Nginx yang tersedia di RHEL 8 akan diinstal secara default menggunakan Yum.

 sudo yum install nginx postgresql-server 

PostgreSQL akan membutuhkan psycopg2, tetapi hanya perlu tersedia di lingkungan virtualenv, jadi kami akan menginstalnya menggunakan pip3 bersama dengan Django dan Gunicorn. Tetapi pertama-tama kita perlu mengkonfigurasi virtualenv.

Selalu ada banyak perdebatan tentang memilih tempat yang tepat untuk menginstal proyek Django, tetapi ketika ragu, Anda selalu dapat beralih ke Linux Filesystem Hierarchy Standard. Secara khusus, FHS mengatakan bahwa / srv digunakan untuk: "menyimpan data spesifik host - data yang disediakan sistem, misalnya, data dan skrip dari server web, data yang disimpan di server FTP, serta repositori sistem kontrol versi (diperkenalkan pada FHS-2.3 pada 2004). "

Ini hanya kasus kami, jadi kami memasukkan semua yang kami butuhkan ke / srv, yang dimiliki oleh pengguna aplikasi kami (pengguna cloud).

 sudo mkdir /srv/djangoapp sudo chown cloud-user:cloud-user /srv/djangoapp cd /srv/djangoapp virtualenv django source django/bin/activate pip3 install django gunicorn psycopg2 ./django-admin startproject djangoapp /srv/djangoapp 

Menyiapkan PostgreSQL dan Django sangat mudah: buat database, buat pengguna, konfigurasikan izin. Ada satu hal yang perlu diingat ketika mengatur PostgreSQL untuk pertama kalinya - script postgresql-setup, yang diinstal dengan paket server postgresql. Script ini membantu Anda melakukan tugas-tugas dasar yang berkaitan dengan administrasi cluster database, seperti menginisialisasi cluster atau memperbarui proses. Untuk mengkonfigurasi instance baru PostgreSQL pada sistem RHEL, kita perlu menjalankan perintah:

 sudo /usr/bin/postgresql-setup -initdb 

Setelah itu, Anda dapat memulai PostgreSQL menggunakan systemd, membuat database dan mengkonfigurasi proyek di Django. Ingatlah untuk memulai kembali PostgreSQL setelah membuat perubahan pada file konfigurasi otentikasi klien (biasanya pg_hba.conf) untuk mengonfigurasi penyimpanan kata sandi untuk pengguna aplikasi. Jika Anda mengalami kesulitan lain, pastikan untuk mengubah pengaturan IPv4 dan IPv6 di file pg_hba.conf.

 systemctl enable -now postgresql sudo -u postgres psql postgres=# create database djangoapp; postgres=# create user djangouser with password 'qwer4321'; postgres=# alter role djangouser set client_encoding to 'utf8'; postgres=# alter role djangouser set default_transaction_isolation to 'read committed'; postgres=# alter role djangouser set timezone to 'utc'; postgres=# grant all on DATABASE djangoapp to djangouser; postgres=# \q 

Dalam file /var/lib/pgsql/data/pg_hba.conf:

 # IPv4 local connections: host all all 0.0.0.0/0 md5 # IPv6 local connections: host all all ::1/128 md5 

Dalam file /srv/djangoapp/settings.py:

 # Database DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql_psycopg2', 'NAME': '{{ db_name }}', 'USER': '{{ db_user }}', 'PASSWORD': '{{ db_password }}', 'HOST': '{{ db_host }}', } } 

Setelah Anda mengkonfigurasi file settings.py di proyek dan mengkonfigurasi konfigurasi database, Anda dapat memulai server pengembangan untuk memastikan bahwa semuanya berfungsi. Setelah memulai server pengembangan, senang membuat pengguna admin untuk menguji koneksi ke database.

 ./manage.py runserver 0.0.0.0:8000 ./manage.py createsuperuser 

WSGI? Wai


Server pengembangan berguna untuk pengujian, tetapi untuk menjalankan aplikasi, Anda harus mengonfigurasi server dan proksi yang sesuai untuk Web Server Gateway Interface (WSGI). Ada beberapa bundel umum, misalnya, Apache HTTPD dengan uWSGI atau Nginx dengan Gunicorn.

Tujuan dari Antarmuka Gateway Server Web adalah untuk mengarahkan permintaan dari server web ke kerangka kerja web Python. WSGI adalah semacam warisan dari masa lalu yang mengerikan ketika mekanisme CGI digunakan, dan hari ini WSGI sebenarnya adalah standar, terlepas dari server web atau kerangka kerja Python yang digunakan. Tetapi meskipun distribusinya luas, masih ada banyak nuansa ketika bekerja dengan kerangka kerja ini, dan banyak pilihan. Dalam hal ini, kami akan mencoba untuk membangun interaksi antara Gunicorn dan Nginx melalui soket.

Karena kedua komponen ini diinstal pada server yang sama, kami akan mencoba menggunakan soket UNIX alih-alih soket jaringan. Karena komunikasi memerlukan soket, mari kita coba satu langkah lagi dan konfigurasikan aktivasi soket untuk Gunicorn melalui systemd.

Proses membuat layanan soket diaktifkan cukup sederhana. Pertama, file unit dibuat yang berisi arahan ListenStream yang menunjuk ke titik di mana soket UNIX akan dibuat, kemudian file unit untuk layanan, di mana arahan Membutuhkan akan menunjuk ke file unit soket. Kemudian, dalam file unit layanan, tetap hanya untuk memanggil Gunicorn dari lingkungan virtual dan membuat WSGI yang mengikat untuk soket UNIX dan aplikasi Django.

Berikut adalah beberapa contoh file unit yang dapat diambil sebagai dasar. Pertama, konfigurasikan soket.

 [Unit] Description=Gunicorn WSGI socket [Socket] ListenStream=/run/gunicorn.sock [Install] WantedBy=sockets.target 

Sekarang Anda perlu mengkonfigurasi daemon Gunicorn.

 [Unit] Description=Gunicorn daemon Requires=gunicorn.socket After=network.target [Service] User=cloud-user Group=cloud-user WorkingDirectory=/srv/djangoapp ExecStart=/srv/djangoapp/django/bin/gunicorn \ —access-logfile - \ —workers 3 \ —bind unix:gunicorn.sock djangoapp.wsgi [Install] WantedBy=multi-user.target 

Untuk Nginx, cukup buat file konfigurasi proxy dan buat direktori untuk menyimpan konten statis jika Anda menggunakannya. Dalam RHEL, file konfigurasi Nginx adalah /etc/nginx/conf.d. Anda dapat menyalin contoh berikut di sana ke file /etc/nginx/conf.d/default.conf, dan memulai layanan. Pastikan untuk menentukan nama server sesuai dengan nama host Anda.

 server { listen 80; server_name 8beta1.example.com; location = /favicon.ico { access_log off; log_not_found off; } location /static/ { root /srv/djangoapp; } location / { proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_pass http://unix:/run/gunicorn.sock; } } 

Jalankan soket Gunicorn dan Nginx menggunakan systemd, dan Anda dapat memulai pengujian.

Gerbang Buruk Salah?


Jika Anda memasukkan alamat di browser, maka kemungkinan besar Anda akan mendapatkan kesalahan 502 Gateway Buruk. Hal ini dapat disebabkan oleh izin yang tidak dikonfigurasi dengan benar untuk soket UNIX, atau karena masalah yang lebih kompleks terkait dengan kontrol akses di SELinux.

Di log kesalahan nginx, Anda bisa melihat garis seperti ini:

 2018/12/18 15:38:03 [crit] 12734#0: *3 connect() to unix:/run/gunicorn.sock failed (13: Permission denied) while connecting to upstream, client: 192.168.122.1, server: 8beta1.example.com, request: "GET / HTTP/1.1", upstream: "http://unix:/run/gunicorn.sock:/", host: "8beta1.example.com" 

Jika kami menguji Gunicorn secara langsung, kami mendapatkan jawaban kosong.

 curl —unix-socket /run/gunicorn.sock 8beta1.example.com 

Mari kita lihat mengapa ini terjadi. Jika Anda membuka log, maka kemungkinan besar kita akan melihat bahwa masalahnya terkait dengan SELinux. Karena kita menjalankan daemon yang belum kita buat kebijakannya sendiri, itu ditandai sebagai init_t. Mari kita uji teori ini dalam praktik.

 sudo setenforce 0 

Semua ini dapat menyebabkan kritik dan air mata berdarah, tetapi ini hanya debugging prototipe. Kami mematikan cek hanya untuk memastikan bahwa ini masalahnya, setelah itu kami akan mengembalikan semuanya ke tempat mereka.

Dengan menyegarkan halaman di browser atau dengan memulai kembali perintah curl kami, Anda dapat melihat halaman uji Django.

Jadi, memastikan semuanya berfungsi, dan tidak ada lagi masalah izin, kami mengaktifkan kembali SELinux.

 sudo setenforce 1 

Tidak akan ada pembicaraan tentang audit2allow dan pembuatan kebijakan berdasarkan peringatan menggunakan sepolgen, karena saat ini tidak ada aplikasi Django nyata, tidak ada peta lengkap tentang apa yang mungkin ingin diakses oleh Gunicorn, dan akses apa yang harus ditolak. Oleh karena itu, perlu untuk menjaga SELinux untuk melindungi sistem, dan pada saat yang sama memungkinkan aplikasi untuk memulai dan meninggalkan pesan dalam log audit sehingga Anda kemudian dapat membuat kebijakan nyata berdasarkan pada mereka.

Menentukan Domain yang Diizinkan


Tidak semua orang pernah mendengar tentang domain yang diizinkan di SELinux, tetapi tidak ada yang baru di dalamnya. Banyak yang bahkan bekerja dengan mereka, tanpa menyadarinya sendiri. Ketika kebijakan dibuat berdasarkan pesan audit, kebijakan yang dibuat adalah domain yang diizinkan. Mari kita coba membuat kebijakan permisif paling sederhana.

Untuk membuat domain diizinkan khusus untuk Gunicorn, Anda memerlukan kebijakan tertentu, dan Anda juga harus menandai file yang sesuai. Selain itu, diperlukan alat untuk menyusun kebijakan baru.

 sudo yum install selinux-policy-devel 

Mekanisme domain yang diselesaikan adalah alat yang hebat untuk mengidentifikasi masalah, terutama ketika menyangkut aplikasi khusus atau aplikasi yang datang tanpa kebijakan yang telah dibuat. Dalam hal ini, kebijakan domain yang diizinkan untuk Gunicorn akan sesederhana mungkin - nyatakan tipe utama (gunicorn_t), nyatakan tipe yang akan kita gunakan untuk menandai beberapa file yang dapat dieksekusi (gunicorn_exec_t), dan kemudian konfigurasikan transisi untuk sistem untuk menandai proses yang berjalan dengan benar. . Baris terakhir menetapkan kebijakan sebagai diaktifkan secara default pada saat pemuatannya.

gunicorn.te:
 policy_module(gunicorn, 1.0) type gunicorn_t; type gunicorn_exec_t; init_daemon_domain(gunicorn_t, gunicorn_exec_t) permissive gunicorn_t; 

Anda dapat mengkompilasi file kebijakan ini dan menambahkannya ke sistem.

 make -f /usr/share/selinux/devel/Makefile sudo semodule -i gunicorn.pp sudo semanage permissive -a gunicorn_t sudo semodule -l | grep permissive 

Mari kita periksa apakah SELinux memblokir hal lain selain apa yang diakses daemon tidak dikenal kita.

 sudo ausearch -m AVC type=AVC msg=audit(1545315977.237:1273): avc: denied { write } for pid=19400 comm="nginx" name="gunicorn.sock" dev="tmpfs" ino=52977 scontext=system_u:system_r:httpd_t:s0 tcontext=system_u:object_r:var_run_t:s0 tclass=sock_file permissive=0 

SELinux mencegah Nginx dari menulis data ke soket UNIX yang digunakan oleh Gunicorn. Biasanya, dalam kasus seperti itu, politisi mulai berubah, tetapi ada tugas lain di depan. Anda juga dapat mengubah pengaturan domain dengan mengubahnya dari domain pembatasan menjadi domain izin. Sekarang pindahkan httpd_t ke domain izin. Ini akan memberi Nginx akses yang diperlukan, dan kami akan dapat melanjutkan pekerjaan lebih lanjut tentang debugging.

 sudo semanage permissive -a httpd_t 

Jadi, ketika dimungkinkan untuk menjaga perlindungan SELinux (pada kenyataannya, Anda tidak boleh meninggalkan proyek dengan SELinux dalam mode pembatasan) dan domain izin dimuat, Anda perlu mencari tahu apa yang sebenarnya perlu ditandai sebagai gunicorn_exec_t sehingga semuanya berfungsi kembali seperti yang diharapkan. Mari kita coba mengakses situs web untuk melihat pesan baru tentang batasan akses.

 sudo ausearch -m AVC -c gunicorn 

Anda dapat melihat banyak pesan yang mengandung 'comm = "gunicorn"' yang melakukan berbagai tindakan pada file di / srv / djangoapp, jadi jelas ini hanya salah satu perintah yang harus Anda tandai.

Namun di samping itu, pesan seperti ini muncul:

 type=AVC msg=audit(1545320700.070:1542): avc: denied { execute } for pid=20704 comm="(gunicorn)" name="python3.6" dev="vda3" ino=8515706 scontext=system_u:system_r:init_t:s0 tcontext=unconfined_u:object_r:var_t:s0 tclass=file permissive=0 

Jika Anda melihat status layanan gunicorn atau menjalankan perintah ps, maka tidak ada proses yang berjalan akan muncul. Gunicorn tampaknya mencoba mengakses juru bahasa Python di lingkungan virtualenv kami, mungkin untuk menjalankan skrip yang berfungsi (pekerja). Jadi sekarang mari kita tandai kedua executable ini dan lihat apakah kita dapat membuka halaman uji Django kami.

 chcon -t gunicorn_exec_t /srv/djangoapp/django/bin/gunicorn /srv/djangoapp/django/bin/python3.6 

Anda harus memulai kembali layanan gunicorn sehingga Anda dapat memilih label baru. Anda dapat memulai kembali dengan segera atau menghentikan layanan dan membiarkan soket memulai ketika Anda membuka situs di browser. Pastikan proses mendapatkan label yang benar menggunakan ps.

 ps -efZ | grep gunicorn 

Ingatlah untuk membuat kebijakan SELinux normal nanti!

Jika Anda melihat pesan AVC sekarang, pesan terakhir berisi permissive = 1 untuk semua yang berhubungan dengan aplikasi, dan permissive = 0 untuk seluruh sistem. Jika Anda memahami jenis akses yang dibutuhkan aplikasi nyata, Anda dapat dengan cepat menemukan cara terbaik untuk menyelesaikan masalah tersebut. Tetapi sampai saat itu, lebih baik bahwa sistem dilindungi, dan untuk mendapatkan audit yang jelas dan dapat digunakan oleh proyek Django.

 sudo ausearch -m AVC 

Ternyata!


Proyek Django yang berfungsi dengan tampilan depan pada Nginx dan Gunicorn WSGI muncul. Kami mengkonfigurasi Python 3 dan PostgreSQL 10 dari repositori RHEL 8 Beta. Sekarang Anda dapat melanjutkan dan membuat (atau hanya menggunakan) aplikasi Django atau menjelajahi alat lain yang tersedia di RHEL 8 Beta untuk mengotomatiskan proses tuning, meningkatkan kinerja, atau bahkan membuat wadah konfigurasi ini.

Source: https://habr.com/ru/post/id447540/


All Articles