尝试编写只读数据库 - Django w/ SELinux 错误

71
我有一个CentOS服务器,上面安装了Apache、Django、Django CMS和mod_wsgi。我的Django项目文件存储在/srv目录中,并启用SELinux以提高安全性。
我已成功将Django-CMS集成到Django中,当我访问本地IP时,可以看到我的页面。但是,当我尝试访问“/admin”(在那里我可以开始使用CMS功能)时,我会收到“DatabaseError at /admin/ attempt to write a readonly database”的错误提示。
所以,由于我的项目文件夹中有一个.sqlite文件,我运行了“ls -l”命令,返回结果如下:
-rw-r--r--.  1 root root 133120 Jan 5 11:53   DATABASE.sqlite

好的,我想也许 Apache 由于某些权限原因无法读取该文件,所以在 Stackoverflow 上进行了一些类似问题的研究后,我运行了:

> chmod 664 DATABASE.sqlite
> chown apache /srv/mysite
> chown apache /srv/mysite/DATABASE.sqlite

现在,ls -l 输出的内容如下:

-rw-rw-r--.  1 apache root 133120 Jan 5 11:53  DATABASE.sqlite

很不幸,当我尝试访问我的Django应用程序中的/admin时,仍然遇到相同的错误。非常感谢任何帮助!可能是与SELinux权限有关,但我不知道从哪里开始诊断发生了什么权限问题。

编辑:

我运行了

> chown apache:apache /srv/mysite
> chown apache:apache /srv/mysite/DATABASE.sqlite

快速执行 ls -l 命令可以查看 mysite 目录和 .sqlite 文件的所有者现在是 apache。然而,当我尝试访问 /admin 页面时仍然遇到错误。我将 /srv/mysite 目录的权限设置为 757,将 DATABASE.sqlite 文件的权限设置为 756,因为这是我能做的最好的方式。我被告知这是一种安全风险,但我似乎无法找出如何授予更少的权限并通过 unable to read/open database file 错误。这是因为 SELinux 的原因吗?

顺便说一下,我在 CentOS 上使用普通用户帐户操作,并在需要提升权限时使用 sudo:

[noblerare@localhost ]$
10个回答

103

您需要将写入权限添加到存储SQLite数据库的目录中。因此运行 chmod -R u+w /srv/mysite/ 应该有所帮助。

如果服务器正在使用自定义用户(例如www-data)访问数据库,则解决方法可能是更改数据库的所有者:

chown www-data:www-data /srv/mysite
chown www-data:www-data /srv/mysite/DATABASE.sqlite

