RHEL 8 Beta Tailerra: Laneko Web Aplikazioak eraikitzea

RHEL 8 Beta-k garatzaileei eginbide berri asko eskaintzen dizkie, eta horien zerrendak orrialdeak har ditzake, hala ere, gauza berriak ikastea beti da praktikan hobea; beraz, jarraian Red Hat Enterprise Linux 8 Beta-n oinarritutako aplikazio-azpiegitura bat sortzeko tailer bat eskaintzen dugu.

RHEL 8 Beta Tailerra: Laneko Web Aplikazioak eraikitzea

Har dezagun Python, garatzaileen artean programazio-lengoaia ezaguna, oinarritzat Django eta PostgreSQL konbinazio bat, aplikazioak sortzeko nahiko konbinazio arrunta, eta konfigura dezagun RHEL 8 Beta haiekin lan egiteko. Ondoren, beste pare bat osagai gehituko ditugu (sailkatu gabekoak).

Proba-ingurunea aldatuko da, interesgarria delako automatizazioaren aukerak arakatzea, edukiontziekin lan egitea eta zerbitzari anitz dituzten inguruneak probatzea. Proiektu berri batekin hasteko, prototipo txiki eta sinple bat eskuz sortzen has zaitezke, zer gertatu behar den eta nola elkarreragiten duen ikusi ahal izateko, eta gero automatizatzera eta konfigurazio konplexuagoak sortzera. Gaur horrelako prototipo baten sorreraz ari gara.

Has gaitezen RHEL 8 Beta VM irudia zabaltzen. Makina birtual bat instalatu dezakezu hutsetik, edo zure Beta harpidetzarekin eskuragarri dagoen KVM gonbidatuaren irudia erabil dezakezu. Gonbidatu-irudi bat erabiltzean, hodeiaren hasierako metadatuak eta erabiltzaile-datuak izango dituen CD birtual bat konfiguratu beharko duzu (cloud-init). Ez duzu ezer berezirik egin behar diskoaren egiturarekin edo eskuragarri dauden paketeekin; edozein konfigurazio balioko du.

Ikus dezagun prozesu osoa gertutik.

Django instalatzen

Django-ren bertsio berrienarekin, Python 3.5 edo berriagoa duen ingurune birtual bat (virtualenv) beharko duzu. Beta-oharretan Python 3.6 erabilgarri dagoela ikus dezakezu, egiazta dezagun hala den:

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

Red Hat-ek aktiboki erabiltzen du Python sistema-tresna-tresna gisa RHEL-en, beraz, zergatik lortzen du emaitza hau?

Kontua da Python-eko garatzaile askok Python 2-tik Python 2-rako trantsizioa aztertzen ari direla oraindik, Python 3 bera garapen aktiboan dagoen bitartean, eta gero eta bertsio berri gehiago agertzen ari dira etengabe. Hori dela eta, sistema-tresna egonkorren beharrari erantzuteko, erabiltzaileei Python-en hainbat bertsio berrietarako sarbidea eskaintzen dien bitartean, Python sistema pakete berri batera eraman zen eta Python 2.7 eta 3.6 instalatzeko gaitasuna eman zuen. Aldaketei buruzko informazio gehiago eta zergatik egin diren argitalpenean aurki daiteke Langdon Whiteren bloga (Langdon Zuria).

Beraz, Python-ek funtzionatzeko, bi pakete instalatu behar dituzu, python3-pip menpekotasun gisa sartuta.

sudo yum install python36 python3-virtualenv

Zergatik ez erabili zuzeneko modulu-deiak Langdonek iradokitzen duen moduan eta instalatu pip3? Datorren automatizazioa kontuan izanda, jakina da Ansiblek pip instalatu beharko duela exekutatzeko, pip moduluak ez baitu onartzen virtualenvs pip exekutagarri pertsonalizatu batekin.

Python3 interprete funtzionala zure eskura duzula, Django instalazio-prozesuarekin jarraitu dezakezu eta gure gainerako osagaiekin batera lan-sistema bat izan dezakezu. Interneten ezarpen-aukera asko daude eskuragarri. Hemen aurkezten den bertsio bat dago, baina erabiltzaileek beren prozesuak erabil ditzakete.

RHEL 8-n eskuragarri dauden PostgreSQL eta Nginx bertsioak instalatuko ditugu lehenespenez Yum erabiliz.

