Delavnica RHEL 8 Beta: Gradnja delujočih spletnih aplikacij

RHEL 8 Beta razvijalcem ponuja številne nove funkcije, katerih naštevanje bi lahko trajalo veliko, vendar se je učenje novih stvari vedno boljše izvajati skozi prakso, zato spodaj ponujamo praktičen vodnik za ustvarjanje resnične aplikacijske infrastrukture, ki temelji na Red Hat Enterprise. Linux 8 Beta.

Delavnica RHEL 8 Beta: Gradnja delujočih spletnih aplikacij

Za osnovo vzemimo Python, med razvijalci priljubljen programski jezik, kombinacijo Djanga in PostgreSQL, dokaj pogoste kombinacije za ustvarjanje aplikacij, in nastavimo RHEL 8 Beta za delo z njima. Nato bomo dodali še nekaj (neuvrščenih) sestavin.

Testno okolje se bo spremenilo, saj je zanimivo raziskovati možnosti avtomatizacije, dela s kontejnerji in preizkušanje okolij z več strežniki. Če želite začeti z novim projektom, lahko začnete tako, da ročno ustvarite majhen, preprost prototip, da boste lahko natančno videli, kaj se mora zgoditi in kako deluje, nato pa nadaljujete z avtomatizacijo in ustvarjanjem bolj zapletenih konfiguracij. Danes govorimo o ustvarjanju takšnega prototipa.

Začnimo z uvedbo slike RHEL 8 Beta VM. Navidezni stroj lahko namestite iz nič ali uporabite gostujočo sliko KVM, ki je na voljo z vašo naročnino Beta. Pri uporabi gostujoče slike boste morali konfigurirati virtualni CD, ki bo vseboval metapodatke in uporabniške podatke za inicializacijo v oblaku (cloud-init). S strukturo diska ali razpoložljivimi paketi vam ni treba storiti ničesar posebnega; zadostuje vsaka konfiguracija.

Oglejmo si podrobneje celoten postopek.

Namestitev Djanga

Z najnovejšo različico Djanga boste potrebovali virtualno okolje (virtualenv) s Pythonom 3.5 ali novejšim. V beta opombah lahko vidite, da je Python 3.6 na voljo, preverimo, ali je res tako:

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

Red Hat aktivno uporablja Python kot sistemski komplet orodij v RHEL, zakaj se torej to zgodi?

Dejstvo je, da številni razvijalci Pythona še vedno razmišljajo o prehodu s Python 2 na Python 2, sam Python 3 pa je v aktivnem razvoju in vedno več novih različic se pojavlja. Da bi zadovoljili potrebo po stabilnih sistemskih orodjih, hkrati pa uporabnikom ponudili dostop do različnih novih različic Pythona, je bil sistemski Python premaknjen v nov paket in je zagotovil možnost namestitve Pythona 2.7 in 3.6. Več informacij o spremembah in razlogih zanje najdete v objavi v Blog Langdona Whitea (Langdon White).

Če želite torej Python delovati, morate namestiti samo dva paketa, pri čemer je python3-pip vključen kot odvisnost.

sudo yum install python36 python3-virtualenv

Zakaj ne bi uporabili neposrednih klicev modulov, kot predlaga Langdon, in namestili pip3? Ob upoštevanju prihajajoče avtomatizacije je znano, da bo Ansible za delovanje zahteval nameščen pip, saj modul pip ne podpira virtualenvs z izvršljivo datoteko pip po meri.

Z delujočim tolmačem python3, ki vam je na voljo, lahko nadaljujete s postopkom namestitve Django in imate delujoč sistem skupaj z našimi drugimi komponentami. Na internetu je na voljo veliko možnosti izvedbe. Tukaj je predstavljena ena različica, vendar lahko uporabniki uporabljajo svoje lastne procese.

Z Yum bomo privzeto namestili različici PostgreSQL in Nginx, ki sta na voljo v RHEL 8.

sudo yum install nginx postgresql-server

