เวิร์กช็อป RHEL 8 เบต้า: การสร้างแอปพลิเคชันเว็บที่ใช้งานได้

RHEL 8 Beta นำเสนอคุณสมบัติใหม่ๆ มากมายแก่นักพัฒนา ซึ่งรายการอาจต้องใช้เวลาหลายหน้า อย่างไรก็ตาม การเรียนรู้สิ่งใหม่ๆ ในทางปฏิบัติย่อมดีกว่าเสมอ ดังนั้นด้านล่างนี้เราขอเสนอเวิร์กช็อปเกี่ยวกับการสร้างโครงสร้างพื้นฐานแอปพลิเคชันจริงโดยใช้ Red Hat Enterprise Linux 8 Beta

เวิร์กช็อป RHEL 8 เบต้า: การสร้างแอปพลิเคชันเว็บที่ใช้งานได้

ลองใช้ Python ซึ่งเป็นภาษาโปรแกรมยอดนิยมในหมู่นักพัฒนาเป็นพื้นฐานของการรวมกันของ Django และ PostgreSQL ซึ่งเป็นการรวมกันที่ค่อนข้างธรรมดาสำหรับการสร้างแอปพลิเคชันและกำหนดค่า RHEL 8 Beta ให้ทำงานร่วมกับพวกเขา จากนั้นเราจะเพิ่มส่วนผสมอีกสองสามอย่าง (ไม่จำแนกประเภท)

สภาพแวดล้อมการทดสอบจะเปลี่ยนไป เนื่องจากเป็นเรื่องน่าสนใจที่จะสำรวจความเป็นไปได้ของระบบอัตโนมัติ การทำงานกับคอนเทนเนอร์ และการลองใช้สภาพแวดล้อมกับเซิร์ฟเวอร์หลายเครื่อง ในการเริ่มต้นโปรเจ็กต์ใหม่ คุณสามารถเริ่มต้นด้วยการสร้างต้นแบบขนาดเล็กที่เรียบง่ายด้วยมือ เพื่อให้คุณสามารถเห็นได้อย่างแน่ชัดว่าต้องเกิดอะไรขึ้นและจะโต้ตอบอย่างไร จากนั้นจึงก้าวไปสู่การทำให้เป็นอัตโนมัติและสร้างการกำหนดค่าที่ซับซ้อนมากขึ้น วันนี้เรากำลังพูดถึงการสร้างต้นแบบดังกล่าว

มาเริ่มด้วยการปรับใช้อิมเมจ RHEL 8 Beta VM คุณสามารถติดตั้งเครื่องเสมือนตั้งแต่เริ่มต้น หรือใช้อิมเมจเกสต์ KVM ที่มาพร้อมกับการสมัครสมาชิกเบต้าของคุณ เมื่อใช้อิมเมจแขก คุณจะต้องกำหนดค่าซีดีเสมือนที่จะมีข้อมูลเมตาและข้อมูลผู้ใช้สำหรับการเริ่มต้นระบบคลาวด์ (cloud-init) คุณไม่จำเป็นต้องดำเนินการใดๆ เป็นพิเศษกับโครงสร้างดิสก์หรือแพ็กเกจที่มีอยู่ การกำหนดค่าใดๆ ก็ตามจะทำได้

มาดูกระบวนการทั้งหมดกันดีกว่า

การติดตั้งจังโก้

ด้วย Django เวอร์ชันใหม่ล่าสุด คุณจะต้องมีสภาพแวดล้อมเสมือน (virtualenv) ที่มี Python 3.5 หรือใหม่กว่า ในบันทึกเบต้า คุณจะเห็นว่า Python 3.6 พร้อมใช้งานแล้ว มาตรวจสอบว่าเป็นกรณีนี้จริงหรือไม่:

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

Red Hat ใช้ Python เป็นชุดเครื่องมือระบบใน RHEL อย่างแข็งขัน แล้วเหตุใดจึงได้ผลลัพธ์นี้

