Atolyeya RHEL 8 Beta: Avakirina sepanên malperê yên xebatê

RHEL 8 Beta gelek taybetmendiyên nû pêşkêşî pêşdebiran dike, navnîşa wan dikare rûpelan bigire, di heman demê de fêrbûna tiştên nû di pratîkê de her gav çêtir e, ji ber vê yekê li jêr em atolyeyek li ser bi rastî afirandina binesaziyek serîlêdanê li ser bingeha Red Hat Enterprise Linux 8 Beta pêşkêş dikin.

Atolyeya RHEL 8 Beta: Avakirina sepanên malperê yên xebatê

Werin em Python, zimanek bernamesaziyê ya populer di nav pêşdebiran de, wekî bingehek bigirin, berhevokek Django û PostgreSQL, ji bo afirandina serîlêdanan berhevokek pir hevpar, û RHEL 8 Beta mîheng bikin ku bi wan re bixebite. Dûv re em ê çend malzemeyên din (netesenkirî) lê zêde bikin.

Dê hawîrdora ceribandinê biguhere, ji ber ku balkêş e ku meriv li îmkanên otomasyonê, xebata bi konteyneran re û ceribandina hawîrdorên bi gelek serveran re keşif bike. Ji bo ku hûn bi projeyek nû dest pê bikin, hûn dikarin dest bi çêkirina prototîpek piçûk û hêsan a bi destan bikin, da ku hûn bi rastî bibînin ka çi hewce dike û çawa ew têkil dike, û dûv re derbasî otomatê bibin û mîhengên tevlihevtir biafirînin. Îro em li ser çêkirina prototîpek weha dipeyivin.

Werin em bi belavkirina wêneya RHEL 8 Beta VM dest pê bikin. Hûn dikarin makîneyek virtual ji nû ve saz bikin, an wêneya mêvanê KVM-ê ku bi abonetiya xweya Beta-yê heye bikar bînin. Dema ku wêneyek mêvan bikar bînin, hûn ê hewce bikin ku CD-yek virtual ku dê metadata û daneyên bikarhêner ji bo destpêkirina ewr (ewr-init) vehewîne mîheng bikin. Hûn ne hewce ne ku tiştek taybetî bi strukturên dîskê an pakêtên berdest re bikin.

Werin em ji nêzîk ve li tevahiya pêvajoyê binêrin.

Sazkirina Django

Bi guhertoya herî nû ya Django re, hûn ê hewceyê hawîrdorek virtual (virtualenv) bi Python 3.5 an derengtir bikin. Di notên Beta de hûn dikarin bibînin ku Python 3.6 heye, em binihêrin ka ev bi rastî wusa ye:

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

Red Hat bi çalak Python wekî amûrek pergalê li RHEL bikar tîne, ji ber vê yekê çima ev encam dibe?

Rastî ev e ku gelek pêşdebirên Python hîn jî li ser derbasbûna ji Python 2 bo Python 2 difikirin, dema ku Python 3 bixwe di bin pêşkeftina çalak de ye, û her ku diçe bêtir guhertoyên nû têne xuyang kirin. Ji ber vê yekê, ji bo peydakirina hewcedariya amûrên pergalê yên domdar dema ku ji bikarhêneran re gihîştina guhertoyên cihêreng ên nû yên Python-ê pêşkêşî dike, pergala Python di pakêtek nû de hate veguheztin û şiyana sazkirina hem Python 2.7 û 3.6 peyda kir. Zêdetir agahdarî di derbarê guhertinan de û çima ew hatine çêkirin dikarin di weşana nav de werin dîtin Bloga Langdon White (Langdon White).

Ji ber vê yekê, ji bo ku hûn Python-ê bixebitin, hûn tenê hewce ne ku du pakêtan saz bikin, ku python3-pip wekî pêwendiyek tê de heye.

sudo yum install python36 python3-virtualenv

Çima wekî ku Langdon pêşniyar dike bangên modulê yên rasterast bikar neynin û pip3 saz nekin? Di hişê xwe de otomasyona dahatûyê digirin, em dizanin ku Ansible ji bo xebitandinê pêdivî ye ku pipek were saz kirin, ji ber ku modula pip-ê virtualenv-ên bi pîpek xwerû ya darvekirî piştgirî nake.

Li gel wergêrek python3 ya ku di destê we de ye, hûn dikarin pêvajoya sazkirina Django bidomînin û digel pêkhateyên me yên din xwedî pergalek xebatê bin. Li ser Înternetê gelek vebijarkên pêkanînê hene. Guhertoyek li vir tê pêşkêş kirin, lê bikarhêner dikarin pêvajoyên xwe bikar bînin.

Em ê guhertoyên PostgreSQL û Nginx-ê yên ku di RHEL 8-ê de bi xwerû bi karanîna Yum-ê têne peyda kirin saz bikin.

