3

我目前正在尝试配置collective.xsendfile、Apache mod_xsendfile 和Plone 4。

显然 Apache 进程在文件系统上看不到 blobstrage 文件,因为它们包含权限:

ls -lh var/blobstorage/0x00/0x00/0x00/0x00/0x00/0x18/0xd5/0x19/0x038ea09d0eddc611.blob -r-------- 1 plone plone 1006K 5 月 28 日 15:30 var/blobstorage/0x00 /0x00/0x00/0x00/0x00/0x18/0xd5/0x19/0x038ea09d0eddc611.blob

如何配置 blobstorage 以提供额外的权限,以便 Apache 可以访问这些文件?

4

2 回答 2

4

blobstorage 写入其目录和文件的模式是硬编码在ZODB.blob. 具体来说,标准ZODB.blob.FileSystemHelper类默认创建安全目录(仅对当前用户可读和可写)。

您可以提供自己的实现FileSystemHelper,或者将其配置为可配置,或者只是将目录模式设置为0750,然后修补ZODB.blob.BlobStorageMixin以使用您的类而不是默认值:

import os
from ZODB import utils
from ZODB.blob import FilesystemHelper, BlobStorageMixin
from ZODB.blob import log, LAYOUT_MARKER

class GroupReadableFilesystemHelper(FilesystemHelper):
    def create(self):
        if not os.path.exists(self.base_dir):
            os.makedirs(self.base_dir, 0750)
            log("Blob directory '%s' does not exist. "
                "Created new directory." % self.base_dir)
        if not os.path.exists(self.temp_dir):
            os.makedirs(self.temp_dir, 0750)
            log("Blob temporary directory '%s' does not exist. "
                "Created new directory." % self.temp_dir)

        if not os.path.exists(os.path.join(self.base_dir, LAYOUT_MARKER)):
            layout_marker = open(
                os.path.join(self.base_dir, LAYOUT_MARKER), 'wb')
            layout_marker.write(self.layout_name)
        else:
            layout = open(os.path.join(self.base_dir, LAYOUT_MARKER), 'rb'
                          ).read().strip()
            if layout != self.layout_name:
                raise ValueError(
                    "Directory layout `%s` selected for blob directory %s, but "
                    "marker found for layout `%s`" %
                    (self.layout_name, self.base_dir, layout))

    def isSecure(self, path):
        """Ensure that (POSIX) path mode bits are 0750."""
        return (os.stat(path).st_mode & 027) == 0

    def getPathForOID(self, oid, create=False):
        """Given an OID, return the path on the filesystem where
        the blob data relating to that OID is stored.

        If the create flag is given, the path is also created if it didn't
        exist already.

        """
        # OIDs are numbers and sometimes passed around as integers. For our
        # computations we rely on the 64-bit packed string representation.
        if isinstance(oid, int):
            oid = utils.p64(oid)

        path = self.layout.oid_to_path(oid)
        path = os.path.join(self.base_dir, path)

        if create and not os.path.exists(path):
            try:
                os.makedirs(path, 0750)
            except OSError:
                # We might have lost a race.  If so, the directory
                # must exist now
                assert os.path.exists(path)
        return path


def _blob_init_groupread(self, blob_dir, layout='automatic'):
    self.fshelper = GroupReadableFilesystemHelper(blob_dir, layout)
    self.fshelper.create()
    self.fshelper.checkSecure()
    self.dirty_oids = []

BlobStorageMixin._blob_init = _blob_init_groupread

相当多,您可能希望将此作为 ZODB3 的功能请求 :-)

于 2011-05-29T17:18:18.063 回答
2

在为 ZOPE/ZEO 设置设置备份例程时,我在 blob 权限方面遇到了同样的问题。

在尝试应用 Mikko 编写的猴子补丁(这并不容易)之后,我想出了一个“真正的”补丁来解决问题。

Martijn 建议的补丁不完整,它仍然没有在 blob 文件上设置正确的模式。

所以这是我的解决方案:

1.) 创建一个补丁,其中包含:

Index: ZODB/blob.py
===================================================================
--- ZODB/blob.py    (Revision 121959)
+++ ZODB/blob.py    (Arbeitskopie)
@@ -337,11 +337,11 @@

     def create(self):
         if not os.path.exists(self.base_dir):
-            os.makedirs(self.base_dir, 0700)
+            os.makedirs(self.base_dir, 0750)
             log("Blob directory '%s' does not exist. "
                 "Created new directory." % self.base_dir)
         if not os.path.exists(self.temp_dir):
-            os.makedirs(self.temp_dir, 0700)
+            os.makedirs(self.temp_dir, 0750)
             log("Blob temporary directory '%s' does not exist. "
                 "Created new directory." % self.temp_dir)

@@ -359,8 +359,8 @@
                     (self.layout_name, self.base_dir, layout))

     def isSecure(self, path):
-        """Ensure that (POSIX) path mode bits are 0700."""
-        return (os.stat(path).st_mode & 077) == 0
+        """Ensure that (POSIX) path mode bits are 0750."""
+        return (os.stat(path).st_mode & 027) == 0

     def checkSecure(self):
         if not self.isSecure(self.base_dir):
@@ -385,7 +385,7 @@

         if create and not os.path.exists(path):
             try:
-                os.makedirs(path, 0700)
+                os.makedirs(path, 0750)
             except OSError:
                 # We might have lost a race.  If so, the directory
                 # must exist now
@@ -891,7 +891,7 @@
             file2.close()
         remove_committed(f1)
     if chmod:
-        os.chmod(f2, stat.S_IREAD)
+        os.chmod(f2, stat.S_IRUSR | stat.S_IRGRP)

 if sys.platform == 'win32':
     # On Windows, you can't remove read-only files, so make the

您也可以在这里查看补丁 -> http://pastebin.com/wNLYyXvw

2.) 将补丁以“blob.patch”的名称存储在您的构建根目录中

3.) 扩展您的构建配置:

parts += 
    patchblob
    postinstall

[patchblob]
recipe = collective.recipe.patch
egg = ZODB3
patches = blob.patch

[postinstall]
recipe = plone.recipe.command
command = 
    chmod -R g+r ${buildout:directory}/var
    find ${buildout:directory}/var -type d | xargs chmod g+x
update-command = ${:command}

postinstall 部分设置对现有 blob 的所需组读取权限。注意,还必须授予 blob 文件夹执行权限,该组可以进入目录。

我已经用 ZODB 3.10.2 和 3.10.3 测试了这个补丁。

正如 Martijn 建议的那样,这应该是可配置的,并且是 ZODB 的一部分。

于 2011-06-17T08:20:08.590 回答