فصل ۷: مدیریت و امنیت — کاربران، بکاپ، Replication و کد سمت سرور

کاربران، GRANT با اصل کمترین دسترسی و Roleها

اصل کمترین دسترسی در عمل

در فصل اول یک کاربر ساده برای برنامه ساختیم. در محیط واقعی چند نوع مصرف‌کننده دارید: خود برنامه‌ی وب، فرمان مایگریشن، کاربر گزارش‌گیری که به ابزار BI وصل می‌شود، کاربر پشتیبان‌گیری و مدیر انسانی. اصل کمترین دسترسی می‌گوید هر کدام فقط همان مجوزی را بگیرد که کارش لازم دارد. اگر رمز برنامه‌ی وب از یک فایل .env نشت کرد، مهاجم نباید بتواند DROP DATABASE بزند یا دیتابیس سایت دیگری را که روی همان سرور است بخواند.

سطوح مجوز

سطحنمونهکاربرد
سراسریON *.*فقط برای مدیر، بکاپ و Replication
دیتابیسON carpet_factory.*حالت معمول برای برنامه
جدولON carpet_factory.ordersکاربر گزارش یا سرویس جانبی
ستونSELECT (id, city) ON ...customersپنهان کردن موبایل و آدرس
روتینEXECUTE ON PROCEDURE ...اجازه‌ی اجرای یک رویه‌ی مشخص

نقش‌ها: مجوز را به نقش بدهید، نه به آدم

از MySQL 8 می‌توان مجموعه‌ای از مجوزها را یک‌بار در قالب Role تعریف و به چند کاربر داد. وقتی کارمند جدیدی به واحد گزارش آمد، فقط نقش را به او می‌دهید.

CREATE ROLE 'app_rw', 'app_migrate', 'report_ro';

GRANT SELECT, INSERT, UPDATE, DELETE ON carpet_factory.* TO 'app_rw';
GRANT ALTER, CREATE, DROP, INDEX, REFERENCES ON carpet_factory.* TO 'app_migrate';

GRANT SELECT ON carpet_factory.orders      TO 'report_ro';
GRANT SELECT ON carpet_factory.order_items TO 'report_ro';
GRANT SELECT (id, full_name, city) ON carpet_factory.customers TO 'report_ro';

CREATE USER 'web'@'10.0.0.%' IDENTIFIED BY 'Long-Random-Secret-1405'
  FAILED_LOGIN_ATTEMPTS 5 PASSWORD_LOCK_TIME 1;
CREATE USER 'sara_bi'@'10.0.0.25' IDENTIFIED BY 'Another-Long-Secret'
  PASSWORD EXPIRE INTERVAL 90 DAY;

GRANT 'app_rw'    TO 'web'@'10.0.0.%';
GRANT 'report_ro' TO 'sara_bi'@'10.0.0.25';
SET DEFAULT ROLE ALL TO 'web'@'10.0.0.%', 'sara_bi'@'10.0.0.25';

SHOW GRANTS FOR 'sara_bi'@'10.0.0.25' USING 'report_ro';

برنامه‌ی جنگو در حالت عادی با نقش app_rw کار می‌کند و manage.py migrate در زمان استقرار با کاربر جداگانه‌ای اجرا می‌شود که app_migrate هم دارد. نقشی که به کاربر داده شده تا وقتی فعال نشود اثری ندارد؛ SET DEFAULT ROLE را فراموش نکنید و برای بررسی، SELECT CURRENT_ROLE(); بزنید.

بازبینی دوره‌ای

SELECT user, host, account_locked, password_last_changed
FROM mysql.user ORDER BY user;

ALTER USER 'old_intern'@'%' ACCOUNT LOCK;   -- قبل از حذف، مدتی قفل کنید
DROP USER 'old_intern'@'%';

نکته‌هایی که کمتر کسی می‌داند

  • در GRANT سطح دیتابیس، _ و % wildcard هستند: GRANT ... ON my_db.* دیتابیس myxdb را هم شامل می‌شود. برای دقت بنویسید my\_db.
  • ALL ON carpet_factory.* مجوز DROP را هم دارد؛ یعنی کاربر برنامه می‌تواند کل دیتابیس را حذف کند. همچنین TRIGGER و CREATE ROUTINE را می‌دهد که برای ماندگاری مهاجم کافی است.
  • مجوز سراسری FILE اجازه‌ی خواندن فایل‌های سرور با LOAD_FILE() را می‌دهد؛ هرگز به کاربر برنامه ندهید و secure_file_priv را خالی نگذارید.
  • با partial_revokes = ON می‌توان «همه به‌جز» ساخت: GRANT SELECT ON *.* و سپس REVOKE SELECT ON mysql.*.
  • 'web'@'localhost' و 'web'@'%' دو حساب جدا با رمز و مجوز جدا هستند؛ MySQL هنگام ورود، خاص‌ترین host را انتخاب می‌کند، نه حسابی را که شما در ذهن دارید.
  • متغیر mandatory_roles نقشی را به همه‌ی کاربران می‌دهد و activate_all_roles_on_login = ON نیاز به SET DEFAULT ROLE را برمی‌دارد.

برای ذخیره‌ی پیشرفت و شرکت در آزمون، وارد شوید — رایگان است.