Atelye RHEL 8 Beta: Konstwi aplikasyon entènèt k ap travay

RHEL 8 Beta ofri devlopè anpil nouvo karakteristik, lis la ki ka pran paj, sepandan, aprann nouvo bagay toujou pi bon nan pratik, kidonk pi ba a nou ofri yon atelye sou aktyèlman kreye yon enfrastrikti aplikasyon ki baze sou Red Hat Enterprise Linux 8 Beta.

Atelye RHEL 8 Beta: Konstwi aplikasyon entènèt k ap travay

Ann pran Python, yon langaj pwogram popilè nan mitan devlopè yo, kòm yon baz, yon konbinezon Django ak PostgreSQL, yon konbinezon jistis komen pou kreye aplikasyon, ak konfigirasyon RHEL 8 Beta pou travay avèk yo. Lè sa a, nou pral ajoute yon koup plis engredyan (ki pa klase).

Anviwònman tès la pral chanje, paske li se enteresan yo eksplore posiblite yo nan automatisation, travay ak resipyan ak ap eseye anviwònman ak sèvè miltip. Pou kòmanse ak yon nouvo pwojè, ou ka kòmanse pa kreye yon ti pwototip senp alamen pou ou ka wè egzakteman sa ki bezwen rive ak ki jan li kominike, epi ale nan otomatize ak kreye konfigirasyon pi konplèks. Jodi a nou ap pale de kreyasyon yon pwototip konsa.

Ann kòmanse pa deplwaye imaj RHEL 8 Beta VM la. Ou ka enstale yon machin vityèl nan grafouyen, oswa itilize imaj envite KVM ki disponib ak abònman Beta ou. Lè w ap itilize yon imaj envite, w ap bezwen konfigirasyon yon CD vityèl ki pral genyen metadata ak done itilizatè pou inisyalizasyon nwaj (cloud-init). Ou pa bezwen fè anyen espesyal ak estrikti disk la oswa pakè ki disponib; nenpòt konfigirasyon ap fè.

Ann pran yon gade pi pre nan pwosesis la tout antye.

Enstale Django

Avèk vèsyon an dernye nan Django, w ap bezwen yon anviwònman vityèl (virtualenv) ak Python 3.5 oswa pita. Nan nòt Beta yo ou ka wè ke Python 3.6 ki disponib, ann tcheke si sa a se tout bon ka a:

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

Red Hat aktivman itilize Python kòm yon bwat zouti sistèm nan RHEL, kidonk poukisa rezilta sa a?

Reyalite a se ke anpil devlopè Python yo toujou kontanple tranzisyon an soti nan Python 2 a Python 2, pandan y ap Python 3 li menm se anba devlopman aktif, ak plis ak plis nouvo vèsyon yo toujou ap parèt. Se poutèt sa, pou satisfè bezwen pou zouti sistèm ki estab pandan y ap ofri itilizatè yo aksè a divès nouvo vèsyon Python, sistèm Python te deplase nan yon nouvo pake epi li te bay kapasite pou enstale tou de Python 2.7 ak 3.6. Ou ka jwenn plis enfòmasyon sou chanjman yo ak poukisa yo te fè yo nan piblikasyon an Blog Langdon White la (Langdon Blan).

Se konsa, pou jwenn travay Python, ou sèlman bezwen enstale de pakè, ak python3-pip enkli kòm yon depandans.

sudo yum install python36 python3-virtualenv

Poukisa nou pa itilize apèl modil dirèk jan Langdon sijere epi enstale pip3? Kenbe nan tèt ou automatisation k ap vini an, li konnen ke Ansible pral mande pou pip enstale yo kouri, depi modil la pip pa sipòte virtualenvs ak yon ègzekutabl pip koutim.

Avèk yon entèprèt python3 k ap travay a dispozisyon ou, ou ka kontinye ak pwosesis enstalasyon Django epi gen yon sistèm k ap travay ansanm ak lòt konpozan nou yo. Gen anpil opsyon aplikasyon ki disponib sou entènèt la. Gen yon vèsyon prezante isit la, men itilizatè yo ka itilize pwòp pwosesis yo.

