RHEL 8 Beta Workshop: Creazione di applicazioni Web di travagliu

RHEL 8 Beta offre à i sviluppatori assai funzioni novi, a lista di quale puderia piglià pagine, però, l'apprendimentu di e cose novi hè sempre megliu in a pratica, cusì quì sottu offremu un attellu nantu à veramente creà una infrastruttura d'applicazione basata in Red Hat Enterprise Linux 8 Beta.

RHEL 8 Beta Workshop: Creazione di applicazioni Web di travagliu

Pigliemu Python, una lingua di prugrammazione populari trà i sviluppatori, cum'è una basa, una cumminazione di Django è PostgreSQL, una cumminazione abbastanza cumuna per creà applicazioni, è cunfigurà RHEL 8 Beta per travaglià cun elli. Allora aghjunghjemu un paru di ingredienti più (senza classificazione).

L'ambiente di prova cambierà, perchè hè interessante per scopre e pussibulità di l'automatizazione, travagliendu cù cuntenituri è pruvà ambienti cù parechji servitori. Per principià cù un novu prughjettu, pudete principià per creà un prototipu chjucu è simplice cù a manu per pudè vede esattamente ciò chì deve accade è cumu interagisce, è poi passà per automatizà è creà cunfigurazioni più cumplesse. Oghje parlemu di a creazione di un tali prototipu.

Cuminciamu da implementà l'imagine RHEL 8 Beta VM. Pudete installà una macchina virtuale da zero, o utilizate l'imaghjini d'ospiti KVM dispunibule cù u vostru abbonamentu Beta. Quandu aduprate una maghjina d'ospiti, avete bisognu di cunfigurà un CD virtuale chì cuntene metadata è dati d'utilizatori per l'inizializazione di nuvola (cloud-init). Ùn avete bisognu di fà nunda di speciale cù a struttura di discu o i pacchetti dispunibili; qualsiasi cunfigurazione farà.

Fighjemu un ochju più vicinu à tuttu u prucessu.

Installazione di Django

Cù a versione più nova di Django, avete bisognu di un ambiente virtuale (virtualenv) cù Python 3.5 o più tardi. In e note Beta pudete vede chì Python 3.6 hè dispunibule, verificate se questu hè veramente u casu:

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

Red Hat usa attivamente Python cum'è un toolkit di sistema in RHEL, allora perchè questu risultatu?

U fattu hè chì parechji sviluppatori di Python sò sempre cuntemplati a transizione da Python 2 à Python 2, mentre chì Python 3 stessu hè in sviluppu attivu, è più è più novi versioni sò sempre apparsu. Dunque, per risponde à a necessità di strumenti di sistema stabile mentre offre à l'utilizatori l'accessu à diverse versioni novi di Python, u sistema Python hè statu spustatu in un novu pacchettu è furnisce a capacità di installà sia Python 2.7 sia 3.6. Più infurmazione nantu à i cambiamenti è perchè sò stati fatti ponu esse truvati in a publicazione in U blog di Langdon White (Langdon White).

Dunque, per travaglià Python, avete solu bisognu di installà dui pacchetti, cù python3-pip inclusu cum'è dipendenza.

sudo yum install python36 python3-virtualenv

Perchè ùn utilizate micca e chjama di moduli diretti cum'è Langdon suggerisce è installate pip3? Tenendu in mente l'automatizazione imminente, hè cunnisciutu chì Ansible necessitarà pip installatu per eseguisce, postu chì u modulu pip ùn sustene micca virtualenvs cù un eseguibile pip persunalizatu.

Cù un interprete python3 chì travaglia à a vostra dispusizione, pudete cuntinuà cù u prucessu di stallazione Django è avè un sistema di travagliu cù i nostri altri cumpunenti. Ci sò parechje opzioni di implementazione dispunibili nantu à Internet. Ci hè una versione presentata quì, ma l'utilizatori ponu utilizà i so prucessi.

Stallaremu e versioni PostgreSQL è Nginx dispunibuli in RHEL 8 per difettu cù Yum.