PostgreSQL bo zahteval psycopg2, vendar mora biti na voljo le v okolju virtualenv, zato ga bomo namestili s pip3 skupaj z Django in Gunicorn. Toda najprej moramo nastaviti virtualenv.

Vedno je veliko razprav o pravem mestu za namestitev projektov Django, toda če ste v dvomih, se lahko vedno sklicujete na standard Linux Standard hierarhije datotečnih sistemov. FHS natančneje navaja, da se /srv uporablja za: "shranjevanje podatkov, specifičnih za gostitelja – podatkov, ki jih ustvari sistem, kot so podatki in skripti spletnega strežnika, podatki, shranjeni na strežnikih FTP, in repozitoriji sistema za nadzor različic (ki so se pojavili v FHS-2.3 leta 2004)."

To je točno naš primer, zato vse, kar potrebujemo, damo v /srv, ki je v lasti uporabnika 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

Nastavitev PostgreSQL in Django je enostavna: ustvarite bazo podatkov, ustvarite uporabnika, konfigurirajte dovoljenja. Ena stvar, ki jo morate upoštevati pri začetni namestitvi PostgreSQL, je namestitveni skript postgresql, ki je nameščen s paketom postgresql-server. Ta skript vam pomaga izvajati osnovne naloge, povezane z upravljanjem gruče baze podatkov, kot je inicializacija gruče ali postopek nadgradnje. Če želite konfigurirati nov primerek PostgreSQL v sistemu RHEL, moramo zagnati ukaz:

sudo /usr/bin/postgresql-setup -initdb

Nato lahko zaženete PostgreSQL z uporabo systemd, ustvarite bazo podatkov in nastavite projekt v Djangu. Ne pozabite znova zagnati PostgreSQL, potem ko spremenite konfiguracijsko datoteko za preverjanje pristnosti odjemalca (običajno pg_hba.conf), da konfigurirate shranjevanje gesel za uporabnika aplikacije. Če naletite na druge težave, spremenite nastavitve IPv4 in IPv6 v datoteki 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

V datoteki /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

V datoteki /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 }}',
   }
}

Ko konfigurirate datoteko settings.py v projektu in nastavite konfiguracijo baze podatkov, lahko zaženete razvojni strežnik, da se prepričate, da vse deluje. Po zagonu razvojnega strežnika je dobro ustvariti skrbniškega uporabnika, da preizkusite povezavo z bazo podatkov.

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

WSGI? Wai?

Razvojni strežnik je uporaben za testiranje, vendar morate za zagon aplikacije konfigurirati ustrezen strežnik in proxy za vmesnik spletnega strežnika Gateway (WSGI). Obstaja več pogostih kombinacij, na primer Apache HTTPD z uWSGI ali Nginx z Gunicorn.

Namen vmesnika spletnega strežnika je posredovanje zahtev iz spletni strežnik K spletnemu ogrodju Python. WSGI je ostanek grozne preteklosti, ko so se uporabljali mehanizmi CGI, danes pa je WSGI dejanski standard, ne glede na uporabljeni spletni strežnik ali ogrodje Python. Kljub široki uporabi pa pri delu s temi ogrodji še vedno obstaja veliko odtenkov in širok nabor možnosti. V tem primeru bomo poskušali vzpostaviti komunikacijo med Gunicorn in Nginx prek vtičnice.

Ker sta obe komponenti nameščeni na istem strežniku, poskusimo namesto omrežne vtičnice uporabiti vtičnico UNIX. Ker komunikacija v vsakem primeru zahteva vtičnico, poskusimo narediti še en korak in konfigurirati aktivacijo vtičnice za Gunicorn prek systemd.

Postopek ustvarjanja storitev, aktiviranih z vtičnicami, je precej preprost. Najprej se ustvari datoteka enote, ki vsebuje direktivo ListenStream, ki kaže na točko, kjer bo ustvarjena vtičnica UNIX, nato pa datoteka enote za storitev, v kateri bo direktiva Zahteva kazala na datoteko enote vtičnice. Nato v datoteki storitvene enote ostane le še, da pokličemo Gunicorn iz virtualnega okolja in ustvarimo vezavo WSGI za vtičnico UNIX in aplikacijo Django.