Nou pral enstale vèsyon yo PostgreSQL ak Nginx ki disponib nan RHEL 8 pa default lè l sèvi avèk Yum.

sudo yum install nginx postgresql-server

PostgreSQL pral mande psycopg2, men li bezwen disponib sèlman nan yon anviwònman virtualenv, kidonk nou pral enstale li lè l sèvi avèk pip3 ansanm ak Django ak Gunicorn. Men, anvan nou bezwen mete kanpe virtualenv.

Gen toujou anpil deba sou sijè a nan chwazi bon kote pou enstale pwojè Django, men lè w gen dout, ou ka toujou ale nan Linux Filesystem Hierarchy Standard. Espesyalman, FHS di ke /srv yo itilize pou: "sere done espesifik lame a—done ke sistèm nan pwodui, tankou done sèvè entènèt ak scripts, done ki estoke sou sèvè FTP, ak depo sistèm kontwòl." vèsyon (ki parèt nan FHS -2.3 an 2004)."

Sa a se egzakteman ka nou an, kidonk nou mete tout sa nou bezwen nan / srv, ki se posede pa itilizatè aplikasyon nou an (nwaj-itilizatè).

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

Mete kanpe PostgreSQL ak Django se fasil: kreye yon baz done, kreye yon itilizatè, konfigirasyon otorizasyon. Youn nan bagay ou dwe kenbe nan tèt ou lè okòmansman enstale PostgreSQL se script postgresql-setup ki enstale ak pake a postgresql-sèvè. Script sa a ede w fè travay debaz ki asosye ak administrasyon gwoup baz done, tankou inisyalizasyon gwoup oswa pwosesis ajou. Pou konfigirasyon yon nouvo egzanp PostgreSQL sou yon sistèm RHEL, nou bezwen kouri lòd la:

sudo /usr/bin/postgresql-setup -initdb

Lè sa a, ou ka kòmanse PostgreSQL lè l sèvi avèk systemd, kreye yon baz done, epi mete yon pwojè nan Django. Sonje rekòmanse PostgreSQL apre w fin fè chanjman nan dosye konfigirasyon otantifikasyon kliyan an (anjeneral pg_hba.conf) pou konfigirasyon depo modpas pou itilizatè aplikasyon an. Si w rankontre lòt difikilte, asire w ke w chanje paramèt IPv4 ak IPv6 nan fichye 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

Nan dosye /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

Nan dosye /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 }}',
   }
}

Apre konfigirasyon fichye a settings.py nan pwojè a ak mete kanpe konfigirasyon baz done a, ou ka kòmanse sèvè devlopman an asire w ke tout bagay ap mache. Apre kòmanse sèvè devlopman an, li se yon bon lide yo kreye yon itilizatè admin yo nan lòd yo teste koneksyon an nan baz done a.

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

WSGI? Wai?

Sèvè devlopman an itil pou fè tès, men pou w kouri aplikasyon an ou dwe konfigirasyon sèvè ki apwopriye a ak proxy pou entèfas Web Server Gateway (WSGI). Gen plizyè konbinezon komen, pou egzanp, Apache HTTPD ak uWSGI oswa Nginx ak Gunicorn.

Travay Web Server Gateway Interface se pou voye demann ki soti nan sèvè entènèt la nan kad wèb Python la. WSGI se yon relik nan sot pase a terib lè motè CGI yo te alantou, ak jodi a WSGI se estanda defakto a, kèlkeswa sèvè wèb la oswa kad Python yo itilize. Men, malgre itilizasyon toupatou li yo, toujou gen anpil nuans lè w ap travay ak kad sa yo, ak anpil chwa. Nan ka sa a, nou pral eseye etabli entèraksyon ant Gunicorn ak Nginx atravè yon priz.

Depi tou de konpozan sa yo enstale sou menm sèvè a, ann eseye itilize yon priz UNIX olye de yon priz rezo. Depi kominikasyon mande pou yon priz nan nenpòt ka, ann eseye fè yon lòt etap ak konfigirasyon deklanchman priz pou Gunicorn atravè systemd.