sudo yum install nginx postgresql-server

PostgreSQL richiederà psycopg2, ma deve esse dispunibule solu in un ambiente virtualenv, cusì l'installeremu usendu pip3 cù Django è Gunicorn. Ma prima avemu bisognu di stallà virtualenv.

Ci hè sempre assai dibattitu nantu à u tema di sceglie u locu adattatu per installà i prughjetti di Django, ma in casu di dubbitu, pudete sempre vultà à u Linux Filesystem Hierarchy Standard. Specificamenti, l'FHS dice chì / srv hè utilizatu per: "almacenà dati specifichi di l'ospite - dati chì u sistema pruduce, cum'è dati è script di u servitore web, dati almacenati in i servitori FTP, è i repositori di u sistema di cuntrollu". -2.3 in u 2004).

Questu hè esattamente u nostru casu, cusì mettemu tuttu ciò chì avemu bisognu in / srv, chì hè propiu di u nostru utilizatore di l'applicazione (nuvola-utente).

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

Configurazione di PostgreSQL è Django hè faciule: crea una basa di dati, crea un utilizatore, cunfigurà i permessi. Una cosa da tene in mente quandu si stalla inizialmente PostgreSQL hè u script postgresql-setup chì hè stallatu cù u pacchettu postgresql-server. Stu script vi aiuta à realizà e funzioni basiche assuciate à l'amministrazione di cluster di basa di dati, cum'è l'inizializazione di cluster o u prucessu di aghjurnamentu. Per cunfigurà una nova istanza PostgreSQL in un sistema RHEL, avemu bisognu di eseguisce u cumandimu:

sudo /usr/bin/postgresql-setup -initdb

Allora pudete inizià PostgreSQL cù systemd, creà una basa di dati, è stabilisce un prughjettu in Django. Ricurdativi di riavvia PostgreSQL dopu avè fattu cambiamenti à u schedariu di cunfigurazione di l'autentificazione di u cliente (di solitu pg_hba.conf) per cunfigurà l'almacenamiento di password per l'utilizatore di l'applicazione. Se scontri altre difficultà, assicuratevi di cambià l'IPv4 è l'IPv6 in u schedariu 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

In u schedariu /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

In u schedariu /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 }}',
   }
}

Dopu a cunfigurazione di u schedariu settings.py in u prugettu è a cunfigurazione di a basa di dati, pudete inizià u servitore di sviluppu per assicurà chì tuttu funziona. Dopu avè principiatu u servitore di sviluppu, hè una bona idea di creà un utilizatore amministratore per pruvà a cunnessione à a basa di dati.

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

WSGI? Wai?

U servitore di sviluppu hè utile per a prova, ma per eseguisce l'applicazione deve cunfigurà u servitore appropritatu è u proxy per l'Interfaccia Web Server Gateway (WSGI). Ci hè parechje cumminazzioni cumuni, per esempiu, Apache HTTPD cù uWSGI o Nginx cù Gunicorn.

U travagliu di u Web Server Gateway Interface hè di rinvià e dumande da u servitore web à u framework web Python. WSGI hè una reliquia di u terribili passatu quandu i motori CGI eranu intornu, è oghje WSGI hè u standard di facto, indipendentemente da u servitore web o u framework Python utilizatu. Ma malgradu u so usu diffusa, ci sò sempre assai sfumature quandu travaglia cù sti frameworks, è parechje scelte. In questu casu, pruveremu di stabilisce l'interazzione trà Gunicorn è Nginx via un socket.

Siccomu sti dui cumpunenti sò stallati nantu à u stessu servitore, pruvemu à utilizà un socket UNIX invece di un socket di rete. Siccomu a cumunicazione richiede un socket in ogni casu, pruvemu di fà un passu più è cunfigurà l'attivazione di u socket per Gunicorn via systemd.

