RHEL 8 Beta nudi programerima mnoge nove funkcije, čije bi nabrajanje moglo potrajati stranicama, ali učenje novih stvari je uvijek bolje kroz praksu, pa u nastavku nudimo praktičan vodič za kreiranje stvarne aplikacijske infrastrukture zasnovane na Red Hat Enterpriseu. Linux 8 Beta.

Uzmimo Python, popularni programski jezik među programerima, kao osnovu, kombinaciju Djanga i PostgreSQL-a, prilično uobičajenu kombinaciju za kreiranje aplikacija, i konfigurišite RHEL 8 Beta da radi sa njima. Zatim ćemo dodati još par (neklasifikovanih) sastojaka.
Testno okruženje će se promeniti, jer je zanimljivo istražiti mogućnosti automatizacije, rada sa kontejnerima i isprobavanje okruženja sa više servera. Da biste započeli s novim projektom, možete započeti kreiranjem malog, jednostavnog prototipa ručno kako biste mogli vidjeti što se točno treba dogoditi i kako to djeluje, a zatim preći na automatizaciju i kreiranje složenijih konfiguracija. Danas govorimo o stvaranju takvog prototipa.
Počnimo sa postavljanjem RHEL 8 Beta VM slike. Možete instalirati virtuelnu mašinu od nule ili koristiti KVM sliku gosta koja je dostupna uz vašu Beta pretplatu. Kada koristite sliku gosta, morat ćete konfigurirati virtualni CD koji će sadržavati metapodatke i korisničke podatke za inicijalizaciju oblaka (cloud-init). Ne morate raditi ništa posebno sa strukturom diska ili dostupnim paketima; bilo koja konfiguracija će učiniti.
Pogledajmo detaljnije ceo proces.
Instaliranje Djanga
Uz najnoviju verziju Djanga, trebat će vam virtualno okruženje (virtualenv) sa Python-om 3.5 ili novijim. U beta beleškama možete videti da je Python 3.6 dostupan, hajde da proverimo da li je to zaista slučaj:
[cloud-user@8beta1 ~]$ python
-bash: python: command not found
[cloud-user@8beta1 ~]$ python3
-bash: python3: command not found
Red Hat aktivno koristi Python kao sistemski alat u RHEL-u, pa zašto je to rezultat?
Činjenica je da mnogi programeri Pythona još uvijek razmišljaju o prijelazu s Pythona 2 na Python 2, dok je sam Python 3 u aktivnom razvoju, a sve više i više novih verzija se stalno pojavljuje. Stoga, kako bi se zadovoljila potreba za stabilnim sistemskim alatima, dok korisnicima nudi pristup raznim novim verzijama Pythona, sistemski Python je premješten u novi paket i omogućio je instalaciju i Python 2.7 i 3.6. Više informacija o promjenama i zašto su napravljene možete pronaći u publikaciji u (Langdon Vajt).
Dakle, da bi Python mogao da radi, potrebno je da instalirate samo dva paketa, sa uključenim python3-pip kao zavisnošću.
sudo yum install python36 python3-virtualenv
Zašto ne koristite direktne pozive modula kao što Langdon predlaže i instalirate pip3? Imajući u vidu nadolazeću automatizaciju, poznato je da će Ansible zahtijevati instaliran pip za pokretanje, budući da pip modul ne podržava virtualenvs sa prilagođenim izvršnim pip-om.
Sa ispravnim python3 interpretatorom koji vam je na raspolaganju, možete nastaviti sa procesom instalacije Djanga i imati radni sistem zajedno sa našim ostalim komponentama. Na Internetu su dostupne mnoge mogućnosti implementacije. Ovdje je predstavljena jedna verzija, ali korisnici mogu koristiti svoje vlastite procese.
Instalirat ćemo PostgreSQL i Nginx verzije dostupne u RHEL 8 po defaultu koristeći Yum.
sudo yum install nginx postgresql-server
PostgreSQL će zahtijevati psycopg2, ali mora biti dostupan samo u virtualenv okruženju, tako da ćemo ga instalirati koristeći pip3 zajedno sa Djangom i Gunicorn. Ali prvo moramo postaviti virtualenv.
Uvijek postoji mnogo debate o pravom mjestu za instaliranje Django projekata, ali kada ste u nedoumici, uvijek se možete pozvati na standardne... Linux Standard hijerarhije datotečnog sistema. Konkretno, FHS navodi da se /srv koristi za: "pohranjivanje podataka specifičnih za hosta - podataka koje proizvodi sistem, kao što su podaci i skripte web servera, podaci pohranjeni na FTP serverima i repozitorije sistema za kontrolu verzija (koji su se pojavili u FHS-2.3 2004. godine)".
To je upravo naš slučaj, pa smo sve što nam treba stavili u /srv, koji je u vlasništvu korisnika naše aplikacije (cloud-user).
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
Postavljanje PostgreSQL-a i Djanga je jednostavno: kreirajte bazu podataka, kreirajte korisnika, konfigurirajte dozvole. Jedna stvar koju treba imati na umu pri početnoj instalaciji PostgreSQL-a je skripta postgresql-setup koja se instalira sa paketom postgresql-server. Ova skripta vam pomaže u izvođenju osnovnih zadataka povezanih s administracijom klastera baze podataka, kao što je inicijalizacija klastera ili proces nadogradnje. Da konfigurišemo novu PostgreSQL instancu na RHEL sistemu, moramo da pokrenemo naredbu:
sudo /usr/bin/postgresql-setup -initdb
Zatim možete pokrenuti PostgreSQL koristeći systemd, kreirati bazu podataka i postaviti projekat u Djangu. Ne zaboravite ponovo pokrenuti PostgreSQL nakon što napravite promjene u konfiguracijskoj datoteci za autentifikaciju klijenta (obično pg_hba.conf) kako biste konfigurirali pohranu lozinki za korisnika aplikacije. Ako naiđete na druge poteškoće, obavezno promijenite IPv4 i IPv6 postavke u datoteci 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
U datoteci /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
U datoteci /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 }}',
}
}
Nakon konfigurisanja datoteke settings.py u projektu i podešavanja konfiguracije baze podataka, možete pokrenuti razvojni server da biste bili sigurni da sve radi. Nakon pokretanja razvojnog servera, dobra je ideja kreirati administratorskog korisnika kako bi se testirala veza s bazom podataka.
./manage.py runserver 0.0.0.0:8000
./manage.py createsuperuser
WSGI? Wai?
Razvojni server je koristan za testiranje, ali da biste pokrenuli aplikaciju morate konfigurisati odgovarajući server i proxy za interfejs mrežnog prolaza servera (WSGI). Postoji nekoliko uobičajenih kombinacija, na primjer, Apache HTTPD sa uWSGI ili Nginx sa Gunicorn.
Svrha Web Server Gateway interfejsa je prosljeđivanje zahtjeva od web server Što se tiče Python web frameworka. WSGI je relikt strašne prošlosti, kada su se koristili CGI mehanizmi, a danas je WSGI de facto standard, bez obzira na korišteni web server ili Python framework. Uprkos širokoj prihvaćenosti, i dalje postoje mnoge nijanse pri radu s ovim frameworkovima i širok raspon opcija. U ovom slučaju, pokušat ćemo uspostaviti komunikaciju između Gunicorna i Nginxa putem socketa.
Pošto su obje ove komponente instalirane na istom serveru, pokušajmo koristiti UNIX utičnicu umjesto mrežne utičnice. Budući da komunikacija u svakom slučaju zahtijeva socket, pokušajmo napraviti još jedan korak i konfigurirati aktivaciju utičnice za Gunicorn preko systemd-a.
Proces kreiranja usluga aktiviranih utičnicom je prilično jednostavan. Prvo se kreira jedinična datoteka koja sadrži direktivu ListenStream koja ukazuje na tačku u kojoj će se kreirati UNIX soket, zatim jedinična datoteka za uslugu u kojoj će direktiva Requires pokazivati na datoteku jedinice utičnice. Zatim, u datoteci servisne jedinice, sve što ostaje je da pozovete Gunicorn iz virtuelnog okruženja i kreirate WSGI vezu za UNIX socket i Django aplikaciju.
Evo nekoliko primjera datoteka jedinica koje možete koristiti kao osnovu. Prvo postavljamo utičnicu.
[Unit]
Description=Gunicorn WSGI socket
[Socket]
ListenStream=/run/gunicorn.sock
[Install]
WantedBy=sockets.target
Sada morate konfigurirati Gunicorn demona.
[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
Za Nginx je jednostavno kreiranje proxy konfiguracijskih datoteka i postavljanje direktorija za pohranjivanje statičkog sadržaja ako ga koristite. U RHEL-u, Nginx konfiguracijske datoteke se nalaze u /etc/nginx/conf.d. Možete kopirati sljedeći primjer u datoteku /etc/nginx/conf.d/default.conf i pokrenuti uslugu. Obavezno postavite server_name da odgovara vašem imenu hosta.
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;
}
}
Pokrenite Gunicorn socket i Nginx koristeći systemd i spremni ste za početak testiranja.
Greška lošeg mrežnog prolaza?
Ako unesete adresu u preglednik, vjerovatno ćete dobiti grešku 502 Bad Gateway. To može biti uzrokovano nepravilno konfiguriranim dozvolama na UNIX socketu ili složenijim problemima vezanim za kontrolu pristupa u SE.Linux.
U nginx dnevniku grešaka možete vidjeti ovu liniju:
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"
Ako direktno testiramo Gunicorn, dobićemo prazan odgovor.
curl —unix-socket /run/gunicorn.sock 8beta1.example.com
Hajde da shvatimo zašto se ovo dešava. Ako otvorite zapisnik, najvjerovatnije ćete vidjeti da je problem povezan sa SE.LinuxPošto pokrećemo demon koji nema vlastitu politiku, označen je kao init_t. Testirajmo ovu teoriju u praksi.
sudo setenforce 0
Sve ovo može izazvati kritike i krvave suze, ali ovo je samo otklanjanje grešaka prototipa. Deaktivirajmo provjeru samo da se uvjerimo da je to problem, nakon čega ćemo sve vratiti na svoje mjesto.
Osvježavanjem stranice u pretraživaču ili ponovnim pokretanjem naše curl komande, možete vidjeti Django test stranicu.
Dakle, nakon što se uvjerimo da sve radi i da više nema problema s dozvolama, ponovo uključujemo SELinux.
sudo setenforce 1
Ovaj članak neće pokrivati audit2allow ili kreiranje politika zasnovanih na upozorenjima pomoću sepolgena, jer trenutno ne postoji prava Django aplikacija, tako da ne postoji potpuna mapa onoga čemu Gunicorn može htjeti pristupiti, a šta treba zabraniti. Stoga je važno da SE ostane u funkciji.Linux da zaštiti sistem, a istovremeno omogući aplikaciji da se pokreće i ostavlja poruke u zapisniku revizije kako bi se na osnovu njih mogle kreirati stvarne politike.
Određivanje dozvoljenih domena
O dozvoljenim domenama u SELinux Nisu svi čuli za njih, ali nisu ništa novo. Mnogi su čak i radili s njima, a da toga nisu ni bili svjesni. Kada se politika kreira na osnovu poruka revizije, rezultirajuća politika predstavlja dozvoljeni domen. Pokušajmo kreirati jednostavnu politiku dozvoljavanja.
Da biste kreirali određeni dozvoljeni domen za Gunicorn, potrebna vam je neka vrsta politike, a također morate označiti odgovarajuće datoteke. Osim toga, potrebni su alati za sastavljanje novih politika.
sudo yum install selinux-policy-devel
Mehanizam dozvoljenih domena je odličan alat za identifikaciju problema, posebno kada je u pitanju prilagođena aplikacija ili aplikacije koje se isporučuju bez već kreiranih politika. U ovom slučaju, dozvoljena politika domene za Gunicorn će biti što je moguće jednostavnija - deklarirajte glavni tip (gunicorn_t), deklarirajte tip koji ćemo koristiti za označavanje više izvršnih datoteka (gunicorn_exec_t), a zatim postavite prijelaz za sistem da ispravno označi pokrenuti procesi. Poslednji red postavlja politiku kao podrazumevano omogućenu u trenutku kada se učita.
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;
Možete kompajlirati ovu datoteku politike i dodati je svom sistemu.
make -f /usr/share/selinux/devel/Makefile
sudo semodule -i gunicorn.pp
sudo semanage permissive -a gunicorn_t
sudo semodule -l | grep permissive
Provjerimo da li SE blokiraLinux nešto drugo osim onoga na šta se naš nepoznati demon obraća.
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 sprečava Nginx da piše podatke u UNIX socket koji koristi Gunicorn. Obično se politike mijenjaju u takvim slučajevima, ali ostala pitanja ostaju koja treba riješiti. Također možete promijeniti postavke domene, pretvarajući je iz ograničene domene u permisivnu domenu. Sada premjestimo httpd_t u permisivnu domenu. Ovo će Nginxu pružiti potreban pristup i možemo nastaviti s otklanjanjem grešaka.
sudo semanage permissive -a httpd_t
Dakle, kada si uspio spasiti SE zaštitu?Linux (u stvari, ne biste trebali napustiti projekat sa SELinux Ako je sistem u ograničenom načinu rada i domene dozvola se učitavaju, moramo shvatiti šta tačno treba označiti kao gunicorn_exec_t da bi sve ponovo ispravno radilo. Pokušajmo pristupiti web stranici da vidimo sve nove poruke o ograničenjima pristupa.
sudo ausearch -m AVC -c gunicorn
Vidjet ćete puno poruka koje sadrže 'comm="gunicorn"' koje rade razne stvari na datotekama u /srv/djangoapp, tako da je ovo očito jedna od naredbi koje vrijedi označiti.
Ali pored toga, pojavljuje se poruka poput ove:
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
Ako pogledate status usluge gunicorn ili pokrenete naredbu ps, nećete vidjeti pokrenute procese. Izgleda da gunicorn pokušava pristupiti Python interpreteru u našem virtualenv okruženju, možda da bi pokrenuo radne skripte. Dakle, hajde da označimo ove dvije izvršne datoteke i provjerimo možemo li otvoriti našu Django test stranicu.
chcon -t gunicorn_exec_t /srv/djangoapp/django/bin/gunicorn /srv/djangoapp/django/bin/python3.6
Gunicorn uslugu će trebati ponovo pokrenuti prije nego što se može odabrati nova oznaka. Možete ga odmah ponovo pokrenuti ili zaustaviti uslugu i pustiti utičnicu da je pokrene kada otvorite stranicu u pretraživaču. Provjerite da li su procesi primili ispravne oznake pomoću ps.
ps -efZ | grep gunicorn
Ne zaboravite kasnije kreirati normalnu SE polisuLinux!
Ako sada pogledate AVC poruke, zadnja poruka sadrži permissive=1 za sve što se odnosi na aplikaciju i permissive=0 za ostatak sistema. Ako shvatite kakav pristup stvarnoj aplikaciji treba, možete brzo pronaći najbolji način za rješavanje takvih problema. Ali do tada, najbolje je da sistem bude siguran i da dobijete jasnu, upotrebljivu reviziju Django projekta.
sudo ausearch -m AVC
Desilo se!
Pojavio se radni Django projekat sa frontendom baziranim na Nginxu i Gunicorn WSGI. Konfigurisali smo Python 3 i PostgreSQL 10 iz RHEL 8 Beta spremišta. Sada možete krenuti naprijed i kreirati (ili jednostavno implementirati) Django aplikacije ili istražiti druge dostupne alate u RHEL 8 Beta kako biste automatizirali proces konfiguracije, poboljšali performanse ili čak spremili ovu konfiguraciju.
izvor: www.habr.com