Pwosesis pou kreye sèvis aktive priz se byen senp. Premyèman, yo kreye yon fichye inite ki gen yon direktiv ListenStream ki montre pwen kote yo pral kreye priz UNIX la, Lè sa a, yon fichye inite pou sèvis la nan ki direktiv Requires la pral montre dosye inite priz la. Lè sa a, nan dosye inite sèvis la, tout sa ki rete se rele Gunicorn soti nan anviwònman an vityèl epi kreye yon obligatwa WSGI pou priz la UNIX ak aplikasyon an Django.

Men kèk egzanp dosye inite ke ou ka itilize kòm yon baz. Premye nou mete priz la.

[Unit]
Description=Gunicorn WSGI socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target

Koulye a, ou bezwen konfigirasyon demon an 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

Pou Nginx, li se yon kesyon senp pou kreye fichye konfigirasyon prokurasyon ak mete kanpe yon anyè pou estoke kontni estatik si w ap itilize youn. Nan RHEL, dosye konfigirasyon Nginx yo sitiye nan /etc/nginx/conf.d. Ou ka kopye egzanp sa a nan dosye /etc/nginx/conf.d/default.conf epi kòmanse sèvis la. Asire w ke ou mete server_name pou matche ak non lame ou.

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

Kòmanse priz la Gunicorn ak Nginx lè l sèvi avèk systemd epi w ap pare yo kòmanse tès la.

Move erè Gateway?

Si ou antre adrès la nan navigatè ou a, ou pral gen plis chans resevwa yon erè 502 Bad Gateway. Li ka koze pa otorizasyon socket UNIX ki mal configuré, oswa li ka akòz pwoblèm ki pi konplèks ki gen rapò ak kontwòl aksè nan SELinux.

Nan jounal erè nginx ou ka wè yon liy tankou sa a:

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"

Si nou teste Gunicorn dirèkteman, n ap jwenn yon repons vid.

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

Ann chèche konnen poukisa sa rive. Si ou louvri boutèy la, ou pral gen plis chans wè ke pwoblèm nan gen rapò ak SELinux. Depi nou ap kouri yon demon pou ki pa gen okenn politik ki te kreye, li make kòm init_t. Ann teste teyori sa a an pratik.

sudo setenforce 0

Tout bagay sa a ka lakòz kritik ak dlo nan je nan san, men sa a se jis debogaj pwototip la. Ann enfim chèk la jis asire w ke sa a se pwoblèm nan, apre sa nou pral retounen tout bagay tounen nan plas li.

Lè w rafrechi paj la nan navigatè a oswa lè w refè kòmandman boukl nou an, ou ka wè paj tès Django a.

Se konsa, nou te asire w ke tout bagay ap mache epi pa gen plis pwoblèm pèmisyon, nou pèmèt SELinux ankò.

sudo setenforce 1

Mwen pa pral pale sou audit2allow oswa kreye règleman ki baze sou alèt ak sepolgen isit la, paske pa gen okenn aplikasyon aktyèl Django nan moman sa a, kidonk pa gen okenn kat konplè sou sa Gunicorn ta ka vle jwenn aksè ak sa li ta dwe refize aksè a. Se poutèt sa, li nesesè pou kenbe SELinux kouri pou pwoteje sistèm nan, pandan y ap pèmèt aplikasyon an kouri epi kite mesaj nan boutèy odit la pou ke politik aktyèl la ka kreye nan men yo.

Espesifye domèn tolerans

Se pa tout moun ki te tande pale de domèn pèmèt nan SELinux, men yo pa gen anyen nouvo. Anpil menm te travay ak yo san yo pa menm reyalize li. Lè yo kreye yon politik ki baze sou mesaj odit, politik la kreye reprezante domèn ki rezoud. Ann eseye kreye yon senp politik pèmi.

Pou kreye yon domèn espesifik ki pèmèt pou Gunicorn, ou bezwen kèk kalite politik, epi ou bezwen tou make dosye ki apwopriye yo. Anplis de sa, zouti yo bezwen rasanble nouvo politik.

sudo yum install selinux-policy-devel

