Seminārs RHEL 8 Beta: strādājoŔu tīmekļa lietojumprogrammu izveide

RHEL 8 Beta piedāvā izstrādātājiem daudzas jaunas iespējas, kuru uzskaitÄ«Å”ana varētu aizņemt lapas, tomēr praksē apgÅ«t jaunas lietas vienmēr ir labāk, tāpēc zemāk piedāvājam semināru par aplikāciju infrastruktÅ«ras reālu izveidi uz Red Hat Enterprise Linux 8 Beta bāzes.

Seminārs RHEL 8 Beta: strādājoŔu tīmekļa lietojumprogrammu izveide

Ņemsim par pamatu Python, izstrādātāju vidÅ« populāro programmÄ“Å”anas valodu, Django un PostgreSQL kombināciju, kas ir diezgan izplatÄ«ta kombinācija lietojumprogrammu izveidei, un konfigurēsim RHEL 8 Beta darbam ar tām. Tad pievienosim vēl pāris (neklasificētas) sastāvdaļas.

Testa vide mainÄ«sies, jo ir interesanti izpētÄ«t automatizācijas iespējas, strādāt ar konteineriem un izmēģināt vides ar vairākiem serveriem. Lai sāktu darbu ar jaunu projektu, varat ar roku izveidot nelielu, vienkārÅ”u prototipu, lai varētu precÄ«zi redzēt, kam jānotiek un kā tas mijiedarbojas, un pēc tam pāriet uz automatizāciju un sarežģītāku konfigurāciju izveidi. Å odien mēs runājam par Ŕāda prototipa izveidi.

Sāksim ar RHEL 8 Beta VM attēla izvietoÅ”anu. Varat instalēt virtuālo maŔīnu no jauna vai izmantot KVM viesa attēlu, kas pieejams jÅ«su Beta abonementā. Izmantojot viesa attēlu, jums bÅ«s jākonfigurē virtuālais kompaktdisks, kurā bÅ«s metadati un lietotāja dati mākoņa inicializÄ“Å”anai (Cloud-init). Ar diska struktÅ«ru vai pieejamajām pakotnēm nekas Ä«paÅ”s nav jādara; derēs jebkura konfigurācija.

Apskatīsim visu procesu tuvāk.

Django instalēŔana

Izmantojot jaunāko Django versiju, jums bÅ«s nepiecieÅ”ama virtuālā vide (virtualenv) ar Python 3.5 vai jaunāku versiju. Beta piezÄ«mēs varat redzēt, ka Python 3.6 ir pieejams, pārbaudÄ«sim, vai tas tā ir:

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

Red Hat aktīvi izmanto Python kā sistēmas rīkkopu RHEL, kāpēc tas rodas?

Fakts ir tāds, ka daudzi Python izstrādātāji joprojām apsver pāreju no Python 2 uz Python 2, savukārt pats Python 3 tiek aktÄ«vi izstrādāts, un pastāvÄ«gi parādās arvien jaunas versijas. Tāpēc, lai apmierinātu vajadzÄ«bu pēc stabiliem sistēmas rÄ«kiem, vienlaikus piedāvājot lietotājiem piekļuvi dažādām jaunām Python versijām, sistēma Python tika pārvietota uz jaunu pakotni un nodroÅ”ināja iespēju instalēt gan Python 2.7, gan 3.6. PlaŔāku informāciju par izmaiņām un to izdarÄ«Å”anas iemeslu var atrast publikācijā Lengdona Vaita emuārs (Lendona Vaita).

Tātad, lai strādātu ar Python, jums ir jāinstalē tikai divas pakotnes, un python3-pip ir iekļauta kā atkarība.

sudo yum install python36 python3-virtualenv

Kāpēc neizmantot tieÅ”os moduļu izsaukumus, kā to iesaka Lengdons, un instalēt pip3? Paturot prātā gaidāmo automatizāciju, ir zināms, ka Ansible darbÄ«bai bÅ«s nepiecieÅ”ams instalēt pip, jo pip modulis neatbalsta virtualenvs ar pielāgotu pip izpildāmo failu.

Ja jÅ«su rÄ«cÄ«bā ir strādājoÅ”s python3 tulks, varat turpināt Django instalÄ“Å”anas procesu un izveidot funkcionējoÅ”u sistēmu kopā ar citiem mÅ«su komponentiem. Internetā ir pieejamas daudzas ievieÅ”anas iespējas. Å eit ir viena versija, taču lietotāji var izmantot savus procesus.

Mēs instalēsim PostgreSQL un Nginx versijas, kas pēc noklusējuma ir pieejamas RHEL 8, izmantojot Yum.

sudo yum install nginx postgresql-server