sudo yum install nginx postgresql-server

PostgreSQL dê psycopg2 hewce bike, lê pêdivî ye ku ew tenê di hawîrdorek virtualenv de peyda bibe, ji ber vê yekê em ê wê bi karanîna pip3 digel Django û Gunicorn saz bikin. Lê pêşî divê em virtualenv saz bikin.

Li ser mijara hilbijartina cîhê rast ji bo sazkirina projeyên Django her gav gelek nîqaş hene, lê gava ku hûn guman dikin, hûn dikarin her gav berê xwe bidin Standarda Hiyerarşiya Pergala Pelan a Linux. Bi taybetî, FHS dibêje ku /srv tê bikar anîn: "Daneyên taybetî yên mêvandar-daneyên ku pergalê hildiberîne, wekî daneyên servera malperê û nivîsar, daneyên ku li ser serverên FTP-yê hatine hilanîn, û guhertoyên pergalê kontrol dikin (di FHS de xuya dibin." -2.3 di 2004 de)."

Ev tam doza me ye, ji ber vê yekê em her tiştê ku ji me re lazim e têxin nav /srv, ku xwediyê serîlêdana me ya bikarhêner (karhênerê ewr) ye.

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

Sazkirina PostgreSQL û Django hêsan e: databasek biafirînin, bikarhênerek biafirînin, destûrên mîheng bikin. Tiştek ku meriv di destpêkê de PostgreSQL saz dike di hişê xwe de bigire skrîpta postgresql-setup e ku bi pakêta postgresql-server ve hatî saz kirin. Ev skrîpt ji we re dibe alîkar ku hûn peywirên bingehîn ên ku bi rêveberiya koma databasê ve girêdayî ne, wekî destpêkirina komê an pêvajoya nûvekirinê pêk bînin. Ji bo mîhengkirina mînakek PostgreSQL ya nû li ser pergalek RHEL, pêdivî ye ku em fermanê bimeşînin:

sudo /usr/bin/postgresql-setup -initdb

Dûv re hûn dikarin PostgreSQL bi karanîna systemd-ê dest pê bikin, databasek biafirînin, û projeyek li Django saz bikin. Bînin bîra xwe ku hûn PostgreSQL-ê ji nû ve bidin destpêkirin piştî ku hûn guheztinên pelê vesazkirina rastkirina xerîdar (bi gelemperî pg_hba.conf) bikin da ku hilanîna şîfreyê ji bo bikarhênerê serîlêdanê mîheng bikin. Ger hûn bi dijwariyên din re rû bi rû bimînin, pê ewle bin ku hûn di pelê pg_hba.conf de mîhengên IPv4 û IPv6 biguherînin.

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

Di pelê /var/lib/pgsql/data/pg_hba.conf de:

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

Di pelê /srv/djangoapp/settings.py de:

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

Piştî ku pelê settings.py di projeyê de mîheng kirin û veavakirina databasê saz kirin, hûn dikarin servera pêşkeftinê dest pê bikin da ku pê ewle bibin ku her tişt dixebite. Piştî destpêkirina servera pêşkeftinê, ramanek baş e ku meriv bikarhênerek rêveberê biafirîne da ku girêdana bi databasê re ceribandin.

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

WSGI? Wai?

Pêşkêşkara pêşkeftinê ji bo ceribandinê bikêr e, lê ji bo ku serîlêdanê bimeşîne divê hûn server û proxy guncan ji bo Navrûya Gateway Server Web (WSGI) mîheng bikin. Gelek kombînasyona hevpar hene, mînakî, Apache HTTPD bi uWSGI an Nginx bi Gunicorn re.

Karê Navbera Gateway Pêşkêşkara Webê ev e ku daxwazên ji servera malperê berbi çarçoweya tevna Python ve bişîne. WSGI bermayek paşeroja tirsnak e dema ku motorên CGI li dora xwe bûn, û îro WSGI standarda defakto ye, bêyî ku servera malperê an çarçoveya Python-ê tê bikar anîn. Lê tevî karanîna wê ya berfireh, dema ku bi van çarçoweyan re dixebitin, hîn jî gelek nuwaze hene, û gelek vebijark. Di vê rewşê de, em ê hewl bidin ku têkiliyek di navbera Gunicorn û Nginx de bi riya soketek saz bikin.

Ji ber ku van her du beşan li ser heman serverê têne saz kirin, bila em biceribînin ku li şûna soketek torê, soketek UNIX bikar bînin. Ji ber ku ragihandinê di her rewşê de soketek hewce dike, em hewl bidin ku gavek din bavêjin û ji bo Gunicorn bi systemd ve çalakkirina soketê mîheng bikin.