Mekanis domèn yo pèmèt yo se yon bon zouti pou idantifye pwoblèm, sitou lè li rive nan yon aplikasyon koutim oswa aplikasyon ki voye san règleman yo deja kreye. Nan ka sa a, politik domèn pèmèt pou Gunicorn yo pral senp ke posib - deklare yon kalite prensipal (gunicorn_t), deklare yon kalite nou pral itilize pou make plizyè ègzèkutabl (gunicorn_exec_t), ak Lè sa a, mete yon tranzisyon pou sistèm kòrèkteman make. kouri pwosesis. Dènye liy lan mete politik la kòm aktive pa default nan moman li chaje.

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;

Ou ka konpile dosye politik sa a epi ajoute li nan sistèm ou an.

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

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

Ann tcheke pou wè si SELinux bloke yon lòt bagay pase sa demon enkoni nou an ap jwenn aksè.

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 anpeche Nginx ekri done nan priz UNIX ki itilize pa Gunicorn. Tipikman, nan ka sa yo, politik yo kòmanse chanje, men gen lòt defi devan yo. Ou kapab tou chanje anviwònman yo domèn soti nan yon domèn restriksyon nan yon domèn pèmisyon. Koulye a, ann deplase httpd_t nan domèn otorizasyon yo. Sa a pral bay Nginx aksè ki nesesè epi nou ka kontinye ak plis travay debogaj.

sudo semanage permissive -a httpd_t

Se konsa, yon fwa ou te jere kenbe SELinux pwoteje (ou reyèlman pa ta dwe kite yon pwojè SELinux nan mòd restriksyon) ak domèn pèmisyon yo chaje, ou bezwen konnen ki sa egzakteman bezwen make kòm gunicorn_exec_t jwenn tout bagay travay byen. ankò. Ann eseye vizite sit entènèt la pou wè nouvo mesaj sou restriksyon aksè.

sudo ausearch -m AVC -c gunicorn

Ou pral wè yon anpil nan mesaj ki gen 'comm="gunicorn"' ki fè divès bagay sou dosye nan /srv/djangoapp, kidonk sa a se evidamman youn nan kòmandman yo vo tabli.

Men, anplis de sa, yon mesaj tankou sa a parèt:

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

Si w gade estati sèvis gunicorn oswa kouri lòd ps la, ou p ap wè okenn pwosesis k ap kouri. Li sanble ke gunicorn ap eseye jwenn aksè nan entèprèt Python nan anviwònman virtualenv nou an, pètèt pou kouri scripts travayè yo. Se konsa, kounye a ann make de dosye ègzèkutabl sa yo epi tcheke si nou ka louvri paj tès Django nou an.

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

Sèvis gunicorn la pral bezwen rekòmanse anvan yo ka chwazi nouvo tag la. Ou ka rekòmanse li imedyatman oswa sispann sèvis la epi kite priz la kòmanse li lè ou louvri sit la nan navigatè a. Verifye ke pwosesis yo te resevwa etikèt ki kòrèk lè l sèvi avèk ps.

ps -efZ | grep gunicorn

Pa bliye kreye yon politik SELinux nòmal pita!

Si w gade mesaj AVC yo kounye a, dènye mesaj la gen permissive=1 pou tout bagay ki gen rapò ak aplikasyon an, ak permissive=0 pou rès sistèm nan. Si ou konprann ki kalite aksè yon aplikasyon reyèl bezwen, ou ka byen vit jwenn pi bon fason pou rezoud pwoblèm sa yo. Men, jiska lè sa a, li pi bon pou kenbe sistèm nan an sekirite epi jwenn yon odit klè, ka itilize nan pwojè Django a.

sudo ausearch -m AVC

Sa te pase!

Yon pwojè Django k ap travay parèt ak yon entèfas ki baze sou Nginx ak Gunicorn WSGI. Nou konfigirasyon Python 3 ak PostgreSQL 10 soti nan depo RHEL 8 Beta yo. Koulye a, ou ka avanse pou pi devan epi kreye (oswa tou senpleman deplwaye) aplikasyon Django oswa eksplore lòt zouti ki disponib nan RHEL 8 Beta pou otomatize pwosesis konfigirasyon an, amelyore pèfòmans, oswa menm kontenè konfigirasyon sa a.

Sous: www.habr.com

Add nouvo kòmantè