ความจริงก็คือนักพัฒนา Python จำนวนมากยังคงใคร่ครวญถึงการเปลี่ยนจาก Python 2 เป็น Python 2 ในขณะที่ Python 3 เองก็อยู่ระหว่างการพัฒนาและมีเวอร์ชันใหม่ ๆ ปรากฏขึ้นอย่างต่อเนื่อง ดังนั้น เพื่อตอบสนองความต้องการเครื่องมือระบบที่เสถียรในขณะที่ให้ผู้ใช้เข้าถึง Python เวอร์ชันใหม่ต่างๆ ระบบ Python จึงถูกย้ายไปยังแพ็คเกจใหม่และจัดเตรียมความสามารถในการติดตั้งทั้ง Python 2.7 และ 3.6 ข้อมูลเพิ่มเติมเกี่ยวกับการเปลี่ยนแปลงและเหตุผลในการเปลี่ยนแปลงสามารถดูได้จากเอกสารเผยแพร่ใน บล็อกของแลงดอน ไวท์ (แลงดอน ไวท์).

ดังนั้นเพื่อให้ Python ใช้งานได้ คุณจะต้องติดตั้งแพ็คเกจสองแพ็คเกจเท่านั้น โดยมี python3-pip รวมอยู่ด้วย

sudo yum install python36 python3-virtualenv

ทำไมไม่ใช้การเรียกโมดูลโดยตรงตามที่ Langdon แนะนำและติดตั้ง pip3 เมื่อคำนึงถึงระบบอัตโนมัติที่กำลังจะมาถึง เป็นที่ทราบกันว่า Ansible จะต้องติดตั้ง pip เพื่อให้ทำงานได้ เนื่องจากโมดูล pip ไม่รองรับ virtualenvs ที่มีการปฏิบัติการ pip แบบกำหนดเอง

ด้วยล่าม python3 ที่ใช้งานได้ คุณสามารถดำเนินการตามกระบวนการติดตั้ง Django ต่อไปและมีระบบที่ใช้งานได้พร้อมกับส่วนประกอบอื่นๆ ของเรา มีตัวเลือกการใช้งานมากมายบนอินเทอร์เน็ต มีการนำเสนอเวอร์ชันหนึ่งไว้ที่นี่ แต่ผู้ใช้สามารถใช้กระบวนการของตนเองได้

เราจะติดตั้งเวอร์ชัน PostgreSQL และ Nginx ที่มีใน RHEL 8 เป็นค่าเริ่มต้นโดยใช้ Yum

sudo yum install nginx postgresql-server

PostgreSQL จะต้องใช้ psycopg2 แต่ต้องพร้อมใช้งานในสภาพแวดล้อม virtualenv เท่านั้น ดังนั้นเราจะติดตั้งโดยใช้ pip3 ร่วมกับ Django และ Gunicorn แต่ก่อนอื่นเราต้องตั้งค่า virtualenv

มีการถกเถียงกันมากมายในหัวข้อการเลือกสถานที่ที่เหมาะสมในการติดตั้งโปรเจ็กต์ Django แต่เมื่อมีข้อสงสัย คุณสามารถเปลี่ยนไปใช้ Linux Filesystem Hierarchy Standard ได้ตลอดเวลา โดยเฉพาะอย่างยิ่ง FHS ระบุว่า /srv ใช้เพื่อ: “จัดเก็บข้อมูลเฉพาะโฮสต์—ข้อมูลที่ระบบสร้างขึ้น เช่น ข้อมูลเว็บเซิร์ฟเวอร์และสคริปต์ ข้อมูลที่จัดเก็บบนเซิร์ฟเวอร์ FTP และที่เก็บข้อมูลระบบควบคุม” เวอร์ชัน (ปรากฏใน FHS -2.3 ในปี พ.ศ. 2004)"