Pêvajoya afirandina karûbarên çalakkirî yên soketê pir hêsan e. Pêşî, pelek yekîneyek tê afirandin ku tê de rêwerzek ListenStream heye ku destnîşan dike xala ku tê de dê soketa UNIX were afirandin, dûv re pelek yekîneyek ji bo karûbarê ku tê de rêbernameya Requires dê îşaret bi pelê yekîneya soketê bike. Dûv re, di pelê yekîneya karûbarê de, ya ku dimîne ev e ku meriv ji hawîrdora virtual gazî Gunicorn bike û ji bo soketa UNIX û serîlêdana Django girêdanek WSGI biafirîne.

Li vir çend mînakên pelên yekîneyê hene ku hûn dikarin wekî bingehek bikar bînin. Pêşî me soketê saz kir.

[Unit]
Description=Gunicorn WSGI socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target

Naha hûn hewce ne ku daemonê Gunicorn mîheng bikin.

[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

Ji bo Nginx, ev mijarek hêsan e ku hûn pelên mîhengê proxy biafirînin û pelrêçek saz bikin da ku naveroka statîk hilînin heke hûn yek bikar tînin. Di RHEL de, pelên veavakirina Nginx li /etc/nginx/conf.d hene. Hûn dikarin mînaka jêrîn li pelê /etc/nginx/conf.d/default.conf kopî bikin û karûbarê dest pê bikin. Bawer bikin ku server_name bi navê mêvandarê we re têkildar bike.

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

Soketa Gunicorn û Nginx bi karanîna systemd-ê dest pê bikin û hûn amade ne ku dest bi ceribandinê bikin.

Çewtiya Deriyê Xirab?

Ger hûn navnîşanê têkevin geroka xwe, hûn ê bi îhtîmalek mezin xeletiyek 502 Bad Gateway bistînin. Dibe ku ew ji ber destûrên soketa UNIX-ê ku bi xeletî hatine mîheng kirin, an jî dibe ku ji ber pirsgirêkên tevlihevtir ên têkildarî kontrola gihîştina li SELinux-ê be.

Di têketina xeletiya nginx de hûn dikarin rêzek weha bibînin:

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"

Ger em rasterast Gunicorn ceribandin, em ê bersivek vala bistînin.

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

Ka em fêhm bikin ka çima ev diqewime. Ger hûn têketinê vekin, hûn ê bi îhtîmalek mezin bibînin ku pirsgirêk bi SELinux re têkildar e. Ji ber ku em daemonek ku jê re siyasetek nehatiye afirandin dimeşînin, ew wekî init_t tê nîşankirin. Werin em vê teoriyê di pratîkê de biceribînin.

sudo setenforce 0

Dibe ku ev hemî bibe sedema rexne û rondikên xwînê, lê ev tenê prototîpa xelet dike. Werin em kontrolê neçalak bikin ku tenê pê ewle bibin ku ev pirsgirêk e, piştî ku em ê her tiştî vegerînin cihê xwe.

Bi nûvekirina rûpelê di gerokê de an dubarekirina fermana meya curl, hûn dikarin rûpela testa Django bibînin.

Ji ber vê yekê, piştî ku em piştrast bûn ku her tişt dixebite û êdî pirsgirêkên destûr tune, em dîsa SELinux çalak dikin.

sudo setenforce 1

Ez ê li vir qala audit2allow an çêkirina polîtîkayên bingeh-hişyariyê bi sepolgen nekim, ji ber ku di vê gavê de serîlêdana Django ya rastîn tune, ji ber vê yekê nexşeyek bêkêmasî ya ku Gunicorn dikare bixwaze bigihîje çi û divê ew gihîştina çi red bike tune. Ji ber vê yekê, pêdivî ye ku SELinux xebitîne da ku pergalê biparêze, di heman demê de destûr bide ku serîlêdan bixebite û peyaman di qeyda kontrolê de bihêle da ku paşê siyaseta rastîn ji wan were afirandin.

Diyarkirina domên destûrdar

Ne her kesî li ser domainên destûrkirî yên li SELinux bihîstiye, lê ew ne tiştek nû ne. Gelek kes jî bêyî ku haya wan jê hebe bi wan re xebitîn. Dema ku siyasetek li ser bingeha peyamên kontrolê tê afirandin, siyaseta hatî afirandin qada çareserkirî temsîl dike. Werin em hewl bidin ku siyasetek destûrek hêsan biafirînin.

Ji bo ku hûn ji bo Gunicorn domainek destûrkirî ya taybetî biafirînin, ji we re siyasetek heye, û hûn jî hewce ne ku pelên guncan nîşan bikin. Ji bilî vê, amûrên ji bo komkirina polîtîkayên nû hewce ne.

sudo yum install selinux-policy-devel

Mekanîzmaya domên destûr ji bo tespîtkirina pirsgirêkan amûrek girîng e, nemaze dema ku ew tê ser serîlêdanek xwerû an serîlêdanên ku bêyî polîtîkayên ku jixwe hatine afirandin têne şandin. Di vê rewşê de, polîtîkaya domainê ya destûr ji bo Gunicorn dê bi qasî ku gengaz be - celebek sereke (gunicorn_t) ragihîne, celebek ku em ê bikar bînin ji bo nîşankirina gelek pêkeran (gunicorn_exec_t) bikar bînin (gunicorn_exec_t), û dûv re veguhezek saz bikin ku pergalê bi rast nîşan bide pêvajoyên xebitandinê. Rêza paşîn di dema barkirinê de polîtîkayê wekî ku ji hêla xwerû ve hatî çalak kirin destnîşan dike.

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;

Hûn dikarin vê pelê polîtîkayê berhev bikin û li pergala xwe zêde bikin.

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

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

Werin em binihêrin ka SELinux ji bilî ya ku daemonê meya nenas digihîje tiştek din asteng dike.

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 nahêle ku Nginx daneyan li soketa UNIX-ê ku ji hêla Gunicorn ve hatî bikar anîn binivîse. Bi gelemperî, di rewşên weha de, polîtîka dest bi guhertinê dikin, lê li pêş de kêşeyên din hene. Her weha hûn dikarin mîhengên domainê ji domînek sînorkirî biguhezînin domainek destûr. Naha em httpd_t bar bikin qada destûran. Ev ê gihandina pêwîst bide Nginx û em dikarin bi xebata debugkirinê ya din re bidomînin.

sudo semanage permissive -a httpd_t

Ji ber vê yekê, gava ku we karî SELinux parastî bihêle (divê hûn bi rastî projeyek SELinux di moda sînorkirî de nehêlin) û domên destûr têne barkirin, hûn hewce ne ku fêm bikin ka bi rastî çi hewce dike ku wekî gunicorn_exec_t were nîşankirin da ku her tişt bi rêkûpêk bixebite. dîsa. Werin em biceribînin ku biçin ser malperê da ku peyamên nû li ser qedexeyên gihîştinê bibînin.

sudo ausearch -m AVC -c gunicorn

Hûn ê gelek peyamên ku tê de 'comm="gunicorn"' hene bibînin ku tiştên cihêreng li ser pelên li /srv/djangoapp dikin, ji ber vê yekê ev eşkere yek ji fermanên ku hêjayî alakirinê ye.

Lê ji bilî vê, peyamek weha xuya dike:

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

Ger hûn li rewşa karûbarê gunicorn binihêrin an fermana ps-ê bimeşînin, hûn ê pêvajoyên xebitandinê nabînin. Wusa dixuye ku gunicorn hewl dide ku xwe bigihîne wergêrê Python di hawîrdora meya virtualenv de, dibe ku skrîptên karker bimeşîne. Ji ber vê yekê naha em van her du pelên darvekirî nîşan bikin û kontrol bikin ka em dikarin rûpela xweya ceribandina Django vekin.

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

Berî ku nîşana nû were hilbijartin, pêdivî ye ku karûbarê gunicorn ji nû ve were destpêkirin. Hûn dikarin wê tavilê ji nû ve bidin destpêkirin an karûbarê rawestînin û gava ku hûn malperê di gerokê de vekin bila soket dest pê bike. Piştrast bikin ku pêvajoyan bi karanîna ps etîketên rast wergirtine.

ps -efZ | grep gunicorn

Ji bîr nekin ku paşê polîtîkaya SELinux-ê ya normal biafirînin!

Ger hûn niha li peyamên AVC-ê binêrin, di peyama paşîn de ji bo her tiştê ku bi serîlêdanê ve girêdayî ye destûr=1 û ji bo pergalên mayî destûr=0 heye. Ger hûn fêm bikin ka çi celeb gihîştina serîlêdanek rastîn hewce dike, hûn dikarin zû riya çêtirîn ji bo çareserkirina pirsgirêkên weha bibînin. Lê heya wê demê, çêtirîn e ku hûn pergalê ewle bihêlin û ji projeya Django vekolînek zelal û bikêrhatî bistînin.

sudo ausearch -m AVC

Bûye!

Projeyek Django ya xebatê bi pêşekek li ser bingeha Nginx û Gunicorn WSGI xuya bû. Me Python 3 û PostgreSQL 10 ji depoyên RHEL 8 Beta mîheng kirin. Naha hûn dikarin pêşde biçin û serîlêdanên Django biafirînin (an bi tenê bicîh bikin) an jî amûrên din ên berdest di RHEL 8 Beta de keşif bikin da ku pêvajoya veavakirinê otomatîk bikin, performansê baştir bikin, an jî vê veavakirinê jî konteynir bikin.

Source: www.habr.com

Add a comment