U prucessu di creà servizii attivati ​​socket hè abbastanza sèmplice. Prima, hè creatu un schedariu di unità chì cuntene una direttiva ListenStream chì indica u puntu à quale u socket UNIX serà creatu, dopu un schedariu di unità per u serviziu in quale a direttiva Requires indicà à u schedariu di unità di socket. Allora, in u schedariu di l'unità di serviziu, tuttu ciò chì resta hè di chjamà Gunicorn da l'ambiente virtuale è creà un vintu WSGI per u socket UNIX è l'applicazione Django.

Eccu alcuni esempi di schedarii unità chì pudete aduprà com'è basa. Prima avemu stallatu u socket.

[Unit]
Description=Gunicorn WSGI socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target

Avà avete bisognu di cunfigurà u 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

Per Nginx, hè una questione simplice di creà fugliali di cunfigurazione proxy è stabilisce un repertoriu per almacenà u cuntenutu staticu se ne aduprate unu. In RHEL, i schedarii di cunfigurazione Nginx si trovanu in /etc/nginx/conf.d. Pudete copià l'esempiu seguente in u schedariu /etc/nginx/conf.d/default.conf è inizià u serviziu. Assicuratevi di stabilisce u server_name per currisponde à u vostru nome d'ospite.

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

Avviate u socket Gunicorn è Nginx usendu systemd è site prontu per inizià a prova.

Errore di Gateway Bad?

Se inserite l'indirizzu in u vostru navigatore, più prubabilmente riceverete un errore 502 Bad Gateway. Pò esse causatu da permessi di socket UNIX cunfigurati in modu incorrectu, o pò esse dovutu à prublemi più cumplessi in relazione à u cuntrollu di l'accessu in SELinux.

In u logu di errore nginx pudete vede una linea cum'è questu:

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"

Se testemu Gunicorn direttamente, averemu una risposta viota.

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

Scupritemu perchè questu succede. Sè avete apertu u logu, probabilmente vi vede chì u prublema hè in relazione cù SELinux. Siccomu eseguimu un daemon per quale ùn hè micca stata creata una pulitica, hè marcatu cum'è init_t. Testemu sta teoria in pratica.

sudo setenforce 0

Tuttu chistu pò causà critiche è lacrime di sangue, ma questu hè solu debugging u prototipu. Disattivemu a verificazione solu per assicurà chì questu hè u prublema, dopu chì vulteremu tuttu in u so locu.

Per rinfriscà a pagina in u navigatore o rerunning our curl command, pudete vede a pagina di prova di Django.

Allora, avè assicuratu chì tuttu funziona è ùn ci sò più prublemi di permessu, attivemu SELinux di novu.

sudo setenforce 1

Ùn parleraraghju micca di audit2allow o di creà pulitiche basate in alerte cù sepolgen quì, postu chì ùn ci hè micca una vera applicazione Django per u mumentu, cusì ùn ci hè micca una mappa cumpleta di ciò chì Gunicorn puderia vulete accede è ciò chì duverebbe negà l'accessu. Per quessa, hè necessariu di mantene SELinux in esecuzione per prutege u sistema, mentre chì à u stessu tempu permette à l'applicazione di eseguisce è lasciate missaghji in u logu di l'auditu in modu chì a pulitica attuale pò esse creata da elli.

Specificà i domini permissivi

Micca tutti anu intesu parlà di domini permessi in SELinux, ma ùn sò nunda di novu. Parechje anu travagliatu ancu cun elli senza mancu capitu. Quandu una pulitica hè creata nantu à i missaghji di auditu, a pulitica creata rapprisenta u duminiu risoltu. Pruvemu di creà una pulitica simplice di permessu.

Per creà un duminiu specificu permessu per Gunicorn, avete bisognu di qualchì tipu di pulitica, è avete ancu bisognu di marcà i schedari apprupriati. Inoltre, i strumenti sò necessarii per assemblà novi pulitiche.

sudo yum install selinux-policy-devel