นี่เป็นกรณีของเราทุกประการ ดังนั้นเราจึงใส่ทุกสิ่งที่เราต้องการลงใน /srv ซึ่งเป็นเจ้าของโดยผู้ใช้แอปพลิเคชันของเรา (ผู้ใช้ระบบคลาวด์)

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 และ Django เป็นเรื่องง่าย: สร้างฐานข้อมูล สร้างผู้ใช้ กำหนดค่าสิทธิ์ สิ่งหนึ่งที่ควรคำนึงถึงเมื่อเริ่มติดตั้ง PostgreSQL คือสคริปต์การตั้งค่า postgresql ที่ติดตั้งพร้อมกับแพ็คเกจ postgresql-server สคริปต์นี้ช่วยให้คุณทำงานพื้นฐานที่เกี่ยวข้องกับการดูแลคลัสเตอร์ฐานข้อมูล เช่น การเริ่มต้นคลัสเตอร์หรือกระบวนการอัปเกรด ในการกำหนดค่าอินสแตนซ์ PostgreSQL ใหม่บนระบบ RHEL เราจำเป็นต้องเรียกใช้คำสั่ง:

sudo /usr/bin/postgresql-setup -initdb

จากนั้นคุณสามารถเริ่ม PostgreSQL โดยใช้ systemd สร้างฐานข้อมูล และตั้งค่าโปรเจ็กต์ใน Django อย่าลืมรีสตาร์ท PostgreSQL หลังจากทำการเปลี่ยนแปลงไฟล์การกำหนดค่าการตรวจสอบสิทธิ์ไคลเอ็นต์ (โดยปกติคือ pg_hba.conf) เพื่อกำหนดค่าที่เก็บข้อมูลรหัสผ่านสำหรับผู้ใช้แอปพลิเคชัน หากคุณพบปัญหาอื่นๆ ตรวจสอบให้แน่ใจว่าได้เปลี่ยนการตั้งค่า IPv4 และ IPv6 ในไฟล์ 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

ในไฟล์ /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

ในไฟล์ /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 }}',
   }
}

หลังจากกำหนดค่าไฟล์ settings.py ในโปรเจ็กต์และตั้งค่าการกำหนดค่าฐานข้อมูลแล้ว คุณสามารถเริ่มเซิร์ฟเวอร์การพัฒนาเพื่อให้แน่ใจว่าทุกอย่างทำงานได้ หลังจากเริ่มต้นเซิร์ฟเวอร์การพัฒนาแล้ว เป็นความคิดที่ดีที่จะสร้างผู้ใช้ที่เป็นผู้ดูแลระบบเพื่อทดสอบการเชื่อมต่อกับฐานข้อมูล

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

WSGI? ไหวเหรอ?

เซิร์ฟเวอร์การพัฒนามีประโยชน์สำหรับการทดสอบ แต่ในการรันแอปพลิเคชัน คุณต้องกำหนดค่าเซิร์ฟเวอร์และพร็อกซีที่เหมาะสมสำหรับ Web Server Gateway Interface (WSGI) มีการผสมผสานร่วมกันหลายอย่าง เช่น Apache HTTPD กับ uWSGI หรือ Nginx กับ Gunicorn

งานของ Web Server Gateway Interface คือการส่งต่อคำขอจากเว็บเซิร์ฟเวอร์ไปยังเฟรมเวิร์กเว็บ Python WSGI เป็นมรดกตกทอดของอดีตอันเลวร้ายเมื่อมีกลไก CGI และในปัจจุบัน WSGI เป็นมาตรฐานโดยพฤตินัย โดยไม่คำนึงถึงเว็บเซิร์ฟเวอร์หรือเฟรมเวิร์ก Python ที่ใช้ แต่ถึงแม้จะมีการใช้งานอย่างแพร่หลาย แต่ก็ยังมีความแตกต่างมากมายเมื่อทำงานกับเฟรมเวิร์กเหล่านี้และมีตัวเลือกมากมาย ในกรณีนี้ เราจะพยายามสร้างการโต้ตอบระหว่าง Gunicorn และ Nginx ผ่านซ็อกเก็ต

เนื่องจากคอมโพเนนต์ทั้งสองนี้ได้รับการติดตั้งบนเซิร์ฟเวอร์เดียวกัน เราจึงลองใช้ซ็อกเก็ต UNIX แทนซ็อกเก็ตเครือข่าย เนื่องจากการสื่อสารจำเป็นต้องใช้ซ็อกเก็ตไม่ว่าในกรณีใด เราจึงพยายามดำเนินการอีกหนึ่งขั้นตอนและกำหนดค่าการเปิดใช้งานซ็อกเก็ตสำหรับ Gunicorn ผ่าน systemd