Tukaj je nekaj primerov datotek enot, ki jih lahko uporabite kot osnovo. Najprej smo postavili vtičnico.

[Unit]
Description=Gunicorn WSGI socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target

Zdaj morate konfigurirati demona 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

Za Nginx je preprosto ustvarjanje konfiguracijskih datotek posrednika in nastavitev imenika za shranjevanje statične vsebine, če ga uporabljate. V RHEL se konfiguracijske datoteke Nginx nahajajo v /etc/nginx/conf.d. Naslednji primer lahko kopirate v datoteko /etc/nginx/conf.d/default.conf in zaženete storitev. Prepričajte se, da nastavite ime strežnika tako, da se ujema z imenom vašega gostitelja.

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;
   }
}

Zaženite vtičnico Gunicorn in Nginx z uporabo systemd in pripravljeni ste na začetek testiranja.

Napaka Bad Gateway?

Če vnesete naslov v brskalnik, boste verjetno dobili napako 502 Bad Gateway. To lahko povzročijo napačno konfigurirana dovoljenja za vtičnico UNIX ali pa bolj zapletene težave, povezane z nadzorom dostopa v SE.Linux.

V dnevniku napak nginx lahko vidite vrstico, kot je ta:

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"

Če neposredno testiramo Gunicorn, bomo dobili prazen odgovor.

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

Ugotovimo, zakaj se to dogaja. Če odprete dnevnik, boste najverjetneje videli, da je težava povezana s SE.LinuxKer izvajamo demon, ki nima lastne politike, je označen kot init_t. Preizkusimo to teorijo v praksi.

sudo setenforce 0

Vse to lahko povzroči kritike in krvave solze, vendar je to le odpravljanje napak v prototipu. Onemogočimo preverjanje samo zato, da se prepričamo, da je to težava, potem pa bomo vse vrnili na svoje mesto.

Če osvežite stran v brskalniku ali znova zaženete naš ukaz curl, si lahko ogledate preskusno stran Django.

Torej, ko se prepričamo, da vse deluje in da ni več težav z dovoljenji, ponovno vklopimo SELinux.

sudo setenforce 1

Ta članek ne bo obravnaval audit2allow ali ustvarjanja pravilnikov na podlagi opozoril z uporabo sepolgena, saj trenutno ni prave aplikacije Django, zato ni popolnega zemljevida, do česa bi Gunicorn morda želel dostopati in kaj bi moral zavrniti. Zato je pomembno, da SE ostane delujoč.Linux za zaščito sistema, hkrati pa omogoča aplikaciji, da se še vedno izvaja in pušča sporočila v dnevniku nadzora, tako da se na podlagi njih lahko ustvari dejanska politika.

Določanje permisivnih domen

O dovoljenih domenah v SELinux Niso vsi slišali zanje, vendar niso nič novega. Mnogi so z njimi celo sodelovali, ne da bi se tega zavedali. Ko je pravilnik ustvarjen na podlagi revizijskih sporočil, nastali pravilnik predstavlja dovoljeno domeno. Poskusimo ustvariti preprost pravilnik za dovoljenja.

Če želite ustvariti določeno dovoljeno domeno za Gunicorn, potrebujete nekakšen pravilnik, prav tako pa morate označiti ustrezne datoteke. Poleg tega so potrebna orodja za sestavljanje novih pravilnikov.

sudo yum install selinux-policy-devel

Mehanizem dovoljenih domen je odlično orodje za prepoznavanje težav, zlasti ko gre za aplikacijo po meri ali aplikacije, ki so dobavljene brez že ustvarjenih pravilnikov. V tem primeru bo pravilnik o dovoljeni domeni za Gunicorn čim preprostejši – deklarirajte glavni tip (gunicorn_t), deklarirajte tip, ki ga bomo uporabili za označevanje več izvršljivih datotek (gunicorn_exec_t), nato pa nastavite prehod, da sistem pravilno označi tekoči procesi. Zadnja vrstica nastavi pravilnik kot privzeto omogočen v času nalaganja.

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;