U mecanismu di domini permessi hè un grande strumentu per identificà i prublemi, soprattuttu quandu si tratta di una applicazione persunalizata o applicazioni chì spedinu senza pulitiche digià creatu. In questu casu, a pulitica di u duminiu permessu per Gunicorn serà u più simplice pussibule - dichjarà un tipu principale (gunicorn_t), dichjarà un tipu chì useremu per marcà parechje eseguibili (gunicorn_exec_t), è poi stabilisce una transizione per u sistema per marcà currettamente. prucessi in esecuzione. L'ultima linea stabilisce a pulitica cum'è attivata per difettu à u mumentu chì hè caricata.

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;

Pudete cumpilà stu schedariu di pulitica è aghjunghje à u vostru sistema.

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

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

Cuntrollamu per vede s'ellu SELinux blucca qualcosa altru ch'è ciò chì u nostru daemon scunnisciutu accede.

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 impedisce à Nginx di scrive dati à u socket UNIX utilizatu da Gunicorn. Di genere, in tali casi, e pulitiche cumincianu à cambià, ma ci sò altre sfide davanti. Pudete ancu cambià i paràmetri di u duminiu da un duminiu di restrizzione à un duminiu di permessu. Avà movemu httpd_t à u duminiu di permessi. Questu darà à Nginx l'accessu necessariu è pudemu cuntinuà cù più travagliu di debugging.

sudo semanage permissive -a httpd_t

Allora, una volta chì avete riesciutu à mantene SELinux prutettu (ùn duvete veramente micca lascià un prughjettu SELinux in modu ristrettu) è i domini di permessu sò caricati, avete bisognu di capisce ciò chì esattamente deve esse marcatu cum'è gunicorn_exec_t per fà tuttu funziona bè. di novu. Pruvemu di visità u situ web per vede novi messagi nantu à e restrizioni d'accessu.

sudo ausearch -m AVC -c gunicorn

Puderete vede assai messagi chì cuntenenu 'comm="gunicorn"' chì facenu parechje cose nantu à i fugliali in /srv/djangoapp, dunque questu hè ovviamente unu di i cumandamenti chì vale a pena signalà.

Ma in più, appare un missaghju cum'è questu:

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

Se guardate u statutu di u serviziu di gunicornu o eseguite u cumandamentu ps, ùn vi vede micca processi in esecuzione. Sembra chì Gunicorn prova à accede à l'interprete Python in u nostru ambiente virtualenv, possibbilmente per eseguisce script di u travagliu. Allora marchemu sti dui fugliali eseguibili è verificate se pudemu apre a nostra pagina di prova Django.

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

U serviziu di Gunicorn hà da esse riavviatu prima chì u novu tag pò esse sceltu. Pudete ripiglià immediatamente o piantà u serviziu è lasciate u socket principià quandu avete apertu u situ in u navigatore. Verificate chì i prucessi anu ricevutu l'etichette currette cù ps.

ps -efZ | grep gunicorn

Ùn vi scurdate di creà una pulitica SELinux normale dopu!

Se guardate i missaghji AVC avà, l'ultimu missaghju cuntene permissive=1 per tuttu ciò chì tocca à l'applicazione, è permissive=0 per u restu di u sistema. Sè avete capitu chì tipu d'accessu una vera applicazione hà bisognu, pudete truvà rapidamente u megliu modu per risolve tali prublemi. Ma finu à tandu, hè megliu per mantene u sistema sicuru è uttene un auditu chjaru è utilizable di u prughjettu Django.

sudo ausearch -m AVC

Accadutu!

Un prughjettu Django di travagliu hè apparsu cù un frontend basatu in Nginx è Gunicorn WSGI. Avemu cunfiguratu Python 3 è PostgreSQL 10 da i repositori RHEL 8 Beta. Avà pudete avanzà è creà (o simpricimenti implementà) applicazioni Django o scopre altre arnesi dispunibuli in RHEL 8 Beta per automatizà u prucessu di cunfigurazione, migliurà u rendiment, o ancu cuntene sta cunfigurazione.

Source: www.habr.com

Add a comment