3
我最终将/srv/mysite设置为755,将DATABASE.sqlite设置为756。这是否存在安全风险?如果我更改权限,会出现错误。 - noblerare
3
感谢您的编辑。由于我使用的是CentOS系统,所以在运行chown命令时使用了apache而不是www-data用户。无论如何,现在/srv/mysiteDATABASE.sqlite的所有者都是apache。但不管怎样,如果我将“所有人”的权限更改为低于读/写/执行或读/写的权限,我都会出现错误。 - noblerare
很不幸,对我来说仍然无法工作 - 由于权限的原因,甚至无法进入数据库目录。:( - erixliechtenstein
1
对我来说,执行 chmod -R u+w /srv/mysite/ 之后就起作用了。 - anils

19
简而言之,当写入 SQLite 数据库的应用程序没有写入权限时,就会发生这种情况。
解决方法有三种:
  1. 使用 chown 命令将 db.sqlite3 文件及其父目录的所有权(即写入访问权限)授予用户(例如:chown username db.sqlite3)
  2. 以 root 用户身份运行 web 服务器(通常是 gunicorn)(在运行 gunicorn 或 Django 的 runserver 命令之前运行 sudo -i 命令)
  3. 通过运行 chmod 777 db.sqlite3 命令允许所有用户读写访问(危险选项)
除非您在本地机器上运行 web 服务器或数据库中的数据完全不重要,否则永远不要选择第三个选项。
第二个选项也不推荐。但如果您确信您的应用程序不容易受到代码注入攻击,可以选择该选项。

8

这个问题是由SELinux引起的。在像你一样设置文件所有权后,我遇到了这个问题。可以使用audit2why(1)工具从日志中诊断SELinux拒绝:

(django)[f22-4:www/django/demo] ftweedal% sudo audit2why -a
type=AVC msg=audit(1437490152.208:407): avc:  denied  { write }
      for  pid=20330 comm="httpd" name="db.sqlite3" dev="dm-1" ino=52036
      scontext=system_u:system_r:httpd_t:s0
      tcontext=unconfined_u:object_r:httpd_sys_content_t:s0
      tclass=file permissive=0
    Was caused by:
    The boolean httpd_unified was set incorrectly. 
    Description:
    Allow httpd to unified

    Allow access by executing:
    # setsebool -P httpd_unified 1

毫无疑问,运行sudo setsebool -P httpd_unified 1解决了这个问题。
在查看httpd_unified的用途时,我发现了一篇fedora-selinux-list post,其中解释道:
该布尔值默认为关闭状态,打开它将允许所有httpd可执行文件完全访问所有带有http文件上下文标签的内容。关闭它可以确保一个httpd服务不会干扰另一个httpd服务。
因此,打开httpd_unified可以绕过默认行为,该行为防止在同一服务器上作为用户apache运行的多个httpd实例相互干扰。
在我的情况下,我只运行了一个httpd,所以我可以打开httpd_unified。如果您不能这样做,我想需要进行更细粒度的标记。

1
这解决了我的问题。我为此苦苦挣扎了两天。即使给了 /var/ 777 权限(这有点破坏性),我还是无法解决它。非常感谢你! - Aakash Rayate
@AakashRayate 同感!我觉得我在整个文件夹上都做了太多的777。 - User

5
我遇到了这个问题,并通过在mysite文件夹中创建一个目录来解决它,用于保存我的db.sqlite3文件。所以我做了/home/user/src/mysite/database/db.sqlite3。在我的Django设置文件中,我进行了修改。
 DATABASES = {
'default': {
    'ENGINE': 'django.db.backends.sqlite3',
    'NAME': "/home/user/src/mysite/database/db.sqlite3" ,
}}

我这样做是为了让Django知道我将数据库存储在基目录的子目录中,对于我的情况来说是mysite。现在你需要授予Apache读写数据库的权限。
chown user:www-data database/db.sqlite3
chown user:www-data database 
chmod 755 database
 chmod 755 database/db.sqlite3

这解决了我的问题。以下是不同权限的列表。你可以选择适合你的权限,但要避免使用777和666。
-rw------- (600) -- 只有用户具有读写权限。
-rw-r--r-- (644) -- 只有用户具有读写权限;组和其他人只能读取。
-rwx------ (700) -- 只有用户具有读、写和执行权限。
-rwxr-xr-x (755) -- 用户具有读、写和执行权限;组和其他人只能读取和执行。
-rwx--x--x (711) -- 用户具有读、写和执行权限;组和其他人只能执行。
-rw-rw-rw- (666) -- 所有人都可以读写该文件。不好的主意。
-rwxrwxrwx (777) -- 所有人都可以读、写和执行。另一个不好的主意。
以下是一些常见的目录设置:
drwx------ (700) -- 只有用户可以读写该目录。
drwxr-xr-x (755) -- 所有人都可以读取该目录,但其内容只能由用户更改。
这里有一篇文章的链接,可以了解更多信息:在chmod中玩转数字

5
我在Ubuntu Server上遇到了同样的问题。 所以我在激活Django虚拟环境之前切换到超级用户,然后运行Django服务器。 这对我来说很好用。 首先复制粘贴 sudo su 然后如果有虚拟环境,请激活它。 source myvenv/bin/activate 最后运行你的Django服务器。 python3 manage.py runserver 希望这可以帮助你。

2
这是我解决它的方法。
sudo chmod 774 . || sudo chmod 776 .  

特别注意,因为大部分情况下,这不能正常工作是因为我们尝试这样做:

sudo chmod 774 db.sqlite3

但是你所要做的是打开包含db.sqlite3文件的文件夹,而不是数据库本身。如果这不能完全解决问题,那么尝试以下步骤:

sudo chmod 774 db.sqlite3

然后它应该可以工作了。干杯!

底下的两个命令是一样的,我相信最后一个命令有一个打字错误。 - undefined

1
我遇到了类似的问题。为了检查SELinux是否是问题所在,可以使用以下命令检查其运行状态:
sestatus

并可以使用

暂时禁用它。

setenforce 0

这至少可以帮助缩小问题的范围。

这帮助了我解决Centos 7的问题。 - noobCoder

0

您可以更改文件/目录的acl而不触及其所有权和权限。

使用以下命令:

setfacl -m u:www-data:rwx /home/user/website
setfacl -m u:www-data:rw /home/user/website/db.sqlite3

0

你可以将数据库文件及其文件夹的所有者更改为 django

chown django:django /home/django/mysite
chown django:django /home/django/mysite/my_db.sqlite3

这适用于DigitalOcean的1-Click Django Droplet


-12

这是我的解决方案:

root@fiq:/home/django/django_project# chmod 777 db.sqlite3
root@fiq:/home/django/django_project# cd ..
root@fiq:/home/django# chmod 777 *

前往 <'your_website/admin'> 输入用户名和密码.. 就这样。


1
非常不安全,您正在将777设置为数据库权限。由于SQLite数据库是自包含在文件中的,这意味着它实际上会授予服务器上任何用户777权限。 - adelriosantiago
1
这是一个非常糟糕的想法。 - Casper B. Hansen
2
这个答案是一个笑话。任何人都不应该这样做。 - Anand C U

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接