To datoteko pravilnika lahko sestavite in jo dodate v svoj sistem.

make -f /usr/share/selinux/devel/Makefile
sudo semodule -i gunicorn.pp

sudo semanage permissive -a gunicorn_t
sudo semodule -l | grep permissive

Preverimo, ali SE blokiraLinux nekaj drugega kot tisto, na kar nagovarja naš neznani demon.

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 preprečuje, da bi Nginx pisal podatke v vtičnico UNIX, ki jo uporablja Gunicorn. Pravila se v takih primerih običajno spremenijo, vendar je treba še odpraviti druge težave. Spremenite lahko tudi nastavitve domene in jo pretvorite iz omejene domene v permisivno domeno. Zdaj pa premaknimo httpd_t v permisivno domeno. To bo Nginxu zagotovilo potreben dostop in lahko nadaljujemo z odpravljanjem napak.

sudo semanage permissive -a httpd_t

Torej, kdaj vam je uspelo rešiti zaščito SE?Linux (pravzaprav projekta ne bi smeli zapustiti pri SELinux Če je sistem v omejenem načinu in se nalagajo domene dovoljenj, moramo ugotoviti, kaj točno je treba označiti kot gunicorn_exec_t, da bo vse spet pravilno delovalo. Poskusimo dostopati do spletnega mesta in videti morebitna nova sporočila o omejitvah dostopa.

sudo ausearch -m AVC -c gunicorn

Videli boste veliko sporočil, ki vsebujejo 'comm="gunicorn"', ki izvajajo različne stvari v datotekah v /srv/djangoapp, zato je to očitno eden od ukazov, ki ga je vredno označiti.

Toda poleg tega se prikaže sporočilo, kot je to:

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

Če pogledate status storitve gunicorn ali zaženete ukaz ps, ne boste videli nobenih tekočih procesov. Videti je, da gunicorn poskuša dostopati do tolmača Python v našem okolju virtualenv, po možnosti za zagon delovnih skriptov. Označimo ti dve izvršljivi datoteki in preverimo, ali lahko odpremo našo testno stran Django.

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

Storitev gunicorn bo treba znova zagnati, preden bo mogoče izbrati novo oznako. Takoj ga lahko znova zaženete ali zaustavite storitev in pustite, da jo vtičnica zažene, ko odprete spletno mesto v brskalniku. Z ps preverite, ali so procesi prejeli pravilne oznake.

ps -efZ | grep gunicorn

Ne pozabite kasneje ustvariti običajne politike SE.Linux!

Če zdaj pogledate sporočila AVC, zadnje sporočilo vsebuje permissive=1 za vse, kar je povezano z aplikacijo, in permissive=0 za preostali sistem. Če razumete, kakšen dostop potrebuje prava aplikacija, lahko hitro najdete najboljši način za reševanje takšnih težav. Toda do takrat je najbolje, da ohranite sistem varen in pridobite jasno, uporabno revizijo projekta Django.

sudo ausearch -m AVC

Zgodilo se!

Pojavil se je delujoč projekt Django s sprednjim delom, ki temelji na Nginx in Gunicorn WSGI. Konfigurirali smo Python 3 in PostgreSQL 10 iz repozitorijev RHEL 8 Beta. Zdaj se lahko premaknete naprej in ustvarite (ali preprosto uvedete) aplikacije Django ali raziščete druga razpoložljiva orodja v RHEL 8 Beta za avtomatizacijo postopka konfiguracije, izboljšanje zmogljivosti ali celo shranjevanje te konfiguracije.

Vir: www.habr.com

Kupite zanesljivo gostovanje za strani z DDoS zaščito, VPS VDS strežniki 🔥 Kupite zanesljivo spletno gostovanje z zaščito DDoS, VPS VDS strežniki | ProHoster