sudo yum install nginx postgresql-server

PostgreSQL-k psycopg2 beharko du, baina virtualenv ingurunean soilik egon behar du erabilgarri, beraz pip3 erabiliz instalatuko dugu Django eta Gunicorn-ekin batera. Baina lehenik virtualenv konfiguratu behar dugu.

Beti eztabaida handia dago Django proiektuak instalatzeko leku egokia aukeratzeko gaiaren inguruan, baina zalantza izanez gero, Linux Fitxategien Hierarkia Estandarra jo dezakezu beti. Zehazki, FHSk dio /srv erabiltzen dela: "ostalariaren berariazko datuak gordetzeko: sistemak ekoizten dituen datuak, hala nola web zerbitzariaren datuak eta script-ak, FTP zerbitzarietan gordetako datuak eta kontrol-sistemaren biltegiak." bertsioak (FHSn agertzen dira -2.3 2004an)."

Hau da, hain zuzen ere, gure kasua, beraz, behar dugun guztia /srv-en jartzen dugu, zeina gure aplikazioaren erabiltzailea den (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

PostgreSQL eta Django konfiguratzea erraza da: datu-base bat sortu, erabiltzaile bat sortu, baimenak konfiguratu. PostgreSQL hasiera batean instalatzerakoan kontuan izan beharreko gauza bat postgresql-server paketearekin instalatzen den postgresql-setup scripta da. Script honek datu-baseen klusterraren administrazioarekin lotutako oinarrizko zereginak egiten laguntzen dizu, hala nola, kluster hasieratzea edo berritze prozesua. RHEL sistema batean PostgreSQL instantzia berri bat konfiguratzeko, komandoa exekutatu behar dugu:

sudo /usr/bin/postgresql-setup -initdb

Ondoren, PostgreSQL abiarazi dezakezu systemd erabiliz, datu-base bat sortu eta Django-n proiektu bat konfiguratu. Gogoratu PostgreSQL berrabiarazi behar duzula bezeroaren autentifikazioaren konfigurazio fitxategian (normalean pg_hba.conf) aldaketak egin ondoren aplikazioaren erabiltzailearentzat pasahitzen biltegia konfiguratzeko. Beste zailtasun batzuk aurkitzen badituzu, ziurtatu pg_hba.conf fitxategian IPv4 eta IPv6 ezarpenak aldatzen dituzula.

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

/var/lib/pgsql/data/pg_hba.conf fitxategian:

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

/srv/djangoapp/settings.py fitxategian:

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

Proiektuan settings.py fitxategia konfiguratu eta datu-basearen konfigurazioa konfiguratu ondoren, garapen zerbitzaria abi dezakezu dena funtzionatzen duela ziurtatzeko. Garapen zerbitzaria hasi ondoren, komeni da administratzaile bat sortzea datu-basearekiko konexioa probatzeko.

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

WSGI? Wai?

Garapen zerbitzaria probak egiteko erabilgarria da, baina aplikazioa exekutatzeko Web Server Gateway Interface (WSGI) zerbitzari eta proxy egokiak konfiguratu behar dituzu. Hainbat konbinazio arrunt daude, adibidez, Apache HTTPD uWSGI-rekin edo Nginx Gunicorn-ekin.

Web Server Gateway Interfazearen lana web zerbitzaritik eskaerak Python web esparrura bidaltzea da. WSGI CGI motorrak zeudenean iragan izugarriaren erlikia da, eta gaur egun WSGI de facto estandarra da, erabilitako web zerbitzaria edo Python esparrua edozein dela ere. Baina erabilera zabala izan arren, Γ±abardura asko daude oraindik esparru hauekin lan egitean, eta aukera asko. Kasu honetan, Gunicorn eta Nginx-en arteko elkarrekintza ezartzen saiatuko gara socket baten bidez.

Bi osagai hauek zerbitzari berean instalatuta daudenez, saia gaitezen UNIX socket bat erabiltzen sareko socket baten ordez. Komunikazioak edozein kasutan entxufe bat behar duenez, saia gaitezen urrats bat gehiago ematen eta konfiguratzen Gunicorn-en socket-a aktibatzea systemd bidez.

Socket aktibatutako zerbitzuak sortzeko prozesua nahiko erraza da. Lehenik eta behin, UNIX socket-a sortuko den puntura seinalatzen duen ListenStream zuzentarau bat duen unitate-fitxategi bat sortzen da, eta, ondoren, Requires zuzentarauak socket-unitate-fitxategia seinalatu duen zerbitzurako unitate-fitxategi bat. Ondoren, zerbitzu-unitateko fitxategian, Gunicorn ingurune birtualetik deitzea eta UNIX socketerako eta Django aplikaziorako WSGI lotura sortzea besterik ez da geratzen.

Hona hemen oinarri gisa erabil ditzakezun unitate-fitxategien adibide batzuk. Lehenik entxufea ezarri dugu.

[Unit]
Description=Gunicorn WSGI socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target

Orain Gunicorn deabrua konfiguratu behar duzu.

[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

Nginx-entzat, proxy konfigurazio fitxategiak sortzea eta eduki estatikoa gordetzeko direktorio bat konfiguratzea besterik ez da erabiltzen ari bazara. RHEL-en, Nginx konfigurazio-fitxategiak /etc/nginx/conf.d-en daude. Ondorengo adibidea /etc/nginx/conf.d/default.conf fitxategian kopiatu eta zerbitzua abi dezakezu. Ziurtatu zerbitzari_izena zure ostalari izenarekin bat etortzeko ezarri duzula.

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

Hasi Gunicorn socketa eta Nginx systemd erabiliz eta probak hasteko prest zaude.

Gateway-ko errorea?

Helbidea zure arakatzailean sartzen baduzu, ziurrenik 502 Bad Gateway errore bat jasoko duzu. Baliteke gaizki konfiguratutako UNIX-en socket-en baimenak izatea, edo SELinux-en sarbide-kontrolarekin lotutako arazo konplexuagoak izatea.

Nginx erroreen erregistroan honelako lerro bat ikus dezakezu:

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"

Gunicorn zuzenean probatzen badugu, erantzun huts bat lortuko dugu.

curl β€”unix-socket /run/gunicorn.sock 8beta1.example.com

Ea zergatik gertatzen den hau. Erregistroa irekitzen baduzu, ziurrenik arazoa SELinux-ekin lotuta dagoela ikusiko duzu. Politikarik sortu ez den deabru bat exekutatzen ari garenez, init_t gisa markatuta dago. Proba dezagun teoria hau praktikan.

sudo setenforce 0

Horrek guztiak kritikak eta odol malkoak sor ditzake, baina hau prototipoa arazketa besterik ez da. Desgaitu dezagun egiaztapena arazoa hori dela ziurtatzeko, eta ondoren dena bere lekura itzuliko dugu.

Orria arakatzailean freskatuz edo gure curl komandoa berriro exekutatuta, Django proba orria ikus dezakezu.

Beraz, dena funtzionatzen duela eta baimen-arazorik ez dagoela ziurtatu ondoren, SELinux gaituko dugu berriro.

sudo setenforce 1

Ez dut hemen audit2allow edo alertan oinarritutako politikak sortzeaz hitz egingo sepolgen-ekin, momentuz ez baitago benetako Django aplikaziorik, beraz, ez dago Gunicorn-ek zer atzitu nahi izan dezakeen eta zertarako sarbidea ukatu behar duen. Hori dela eta, beharrezkoa da SELinux martxan mantentzea sistema babesteko, eta, aldi berean, aplikazioa exekutatzen utzi eta auditoretza-erregistroan mezuak uzteko aukera ematen dio, gero haietatik benetako politika sortu ahal izateko.

Domeinu baimengarriak zehaztea

Denek ez dute SELinux-en baimendutako domeinuen berri izan, baina ez dira berriak. Askok ere haiekin lan egin zuten konturatu gabe. Politika bat auditoretza-mezuetan oinarrituta sortzen denean, sortutako politikak ebatzitako domeinua adierazten du. Saia gaitezen baimen-politika soil bat sortzen.

Gunicorn-entzako baimendutako domeinu espezifiko bat sortzeko, politika motaren bat behar duzu, eta fitxategi egokiak ere markatu behar dituzu. Horrez gain, tresnak behar dira politika berriak muntatzeko.

sudo yum install selinux-policy-devel

Baimendutako domeinuen mekanismoa tresna bikaina da arazoak identifikatzeko, batez ere dagoeneko sorturiko politikarik gabe bidaltzen diren aplikazio pertsonalizatu edo aplikazioei dagokienez. Kasu honetan, Gunicorn-en baimendutako domeinu-politika ahalik eta sinpleena izango da - deklaratu mota nagusi bat (gunicorn_t), deklaratu exekutagarri anitz markatzeko erabiliko dugun mota bat (gunicorn_exec_t) eta, ondoren, konfiguratu trantsizio bat sistema behar bezala markatzeko. exekutatzen ari diren prozesuak. Azken lerroak politika lehenespenez gaituta bezala ezartzen du kargatzen den unean.

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;

Politika-fitxategi hau konpila dezakezu eta zure sisteman gehi dezakezu.

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

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

Ikus dezagun SELinux-ek gure deabru ezezaguna sartzen ari den beste zerbait blokeatzen ari ote den.

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-ek Nginx-ek Gunicorn-ek erabiltzen duen UNIX socketean datuak idaztea eragozten du. Normalean, halakoetan, politikak aldatzen hasten dira, baina beste erronka batzuk daude aurretik. Domeinuaren ezarpenak ere alda ditzakezu murrizketa-domeinu batetik baimen-domeinu batera. Orain mugi dezagun httpd_t baimenen domeinura. Honek Nginx-i beharrezko sarbidea emango dio eta arazketa lan gehiagorekin jarraitu ahal izango dugu.

sudo semanage permissive -a httpd_t

Beraz, SELinux babestuta mantentzea lortu ondoren (ez zenuke SELinux proiektu bat modu mugatuan utzi behar) eta baimen-domeinuak kargatzen direnean, jakin behar duzu zer markatu behar den gunicorn_exec_t gisa dena behar bezala funtziona dezan. berriz. Saia gaitezen webgunea bisitatzen sarbide murrizketei buruzko mezu berriak ikusteko.

sudo ausearch -m AVC -c gunicorn

/srv/djangoapp-ko fitxategietan hainbat gauza egiten dituzten 'comm="gunicorn"' duten mezu asko ikusiko dituzu, beraz, hau da, jakina, markatu beharreko komandoetako bat.

Baina horrez gain, honelako mezu bat agertzen da:

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

Gunicorn zerbitzuaren egoera aztertzen baduzu edo ps komandoa exekutatzen baduzu, ez duzu exekutatzen ari den prozesurik ikusiko. Badirudi gunicorn gure virtualenv ingurunean Python interpretea sartzen saiatzen ari dela, beharbada langileen scriptak exekutatzeko. Beraz, orain markatu ditzagun bi fitxategi exekutagarri hauek eta egiaztatu gure Django proba orria ireki dezakegun.

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

Gunicorn zerbitzua berrabiarazi beharko da etiketa berria hautatu ahal izateko. Berehala berrabia dezakezu edo zerbitzua gelditu eta socketa abiarazten utzi gunea arakatzailean irekitzen duzunean. Egiaztatu prozesuek etiketa egokiak jaso dituztela ps erabiliz.

ps -efZ | grep gunicorn

Ez ahaztu gero SELinux politika normal bat sortzea!

Orain AVC mezuei begiratuz gero, azken mezuak permissive=1 dauka aplikazioarekin zerikusia duen guztiarentzat, eta permissive=0 sistemaren gainerakoentzat. Benetako aplikazio batek zer sarbide-mota behar duen ulertzen baduzu, azkar aurki dezakezu horrelako arazoak konpontzeko modurik onena. Baina ordura arte, hobe da sistema seguru mantentzea eta Django proiektuaren auditoria argi eta erabilgarri bat lortzea.

sudo ausearch -m AVC

Gertatu da!

Lanean ari den Django proiektu bat agertu da Nginx eta Gunicorn WSGIn oinarritutako frontend batekin. Python 3 eta PostgreSQL 10 konfiguratu ditugu RHEL 8 Beta biltegietatik. Orain aurrera egin eta Django aplikazioak sor ditzakezu (edo besterik gabe inplementatu) edo RHEL 8 Beta-n eskuragarri dauden beste tresna batzuk arakatu ditzakezu konfigurazio-prozesua automatizatzeko, errendimendua hobetzeko edo are konfigurazio hau edukiontziratzeko.

Iturria: www.habr.com

Gehitu iruzkin berria