为Zope3视图的安全审计工具和演示
项目描述
z3c.securitytool
z3c.securitytool是一个针对Zope3的包,旨在提供组件级别的安全信息,以帮助分析安全问题和暴露潜在弱点。安全工具的目标是为任何给定组件和上下文的可用视图提供用户和其实际权限的矩阵。我们还提供两个更详细的级别。您可以通过在矩阵中点击权限来查看用户如何获得给定视图的权限详情。
演示说明
您可以通过仅下载securitytool包来运行演示
# svn co svn://svn.zope.org/repos/main/z3c.securitytool/trunk securitytool
# cd securitytool
# python bootstrap.py
# ./bin/buildout
# ./bin/demo fg
然后使用以下方式访问演示站点
https://127.0.0.1:8080/++skin++SecurityTool/securityMatrix.html
用户: admin
密码: admin
这里添加了一些文件夹,并应用了权限和角色,以展示演示中的设置。
https://127.0.0.1:8080/++skin++SecurityTool/Folder1/securityMatrix.html
https://127.0.0.1:8080/++skin++SecurityTool/Folder1/Folder2/securityMatrix.html
这些权限应与您在@@grant.html视图中看到的一致
- (这些设置是在数据库首次打开时添加的
您可以在demoSetup.py中找到这些设置)
如何将securityTool与您的项目结合使用
请记住,这是一个正在进行中的工作。
在您的setup.py中添加z3c.securitytool到install_requires。
在您的site.zcml中添加<include package=”z3c.securitytool”/>。
使用皮肤 ++skin++SecurityTool 访问安全工具页面
将@@securityMatrix.html视图追加到任何上下文中,使用安全工具皮肤查看该上下文的权限矩阵。
例如:https://127.0.0.1:8080/++skin++SecurityTool/Folder1/@@securityMatrix.html
详细文档
在安全工具的主页上,您可以从系统上所有可用的皮肤中选择所需的皮肤。在安全工具初次加载时,您将只能看到IBrowserRequest和您当前上下文的权限。当您选择皮肤时,有趣的信息就会出现。此工具的将来版本将提供选择,以查看所有皮肤的详细信息以及每个皮肤单独的详细信息。您还可以通过从过滤器选择框中选择权限来截断结果。当您点击“允许”或“拒绝”时,安全工具将解释这些权限是在角色、组或本地上下文中指定的。
当您点击用户名时,将显示从角色、组或特定分配的权限继承的所有权限。
>>> import zope >>> from zope.app import zapi >>> from pprint import pprint >>> from zope.interface import providedBy >>> from z3c.securitytool.securitytool import * >>> from z3c.securitytool.interfaces import ISecurityChecker >>> from z3c.securitytool.interfaces import IPrincipalDetails >>> from z3c.securitytool.interfaces import IPermissionDetails >>> from z3c.securitytool.browser import ISecurityToolSkin >>> root = getRootFolder()在启动演示或运行测试时,在IDatabaseOpenedEvent中向数据库添加了一些内容。这些设置用于测试中的功能测试以及为演示填充矩阵。让我们确保这些项是通过demoSetup.py添加的,我们假设如果Folder1存在于根文件夹中,则已执行demoSetup.py。
>>> sorted(root.keys()) [u'Folder1']要检索文件夹的权限设置,我们必须首先将上下文适配到SecurityChecker对象。
>>> folder1 = ISecurityChecker(root['Folder1'])>>> print folder1.__class__.__name__ SecurityChecker让我们检查这个对象。
>>> pprint(dir(folder1)) ['__class__', '__component_adapts__', ... 'aggregateMatrices', 'context', 'getPermissionSettingsForAllViews', 'getReadPerm', 'populateMatrix', 'populatePermissionMatrix', 'populateViewRoleMatrix']要获取特定上下文级别的所有安全设置,请使用getPermissionSettingsForAllViews调用一个接口元组。将检查传递给接口的所有注册视图。
由于不应只为zope.interface.Interface注册任何内容,因此我们应该收到一个空的权限、角色和组集合。
>>> folder1.getPermissionSettingsForAllViews(zope.interface.Interface) [{}, {}, set([])]进行一次现实的测试,可以通过获取特定上下文级别(如 Folder1)提供的所有接口来实现。由于是文件夹,所以这些接口正如你所期望的那样。
>>> ifaces = tuple(providedBy(root['Folder1'])) >>> pprint(ifaces) (<InterfaceClass zope.site.interfaces.IFolder>, <InterfaceClass zope.container.interfaces.IContentContainer>, <InterfaceClass persistent.interfaces.IPersistent>, <InterfaceClass zope.location.interfaces.IContained>, <InterfaceClass zope.component.interfaces.IPossibleSite>)确定安全级别的下一步是 getViews 函数。 getViews 获取该接口的所有已注册视图。这将在稍后细化到只在此上下文中可访问的视图。
>>> pprint(sorted([x for x in getViews(ifaces[0])])) [AdapterRegistration... ITraversable, u'acquire', ... AdapterRegistration... ITraversable, u'adapter', ... AdapterRegistration... ITraversable, u'attribute', ... AdapterRegistration... ITraversable, u'etc', ... AdapterRegistration... ITraversable, u'item', ... AdapterRegistration... ITraversable, u'lang', ... AdapterRegistration... ITraversable, u'resource', ... AdapterRegistration... ITraversable, u'skin', ... AdapterRegistration... ITraversable, u'vh', ... AdapterRegistration... ITraversable, u'view', ...由于这是一个大型结果集,我们只测试足够的结果片段来了解所需的操作行为,并确保结果合理。
>>> permDetails = folder1.getPermissionSettingsForAllViews(ifaces, ... ISecurityToolSkin)通过使用 ISecurityToolSkin,我们可以看到实际的 securityTool 视图。securityTool 视图仅注册在 ISecurityToolSkin 层。
>>> pprint(permDetails) [... 'zope.globalmgr': {u'<i>no name</i>': 'Allow', u'DELETE': 'Allow', u'OPTIONS': 'Allow', u'PUT': 'Allow', u'absolute_url': 'Allow', u'permissionDetails.html': 'Allow', u'principalDetails.html': 'Allow', u'securityMatrix.html': 'Allow'}, ...]如你所见,以下 zope.anybody 对下面列出的四个视图有“允许”权限。由于安全工具视图既未特别拒绝也未允许此主体,因此它们未在此列出。
>>> pprint(permDetails) ... [{'zope.anybody': {u'<i>no name</i>': 'Allow', u'DELETE': 'Allow', u'OPTIONS': 'Allow', u'PUT': 'Allow', u'absolute_url': 'Allow'}, ...结果集的另一部分显示了此上下文和皮肤的所有有效视图,以及访问视图所需的权限。
>>> pprint(permDetails) [... {u'<i>no name</i>': 'zope.Public', u'DELETE': 'zope.Public', u'OPTIONS': 'zope.Public', u'PUT': 'zope.Public', u'absolute_url': 'zope.Public', u'permissionDetails.html': 'zope.ManageContent', u'principalDetails.html': 'zope.ManageContent', u'securityMatrix.html': 'zope.ManageContent'}, ...]系统中的所有主体都位于这个数据结构中。这里我们只打印结构的一个子集,以确保数据是合理的。
>>> pprint(sorted(permDetails[0].keys())) ['zope.anybody', 'zope.daniel', 'zope.globalmgr', 'zope.group1', 'zope.markus', 'zope.martin', 'zope.mgr', 'zope.randy', 'zope.sample_manager', 'zope.stephan']这当然应该与 zapi.getPrincipals() 返回的系统用户相同,但不包括 (zope.anybody)
>>> from zope.app import zapi >>> sysPrincipals = zapi.principals() >>> principals = [x.id for x in sysPrincipals.getPrincipals('')] >>> pprint(sorted(principals)) ['zope.daniel', 'zope.globalmgr', 'zope.group1', 'zope.group2', 'zope.markus', 'zope.martin', 'zope.mgr', 'zope.randy', 'zope.sample_manager', 'zope.stephan']
使用securitytool检查主体
让我们看看主体 Daniel 和上下文“Folder1”的主体详细信息是什么样的。
首先,我们检索 Folder1 的主体详细信息
>>> prinDetails = PrincipalDetails(root[u'Folder1'])然后我们过滤掉用户检查中的不感兴趣的信息。
>>> matrix = prinDetails('zope.daniel')主体详细信息结构包含五个有趣的数据点。
>>> pprint(sorted(matrix.keys())) ['groups', 'permissionTree', 'permissions', 'roleTree', 'roles']以下我们检查用户 daniel 的组数据结构是否如预期返回。这是用于填充用户详细信息页面上的组部分的 数据。
>>> pprint(matrix['groups'].keys()) ['zope.randy']权限树用于显示达到显示的权限所经过的继承级别。权限作为列表存储,以保持顺序。(我知道有更好的方法来完成这项工作)
>>> pprint(matrix['permissionTree'][0]) {u'Folder1_2': {'name': None, 'parentList': [u'Folder1', 'Root Folder'], 'permissions': [{'permission': 'concord.CreateArticle', 'principal': 'zope.daniel', 'setting': PermissionSetting: Allow}, {'permission': 'concord.ReadIssue', 'principal': 'zope.daniel', 'setting': PermissionSetting: Deny}, {'permission': 'concord.DeleteIssue', 'principal': 'zope.daniel', 'setting': PermissionSetting: Allow}]}}>>> pprint(matrix['permissionTree'][1]) {'Root Folder': {'name': 'Root Folder', 'parentList': ['Root Folder'], 'permissions': [{'permission': 'concord.DeleteArticle', 'principal': 'zope.daniel', 'setting': PermissionSetting: Deny}, {'permission': 'concord.CreateArticle', 'principal': 'zope.daniel', 'setting': PermissionSetting: Deny}, {'permission': 'concord.ReadIssue', 'principal': 'zope.daniel', 'setting': PermissionSetting: Allow}]}}矩阵的权限部分显示了用户是否具有此上下文级别的权限的最终决定。
>>> pprint(matrix['permissions'], width=1) [{'permission': 'concord.CreateArticle', 'setting': PermissionSetting: Allow}, {'permission': 'concord.ReadIssue', 'setting': PermissionSetting: Deny}, {'permission': 'concord.DeleteIssue', 'setting': PermissionSetting: Allow}, {'permission': 'concord.DeleteArticle', 'setting': PermissionSetting: Deny}, {'permission': 'concord.CreateIssue', 'setting': PermissionSetting: Allow}, {'permission': 'concord.PublishIssue', 'setting': PermissionSetting: Allow}]roleTree 结构用于显示在遍历的每个级别获得的角色。roleTree 作为列表存储,因此为了正确地一致测试数据,我们将它转换为字典,这与 permissionTree 的功能相似。
>>> tmpDict = {} >>> keys = matrix['roleTree'] >>> for item in matrix['roleTree']: ... tmpDict.update(item)>>> pprint(tmpDict['Root Folder']) {'name': 'Root Folder', 'parentList': ['Root Folder'], 'roles': [{'principal': 'zope.daniel', 'role': 'zope.Writer', 'setting': PermissionSetting: Allow}]}>>> pprint(tmpDict['Folder1_2']) {'name': None, 'parentList': [u'Folder1', 'Root Folder'], 'roles': [{'principal': 'zope.daniel', 'role': 'zope.Writer', 'setting': PermissionSetting: Allow}]}>>> pprint(tmpDict['global settings']) {'name': None, 'parentList': ['global settings'], 'roles': [{'principal': 'zope.daniel', 'role': 'zope.Janitor', 'setting': PermissionSetting: Allow}]}矩阵的角色部分显示了用户是否具有在此上下文级别分配的角色最终决定。
>>> pprint(matrix['roles'], width=1) {'zope.Janitor': [{'permission': 'concord.ReadIssue', 'setting': 'Allow'}], 'zope.Writer': [{'permission': 'concord.DeleteArticle', 'setting': 'Allow'}, {'permission': 'concord.CreateArticle', 'setting': 'Allow'}, {'permission': 'concord.ReadIssue', 'setting': 'Allow'}]}
现在让我们看看权限详细信息返回的内容
>>> from zope.publisher.interfaces.browser import IBrowserRequest >>> from z3c.securitytool.interfaces import IPermissionDetails >>> permAdapter = zapi.getMultiAdapter((root[u'Folder1'], ... ),IPermissionDetails) >>> prinPerms = permAdapter('zope.daniel', ... 'ReadIssue.html', ... )>>> print permAdapter.skin <InterfaceClass zope.publisher.interfaces.browser.IBrowserRequest>>>> print permAdapter.read_perm zope.Public>>> print permAdapter.view_name ReadIssue.html>>> pprint(prinPerms) {'groups': {'zope.randy': {'groups': {'zope.group1': {'groups': {}, 'permissionTree': [], 'permissions': [], 'roleTree': [], 'roles': {}}, 'zope.group2': {'groups': {}, 'permissionTree': [], 'permissions': [], 'roleTree': [], 'roles': {}}}, 'permissionTree': [], 'permissions': [], 'roleTree': [], 'roles': {}}}, 'permissionTree': [], 'permissions': [], 'roleTree': [], 'roles': {}}
以下是在安全工具中使用的一些辅助函数,这些函数包含在许多地方使用的一系列常用功能。让我们看看“hasPermissionSetting”方法是否在存在权限或角色时返回 True,不存在时返回 False。
>>> hasPermissionSetting({'permissions':'Allow'}) True我们需要创建一些模拟对象来测试“hasPermissionSetting”方法
>>> emptySettings = {'permissions': [], ... 'roles': {}, ... 'groups': {}}>>> fullSettings = {'permissions': 'Allow', ... 'roles': {}, ... 'groups': {}}我们还需要确保此方法的功能是递归的
>>> hasPermissionSetting({'permissions':{},'roles':{}, ... 'groups':{'group1':emptySettings, ... 'group2':fullSettings}}) True>>> from zope.securitypolicy.interfaces import Allow, Unset, Deny >>> prinPermMap = ({'principal':'daniel', ... 'permission':'takeOverTheWORLD', ... 'setting': Allow})>>> rolePermMap = ({'role':'Janitor', ... 'permission':'takeOverTheWORLD', ... 'setting': Allow})>>> prinRoleMap = ({'principal':'daniel', ... 'role':'Janitor', ... 'setting': Allow})让我们使用我们的新模拟数据测试该方法 >>> principalDirectlyProvidesPermission([prinPermMap],’daniel’,…‘takeOverTheWORLD’)‘允许’
我们还必须测试 roleProvidesPermission >>> roleProvidesPermission([rolePermMap], ‘Janitor’, ‘takeOverTheWORLD’)‘允许’
我们还必须测试 roleProvidesPermission >>> principalRoleProvidesPermission([prinRoleMap],…[rolePermMap],…‘daniel’,…‘takeOverTheWORLD’)(‘Janitor’,‘允许’)
看啊,清洁工可以接管世界!!!!
当然,如果我们在页面上没有收到名称,这意味着我们处于根级别。
>>> renderedName(None) u'Root Folder'>>> renderedName('Daniel') 'Daniel'>>> folder1.populatePermissionMatrix('takeOverTheWORLD',[prinPermMap])
TestBrowser 烟雾测试
让我们确保所有视图都能正常工作。仅进行简单的烟雾测试
>>> from zope.testbrowser.testing import Browser >>> manager = Browser() >>> authHeader = 'Basic mgr:mgrpw' >>> manager.addHeader('Authorization', authHeader) >>> manager.handleErrors = False>>> server = 'https://127.0.0.1:8080/++skin++SecurityTool'>>> manager.open(server + '/@@securityMatrix.html')首先,我们将检查主页是否可用
>>> manager.open(server + '/@@securityMatrix.html')>>> manager.open(server + '/Folder1/@@securityMatrix.html')>>> manager.open(server + '/Folder1/Folder2/Folder3/@@securityMatrix.html')现在让我们发送过滤变量,以便完成测试
>>> manager.open(server + '/@@securityMatrix.html?' ... 'FILTER=None&selectedSkin=ConcordTimes')并且使用选定的权限
>>> manager.open(server + '/@@securityMatrix.html?' ... 'FILTER=None&selectedSkin=ConcordTimes&' ... 'selectedPermission=zope.Public')这里我们发送一个无效的selectedPermisson(仅用于覆盖);)
>>> manager.open(server + '/@@securityMatrix.html?' ... 'FILTER=None&selectedSkin=ConcordTimes&' ... 'selectedPermission=zope.dummy')并且使用None权限
>>> manager.open(server + '/@@securityMatrix.html?' ... 'FILTER=None&selectedSkin=ConcordTimes&' ... 'selectedPermission=None')这是主要详情页面,您可以通过点击表单顶部的主体名称来访问
>>> manager.open(server + ... '/@@principalDetails.html?principal=zope.daniel')>>> manager.open(server + ... '/Folder1/Folder2/Folder3/' ... '@@principalDetails.html?principal=zope.daniel')>>> 'Permission settings' in manager.contents True然后我们调用没有主体的视图
>>> manager.open(server + '/@@principalDetails.html') Traceback (most recent call last): ... PrincipalLookupError: no principal specified这里是在点击矩阵中与用户在公共视图交叉的实际权限值时您将看到的视图
>>> manager.open(server + '/@@permissionDetails.html?' ... 'principal=zope.daniel&view=PUT')好的,让我们发送没有主体的命令
>>> manager.open(server + '/@@permissionDetails.html?view=PUT') Traceback (most recent call last): ... PrincipalLookupError: no user specified现在我们将测试不带视图名称的命令
>>> manager.open(server + '/@@permissionDetails.html?' ... 'principal=zope.daniel')现在使用一个不存在的视图名称
>>> manager.open(server + '/@@permissionDetails.html?' ... 'principal=zope.daniel&view=garbage')让我们也测试不同的上下文级别
>>> manager.open(server + ... '/Folder1/Folder2/Folder3/' ... '@@permissionDetails.html' ... '?principal=zope.daniel&view=ReadIssue.html')
变更
0.5.1 (2010-10-23)
在setup.py中删除了重复的URL条目,修复了棕色袋发布。
0.5.0 (2010-10-21)
更新了测试、测试设置和演示应用程序,使其在Python 2.4和Python 2.6上运行ZTK 1.0。
更新到z3c.layer.minimal,而不是已弃用的z3c.layer。
0.4.2 (2008-07-22)
修复了权限详情页面上继承显示的问题
清理了一些页面模板文件。
在主体详情页面上对组继承显示添加了描述。
0.4.1 (2008-06-12)
修复了securityMatrix.html页面上继承显示的问题
在securityMatrix.html页面上添加了指向视图的链接
将PrincipalDetails和PermissionDetails重构到它们自己的文件中
将ZPL文本添加到所有py文件顶部
将共享的全局函数重构到globalFunctions.py
将MatrixDetails超级类重构到其自己的文件。
呼呼,呼呼,呼呼
0.4.0b (2008-06-09)
更新了主体详情页面的页面模板
修复了viewMatrix页面上的排序问题
0.4.0 (2008-06-09)
更新了主体详情页面的页面模板
作为Beta版发布
0.3.6b (2008-06-02)
对组权限继承的一些杂项修复。
页面模板的一些杂项文本和布局更新。
0.3.6 (2008-05-25)
安全工具现在正确地从组继承。
0.3.5c (2008-05-24)
主要修复了文档和DocTests。
0.3.5b (2008-03-03)
修复了样式表不会在皮肤中显示的问题
将z3c.macro命名空间添加到configure.zcml中
0.3.5 (2008-03-02)
修复了SecurityTool皮肤仅在演示中声明的错误,现在在configure.zcml中声明了皮肤。
0.3.4 (2008-02-26)
修复了permDetails和principalDetails页面上的组问题
修复了securitytool视图被声明为zope.Public的错误
添加了SecurityTool皮肤以注册securitytool视图
0.3.3 (2008-02-21)
更新了CSS和样式
页面模板的清理
修复了权限详情页面
0.3.2 (2008-02-18)
更新了CSS和样式
页面模板的清理
更新了principalDetails以进行排序
修复了某些权限没有被适当删除的问题
0.3.1 (2008-02-07)
更新了接口和视图
更新了CSS和样式
页面模板的清理
更新principalDetails以显示所有数据
各种错误修复
为演示添加了一些更多的角色和权限。
0.3.0 (2008-02-07)
更新了接口和视图
页面模板的清理
在会话中存储选定的皮肤
各种错误修复
更好的项目描述
0.2.4 (2008-02-06)
修复了permDetails中的错误
更新了接口和视图
为演示添加了一些更多内容
0.2.3 (2008-01-29)
修复了与主体关联的所有权限没有正确填充的问题
0.2.2 (2008-01-28)
页面模板和CSS类的某些改进
更好的测试覆盖率和所有可用视图的“烟雾”测试
0.2.1 (2008-01-27)
修复了权限详情页面的错误
0.2.0 (2008-01-26)
z3c.securitytool的完整功能初始发布
0.2.1 (2008-01-26)
修复了主体详情页面的错误
项目详情
下载文件
下载适合您平台文件的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。
源分布
构建发行版
z3c.securitytool-0.5.1.tar.gz 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 23d51f828c1d6cde6c6b23596fc67ab1796d6d4254946cba7625fabfa53eef9f |
|
MD5 | 161fdc41c8e208fc27b38618772a7a26 |
|
BLAKE2b-256 | 5efc72625b46ef99d1afc81b682415512c97ece860b757bc7469c4288dfd3bca |
z3c.securitytool-0.5.1-py2.4.egg 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 0d250ccb3448b7d9115041fb69e166781961ac1a37ee7e6d731d1f5d3cc05317 |
|
MD5 | 4a1ab805ab15eb668ef30007a6223d74 |
|
BLAKE2b-256 | 3955dbca8808c3e9fdd07b9f8343a4583db2b9b11dd620531db31a8a62f9130c |