PostgreSQL bÅ«s nepiecieÅ”ams psycopg2, taču tam ir jābÅ«t pieejamam tikai virtualenv vidē, tāpēc mēs to instalēsim, izmantojot pip3 kopā ar Django un Gunicorn. Bet vispirms mums ir jāiestata virtualenv.

Vienmēr ir daudz diskusiju par tēmu, kā izvēlēties pareizo vietu Django projektu instalÄ“Å”anai, taču, ja rodas Å”aubas, vienmēr varat vērsties pie Linux failu sistēmas hierarhijas standarta. Konkrēti, FHS saka, ka /srv tiek izmantots, lai: ā€œsaglabātu resursdatoram raksturÄ«gus datus ā€” datus, ko sistēma ražo, piemēram, tÄ«mekļa servera datus un skriptus, datus, kas tiek glabāti FTP serveros un kontroles sistēmas krātuvēs.ā€ versijas (parādās FHS -2.3 2004. gadā).

Tas ir tieÅ”i mÅ«su gadÄ«jums, tāpēc visu nepiecieÅ”amo ievietojam /srv, kas pieder mÅ«su lietojumprogrammas lietotājam (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 un Django iestatÄ«Å”ana ir vienkārÅ”a: izveidojiet datu bāzi, izveidojiet lietotāju, konfigurējiet atļaujas. Viena lieta, kas jāpatur prātā, sākotnēji instalējot PostgreSQL, ir postgresql-setup skripts, kas tiek instalēts kopā ar postgresql-servera pakotni. Å is skripts palÄ«dz veikt pamata uzdevumus, kas saistÄ«ti ar datu bāzes klasteru administrÄ“Å”anu, piemēram, klastera inicializÄ“Å”anu vai jaunināŔanas procesu. Lai konfigurētu jaunu PostgreSQL gadÄ«jumu RHEL sistēmā, mums ir jāpalaiž komanda:

sudo /usr/bin/postgresql-setup -initdb

Pēc tam varat startēt PostgreSQL, izmantojot systemd, izveidot datu bāzi un iestatÄ«t projektu Django. Neaizmirstiet restartēt PostgreSQL pēc izmaiņu veikÅ”anas klienta autentifikācijas konfigurācijas failā (parasti pg_hba.conf), lai konfigurētu paroles krātuvi lietojumprogrammas lietotājam. Ja rodas citas grÅ«tÄ«bas, noteikti mainiet IPv4 un IPv6 iestatÄ«jumus failā 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

Failā /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

Failā /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 }}',
   }
}

Pēc faila settings.py konfigurÄ“Å”anas projektā un datu bāzes konfigurācijas iestatÄ«Å”anas varat startēt izstrādes serveri, lai pārliecinātos, ka viss darbojas. Pēc izstrādes servera palaiÅ”anas ieteicams izveidot administratora lietotāju, lai pārbaudÄ«tu savienojumu ar datu bāzi.

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

WSGI? Vai?

Izstrādes serveris ir noderÄ«gs testÄ“Å”anai, taču, lai palaistu lietojumprogrammu, ir jākonfigurē atbilstoÅ”ais serveris un starpniekserveris tÄ«mekļa servera vārtejas saskarnei (WSGI). Ir vairākas izplatÄ«tas kombinācijas, piemēram, Apache HTTPD ar uWSGI vai Nginx ar Gunicorn.

TÄ«mekļa servera vārtejas saskarnes uzdevums ir pārsÅ«tÄ«t pieprasÄ«jumus no tÄ«mekļa servera uz Python tÄ«mekļa ietvaru. WSGI ir Å”ausmÄ«gās pagātnes relikts, kad pastāvēja CGI dzinēji, un mÅ«sdienās WSGI ir de facto standarts neatkarÄ«gi no izmantotā tÄ«mekļa servera vai Python ietvara. Bet, neskatoties uz tā plaÅ”o izmantoÅ”anu, strādājot ar Å”iem ietvariem, joprojām ir daudz nianses un daudzas izvēles iespējas. Å ajā gadÄ«jumā mēs mēģināsim izveidot mijiedarbÄ«bu starp Gunicorn un Nginx, izmantojot ligzdu.

Tā kā abi Å”ie komponenti ir instalēti vienā serverÄ«, mēģināsim tÄ«kla ligzdas vietā izmantot UNIX ligzdu. Tā kā saziņai jebkurā gadÄ«jumā ir nepiecieÅ”ama ligzda, mēģināsim spert vēl vienu soli un konfigurēt Gunicorn ligzdas aktivizÄ“Å”anu, izmantojot systemd.