กระบวนการสร้างบริการที่เปิดใช้งานซ็อกเก็ตนั้นค่อนข้างง่าย ขั้นแรก ไฟล์หน่วยจะถูกสร้างขึ้นโดยมีคำสั่ง ListenStream ที่ชี้ไปยังจุดที่ซ็อกเก็ต UNIX จะถูกสร้างขึ้น จากนั้นไฟล์หน่วยสำหรับบริการที่คำสั่ง Requires จะชี้ไปที่ไฟล์หน่วยซ็อกเก็ต จากนั้นในไฟล์หน่วยบริการ สิ่งที่เหลืออยู่คือการเรียก Gunicorn จากสภาพแวดล้อมเสมือนและสร้างการเชื่อมโยง WSGI สำหรับซ็อกเก็ต UNIX และแอปพลิเคชัน Django

ต่อไปนี้เป็นตัวอย่างไฟล์หน่วยที่คุณสามารถใช้เป็นพื้นฐานได้ ก่อนอื่นเราตั้งค่าซ็อกเก็ต

[Unit]
Description=Gunicorn WSGI socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target

ตอนนี้คุณต้องกำหนดค่า Gunicorn daemon

[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 การสร้างไฟล์การกำหนดค่าพร็อกซีและการตั้งค่าไดเร็กทอรีเพื่อจัดเก็บเนื้อหาแบบคงที่เป็นเรื่องง่ายหากคุณใช้งานอยู่ ใน RHEL ไฟล์การกำหนดค่า Nginx จะอยู่ใน /etc/nginx/conf.d คุณสามารถคัดลอกตัวอย่างต่อไปนี้ลงในไฟล์ /etc/nginx/conf.d/default.conf และเริ่มบริการ ตรวจสอบให้แน่ใจว่าได้ตั้งค่า server_name ให้ตรงกับชื่อโฮสต์ของคุณ

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

เริ่มซ็อกเก็ต Gunicorn และ Nginx โดยใช้ systemd และคุณพร้อมที่จะเริ่มการทดสอบแล้ว

ข้อผิดพลาดเกตเวย์ไม่ถูกต้อง?

หากคุณป้อนที่อยู่ในเบราว์เซอร์ของคุณ คุณมักจะได้รับข้อผิดพลาด 502 Bad Gateway อาจเกิดจากสิทธิ์ซ็อกเก็ต UNIX ที่กำหนดค่าไม่ถูกต้อง หรืออาจเป็นเพราะปัญหาที่ซับซ้อนมากขึ้นที่เกี่ยวข้องกับการควบคุมการเข้าถึงใน SELinux

ในบันทึกข้อผิดพลาด nginx คุณจะเห็นบรรทัดดังนี้:

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 โดยตรง เราก็จะได้คำตอบที่ว่างเปล่า

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

ลองหาสาเหตุว่าทำไมสิ่งนี้จึงเกิดขึ้น หากคุณเปิดบันทึก คุณมักจะเห็นว่าปัญหาเกี่ยวข้องกับ SELinux เนื่องจากเรากำลังเรียกใช้ daemon ที่ไม่มีการสร้างนโยบาย จึงถูกทำเครื่องหมายเป็น init_t เรามาทดสอบทฤษฎีนี้ในทางปฏิบัติกันดีกว่า

sudo setenforce 0

ทั้งหมดนี้อาจทำให้เกิดการวิพากษ์วิจารณ์และน้ำตานองเลือด แต่นี่เป็นเพียงการดีบักต้นแบบเท่านั้น เรามาปิดการใช้งานการตรวจสอบเพื่อให้แน่ใจว่านี่คือปัญหา หลังจากนั้นเราจะคืนทุกอย่างกลับไปที่เดิม

โดยการรีเฟรชเพจในเบราว์เซอร์หรือรันคำสั่ง curl อีกครั้ง คุณจะเห็นหน้าทดสอบ Django

ดังนั้น เพื่อให้แน่ใจว่าทุกอย่างใช้งานได้และไม่มีปัญหาเรื่องการอนุญาตอีกต่อไป เราจึงเปิดใช้งาน SELinux อีกครั้ง

sudo setenforce 1

ฉันจะไม่พูดถึง audit2allow หรือการสร้างนโยบายตามการแจ้งเตือนด้วย sepolgen ที่นี่ เนื่องจากไม่มีแอปพลิเคชัน Django จริงในขณะนี้ ดังนั้นจึงไม่มีแผนที่ที่สมบูรณ์ว่า Gunicorn ต้องการเข้าถึงอะไร และสิ่งใดที่ควรปฏิเสธการเข้าถึง ดังนั้นจึงจำเป็นต้องให้ SELinux ทำงานต่อไปเพื่อปกป้องระบบ ในขณะเดียวกันก็อนุญาตให้แอปพลิเคชันทำงานและฝากข้อความไว้ในบันทึกการตรวจสอบเพื่อให้สามารถสร้างนโยบายจริงได้

การระบุโดเมนที่อนุญาต

ไม่ใช่ทุกคนที่เคยได้ยินเกี่ยวกับโดเมนที่อนุญาตใน SELinux แต่ก็ไม่ใช่เรื่องใหม่ หลายคนถึงกับทำงานร่วมกับพวกเขาโดยไม่รู้ตัวด้วยซ้ำ เมื่อนโยบายถูกสร้างขึ้นตามข้อความการตรวจสอบ นโยบายที่สร้างขึ้นจะแสดงถึงโดเมนที่แก้ไขแล้ว เรามาลองสร้างนโยบายการอนุญาตง่ายๆ

ในการสร้างโดเมนที่ได้รับอนุญาตเฉพาะสำหรับ Gunicorn คุณต้องมีนโยบายบางประเภท และคุณต้องทำเครื่องหมายไฟล์ที่เหมาะสมด้วย นอกจากนี้ยังจำเป็นต้องมีเครื่องมือในการประกอบนโยบายใหม่

sudo yum install selinux-policy-devel

กลไกโดเมนที่อนุญาตเป็นเครื่องมือที่ยอดเยี่ยมสำหรับการระบุปัญหา โดยเฉพาะอย่างยิ่งเมื่อเป็นแอปพลิเคชันแบบกำหนดเองหรือแอปพลิเคชันที่จัดส่งโดยไม่ได้สร้างนโยบายไว้แล้ว ในกรณีนี้ นโยบายโดเมนที่อนุญาตสำหรับ Gunicorn จะง่ายที่สุดเท่าที่จะเป็นไปได้ - ประกาศประเภทหลัก (gunicorn_t) ประกาศประเภทที่เราจะใช้เพื่อทำเครื่องหมายไฟล์ปฏิบัติการหลายรายการ (gunicorn_exec_t) จากนั้นตั้งค่าการเปลี่ยนแปลงเพื่อให้ระบบทำเครื่องหมายอย่างถูกต้อง กระบวนการที่กำลังทำงานอยู่ บรรทัดสุดท้ายจะตั้งค่านโยบายเป็นเปิดใช้งานโดยค่าเริ่มต้น ณ เวลาที่โหลด

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;

คุณสามารถคอมไพล์ไฟล์นโยบายนี้และเพิ่มลงในระบบของคุณได้

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

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

เรามาตรวจสอบว่า SELinux กำลังบล็อกสิ่งอื่นนอกเหนือจากที่ daemon ที่ไม่รู้จักของเรากำลังเข้าถึงอยู่หรือไม่

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 ป้องกัน Nginx จากการเขียนข้อมูลไปยังซ็อกเก็ต UNIX ที่ Gunicorn ใช้ โดยปกติแล้ว ในกรณีเช่นนี้ นโยบายจะเริ่มมีการเปลี่ยนแปลง แต่ก็ยังมีความท้าทายอื่นๆ รออยู่ข้างหน้า คุณยังสามารถเปลี่ยนการตั้งค่าโดเมนจากโดเมนข้อจำกัดไปเป็นโดเมนสิทธิ์ได้ ตอนนี้เรามาย้าย httpd_t ไปยังโดเมนการอนุญาต สิ่งนี้จะทำให้ Nginx สามารถเข้าถึงที่จำเป็น และเราสามารถดำเนินการแก้ไขจุดบกพร่องต่อไปได้

sudo semanage permissive -a httpd_t

ดังนั้น เมื่อคุณจัดการเพื่อให้ SELinux ได้รับการปกป้องแล้ว (คุณไม่ควรปล่อยให้โปรเจ็กต์ SELinux อยู่ในโหมดจำกัด) และโดเมนการอนุญาตถูกโหลดแล้ว คุณจะต้องคิดให้แน่ชัดว่าต้องทำเครื่องหมายอะไรเป็น gunicorn_exec_t เพื่อให้ทุกอย่างทำงานได้อย่างถูกต้อง อีกครั้ง. ลองเยี่ยมชมเว็บไซต์เพื่อดูข้อความใหม่เกี่ยวกับการจำกัดการเข้าถึง

sudo ausearch -m AVC -c gunicorn

คุณจะเห็นข้อความจำนวนมากที่มี 'comm="gunicorn"' ซึ่งทำหน้าที่ต่างๆ กับไฟล์ใน /srv/djangoapp ดังนั้น นี่จึงเป็นคำสั่งหนึ่งที่คุ้มค่าแก่การแฟล็ก

แต่นอกเหนือจากนี้ ข้อความลักษณะนี้จะปรากฏขึ้น:

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 หรือเรียกใช้คำสั่ง ps คุณจะไม่เห็นกระบวนการที่ทำงานอยู่ ดูเหมือนว่า gunicorn กำลังพยายามเข้าถึงล่าม Python ในสภาพแวดล้อม virtualenv ของเรา ซึ่งอาจเรียกใช้สคริปต์ของผู้ปฏิบัติงานได้ ตอนนี้เรามาทำเครื่องหมายไฟล์ปฏิบัติการทั้งสองไฟล์นี้และตรวจสอบว่าเราสามารถเปิดหน้าทดสอบ Django ของเราได้หรือไม่

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

จะต้องเริ่มบริการ gunicorn ใหม่ก่อนจึงจะสามารถเลือกแท็กใหม่ได้ คุณสามารถรีสตาร์ทได้ทันทีหรือหยุดบริการและปล่อยให้ซ็อกเก็ตเริ่มทำงานเมื่อคุณเปิดไซต์ในเบราว์เซอร์ ตรวจสอบว่ากระบวนการได้รับฉลากที่ถูกต้องโดยใช้ PS

ps -efZ | grep gunicorn

อย่าลืมสร้างนโยบาย SELinux ปกติในภายหลัง!

หากคุณดูข้อความ AVC ในตอนนี้ ข้อความสุดท้ายประกอบด้วย permissive=1 สำหรับทุกสิ่งที่เกี่ยวข้องกับแอปพลิเคชัน และ permissive=0 สำหรับส่วนที่เหลือของระบบ หากคุณเข้าใจว่าแอปพลิเคชันจริงต้องการการเข้าถึงประเภทใด คุณจะพบวิธีที่ดีที่สุดเพื่อแก้ไขปัญหาดังกล่าวได้อย่างรวดเร็ว แต่จนกว่าจะถึงตอนนั้น ทางที่ดีที่สุดคือรักษาระบบให้ปลอดภัยและได้รับการตรวจสอบโปรเจ็กต์ Django ที่ชัดเจนและใช้งานได้

sudo ausearch -m AVC

เกิดขึ้น!

โครงการ Django ที่ใช้งานได้ปรากฏขึ้นพร้อมส่วนหน้าตาม Nginx และ Gunicorn WSGI เรากำหนดค่า Python 3 และ PostgreSQL 10 จากที่เก็บ RHEL 8 Beta ตอนนี้คุณสามารถก้าวไปข้างหน้าและสร้าง (หรือเพียงแค่ปรับใช้) แอปพลิเคชัน Django หรือสำรวจเครื่องมืออื่นๆ ที่มีอยู่ใน RHEL 8 Beta เพื่อทำให้กระบวนการกำหนดค่าเป็นแบบอัตโนมัติ ปรับปรุงประสิทธิภาพ หรือแม้แต่จัดคอนเทนเนอร์การกำหนดค่านี้

ที่มา: will.com

เพิ่มความคิดเห็น