Socket aktivizēto pakalpojumu izveides process ir diezgan vienkārÅ”s. Vispirms tiek izveidots vienÄ«bas fails, kurā ir ListenStream direktÄ«va, kas norāda uz vietu, kurā tiks izveidota UNIX ligzda, pēc tam pakalpojuma vienÄ«bas fails, kurā direktÄ«va Requires norāda uz ligzdas vienÄ«bas failu. Pēc tam servisa vienÄ«bas failā atliek tikai izsaukt Gunicorn no virtuālās vides un izveidot WSGI saiti UNIX ligzdai un Django lietojumprogrammai.

Šeit ir daži vienības failu piemēri, kurus varat izmantot par pamatu. Vispirms mēs uzstādām kontaktligzdu.

[Unit]
Description=Gunicorn WSGI socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target

Tagad jums ir jākonfigurē Gunicorn dēmons.

[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 ir vienkārÅ”i izveidot starpniekservera konfigurācijas failus un iestatÄ«t direktoriju statiskā satura glabāŔanai, ja tādu izmantojat. RHEL Nginx konfigurācijas faili atrodas mapē /etc/nginx/conf.d. Varat kopēt Å”o piemēru failā /etc/nginx/conf.d/default.conf un sākt pakalpojumu. Noteikti iestatiet servera_nosaukumu, lai tas atbilstu jÅ«su resursdatora nosaukumam.

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

Palaidiet Gunicorn ligzdu un Nginx, izmantojot systemd, un esat gatavs sākt testÄ“Å”anu.

Slikta vārtejas kļūda?

Ja ievadāt adresi pārlūkprogrammā, visticamāk, tiks parādīta kļūda 502 Bad Gateway. To var izraisīt nepareizi konfigurētas UNIX ligzdas atļaujas vai arī sarežģītākas problēmas, kas saistītas ar piekļuves kontroli SELinux.

Nginx kļūdu žurnālā var redzēt Ŕādu rindiņu:

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"

Ja pārbaudÄ«sim Gunicorn tieÅ”i, mēs saņemsim tukÅ”u atbildi.

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

Noskaidrosim, kāpēc tas notiek. Atverot žurnālu, visticamāk, redzēsit, ka problēma ir saistÄ«ta ar SELinux. Tā kā mēs darbinām dēmonu, kuram nav izveidota politika, tas ir atzÄ«mēts kā init_t. PārbaudÄ«sim Å”o teoriju praksē.

sudo setenforce 0

Tas viss var izraisÄ«t kritiku un asiņu asaras, taču tas ir tikai prototipa atkļūdoÅ”ana. Atspējosim pārbaudi, lai pārliecinātos, ka tā ir problēma, un pēc tam visu atgriezÄ«sim savās vietās.

Atsvaidzinot lapu pārlūkprogrammā vai atkārtoti palaižot mūsu curl komandu, varat redzēt Django testa lapu.

Tātad, pārliecinājuÅ”ies, ka viss darbojas un vairs nav atļauju problēmu, mēs atkal iespējojam SELinux.

sudo setenforce 1

Å eit es nerunāŔu par audit2allow vai uz brÄ«dinājumiem balstÄ«tu politiku izveidi, izmantojot sepolgen, jo paÅ”laik nav Ä«stas Django lietojumprogrammas, tāpēc nav pilnÄ«gas kartes par to, kam Gunicorn varētu vēlēties piekļūt un kam tai vajadzētu liegt piekļuvi. Tāpēc ir nepiecieÅ”ams, lai SELinux darbotos, lai aizsargātu sistēmu, vienlaikus ļaujot lietojumprogrammai darboties un atstāt ziņojumus audita žurnālā, lai pēc tam no tiem varētu izveidot faktisko politiku.

AtļaujoÅ”o domēnu norādÄ«Å”ana

Ne visi ir dzirdējuÅ”i par atļautajiem domēniem SELinux, taču tie nav nekas jauns. Daudzi pat strādāja ar viņiem, pat neapzinoties. Kad politika tiek izveidota, pamatojoties uz audita ziņojumiem, izveidotā politika atspoguļo atrisināto domēnu. Mēģināsim izveidot vienkārÅ”u atļauju izsniegÅ”anas politiku.

Lai izveidotu konkrētu atļauto domēnu Gunicorn, jums ir nepiecieÅ”ama sava veida politika, kā arÄ« jāatzÄ«mē atbilstoÅ”i faili. Turklāt ir nepiecieÅ”ami instrumenti, lai izveidotu jaunas politikas.

sudo yum install selinux-policy-devel

Atļauto domēnu mehānisms ir lielisks rÄ«ks problēmu identificÄ“Å”anai, Ä«paÅ”i, ja runa ir par pielāgotu lietojumprogrammu vai lietojumprogrammām, kas tiek piegādātas bez jau izveidotām politikām. Å ajā gadÄ«jumā Gunicorn atļautā domēna politika bÅ«s pēc iespējas vienkārŔāka ā€” deklarējiet galveno tipu (gunicorn_t), deklarējiet veidu, ko izmantosim, lai atzÄ«mētu vairākus izpildāmos failus (gunicorn_exec_t), un pēc tam iestatiet pāreju, lai sistēma pareizi atzÄ«mētu. darbojas procesi. Pēdējā rindā politika tiek iestatÄ«ta kā iespējota pēc noklusējuma tās ielādes laikā.

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;

Varat apkopot Å”o politikas failu un pievienot to savai sistēmai.

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

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

Pārbaudīsim, vai SELinux nebloķē kaut ko citu, nevis to, kam piekļūst mūsu nezināmais dēmons.

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 neļauj Nginx ierakstÄ«t datus UNIX ligzdā, ko izmanto Gunicorn. Parasti Ŕādos gadÄ«jumos politika sāk mainÄ«ties, taču priekŔā ir citi izaicinājumi. Varat arÄ« mainÄ«t domēna iestatÄ«jumus no ierobežojuma domēna uz atļauju domēnu. Tagad pārvietosim httpd_t uz atļauju domēnu. Tādējādi Nginx tiks nodroÅ”ināta nepiecieÅ”amā piekļuve, un mēs varēsim turpināt turpmāko atkļūdoÅ”anas darbu.

sudo semanage permissive -a httpd_t

Tātad, kad jums ir izdevies saglabāt SELinux aizsardzÄ«bu (jums tieŔām nevajadzētu atstāt SELinux projektu ierobežotā režīmā) un atļauju domēni ir ielādēti, jums ir jāizdomā, kas tieÅ”i ir jāatzÄ«mē kā gunicorn_exec_t, lai viss darbotos pareizi. atkal. Mēģināsim apmeklēt vietni, lai redzētu jaunus ziņojumus par piekļuves ierobežojumiem.

sudo ausearch -m AVC -c gunicorn

JÅ«s redzēsit daudz ziņojumu, kas satur ā€œcomm="gunicorn", kas veic dažādas darbÄ«bas failos, kas atrodas /srv/djangoapp, tāpēc Ŕī acÄ«mredzami ir viena no komandām, ko ir vērts atzÄ«mēt.

Bet papildus tiek parādÄ«ts Ŕāds ziņojums:

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

Ja skatāties uz gunicorn pakalpojuma statusu vai palaižat komandu ps, jÅ«s neredzēsit nevienu darbÄ«gu procesu. Å Ä·iet, ka gunicorn mēģina piekļūt Python tulkam mÅ«su virtualenv vidē, iespējams, lai palaistu darbinieku skriptus. Tagad atzÄ«mēsim Å”os divus izpildāmos failus un pārbaudÄ«sim, vai varam atvērt mÅ«su Django testa lapu.

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

Lai varētu atlasÄ«t jauno atzÄ«mi, ir jārestartē lielradža pakalpojums. Varat to nekavējoties restartēt vai apturēt pakalpojumu un ļaut ligzdai to palaist, atverot vietni pārlÅ«kprogrammā. Pārbaudiet, vai procesi ir saņēmuÅ”i pareizās etiÄ·etes, izmantojot ps.

ps -efZ | grep gunicorn

Neaizmirstiet vēlāk izveidot normālu SELinux politiku!

Ja tagad aplÅ«kojat AVC ziņojumus, pēdējā ziņojumā ir permissive=1 visam, kas saistÄ«ts ar lietojumprogrammu, un permissive=0 pārējai sistēmai. Ja saprotat, kāda veida piekļuve nepiecieÅ”ama reālai lietojumprogrammai, varat ātri atrast labāko veidu, kā atrisināt Ŕādas problēmas. Bet lÄ«dz tam vislabāk ir nodroÅ”ināt sistēmas droŔību un iegÅ«t skaidru, izmantojamu Django projekta auditu.

sudo ausearch -m AVC

Notika!

Ir parādÄ«jies strādājoÅ”s Django projekts ar priekÅ”galu, kura pamatā ir Nginx un Gunicorn WSGI. Mēs konfigurējām Python 3 un PostgreSQL 10 no RHEL 8 Beta krātuvēm. Tagad varat virzÄ«ties uz priekÅ”u un izveidot (vai vienkārÅ”i izvietot) Django lietojumprogrammas vai izpētÄ«t citus pieejamos rÄ«kus RHEL 8 Beta, lai automatizētu konfigurācijas procesu, uzlabotu veiktspēju vai pat konteinerizētu Å”o konfigurāciju.

Avots: www.habr.com

Pievieno komentāru