抽象
我已经发布了许多有关Derby的博客:
这本不打算是一个系列。 但是多年来,我越来越多地使用Derby。 我开始使用Derby作为微服务体系结构的数据库。 这些是个人使用的应用程序,因此Derby绰绰有余。 即使这些是个人使用的应用程序,我也需要具有有限用户权限的 多台服务器 ,当然还有数据库备份和还原 。 终要求是安全性。 我使用derby
usr帐户在Ubuntu Linux VM上运行Derby数据库。 尽管derby
usr帐户对VM的权限有限,但是任何额外的安全层都是好的。 因此,本博客的目的是演示如何使用Java安全策略运行Derby,以限制JVM的权限并增强运行时安全性。
免责声明
这篇文章仅供参考。 在使用所提供的任何信息之前,请认真思考。 从中学到东西,但终自己做出决定,风险自负。
要求
我使用以下主要技术完成了本文的所有工作。 您可能可以使用不同的技术或版本来做相同的事情,但不能保证。
- Apache Derby 10.14.2.0
- Java zulu11.39.15-ca-jdk11.0.7-linux_x64
我将不涉及下载和安装这些技术的过程。 我将其留给您练习。
注意从版本10.15开始,Derby项目已更新为使用Java 9模块系统。 结果,JAR文件已经发生了很大变化。 下面的security.policy不太可能与10.15+版本一起使用。 截至本博客的发布日期,我还没有尝试过。
Linux bash脚本
为了管理Derby使其与Java安全策略一起运行,您需要3个脚本。 个脚本将设置设置环境变量以配置Derby。 第二个脚本将启动Derby网络服务器,并传递正确的命令行参数。 第三台将停止Derby网络服务器。
清单1.1向您展示了这些脚本中的个。 它导出具有特定配置值的许多系统环境变量,这些配置值专门用于在您的环境中运行Derby。
清单1.1 – setenv.sh
#!/bin/bash export DERBY_HOME=/home/derby/opt/derby export PATH= "$DERBY_HOME/bin:$PATH" echo "DERBY_HOME=$DERBY_HOME" export JAVA_HOME=/home/derby/opt/java echo "JAVA_HOME=$JAVA_HOME" export NS_HOME=/var/local/derby/ 1527 mkdir -p $NS_HOME echo "NS_HOME=$NS_HOME" export NS_PORT= 1527 echo "NS_PORT=$NS_PORT" export NS_HOST= 0.0 . 0.0 echo "NS_HOST=$NS_HOST" export DERBY_OPTS= "" export DERBY_OPTS= "$DERBY_OPTS -Dderby.drda.host=$NS_HOST" export DERBY_OPTS= "$DERBY_OPTS -Dderby.drda.portNumber=$NS_PORT" export DERBY_OPTS= "$DERBY_OPTS -Dderby.system.home=$NS_HOME" # Security Policy export DERBY_OPTS= "$DERBY_OPTS -Dderby.stream.error.logSeverityLevel=0" export DERBY_OPTS= "$DERBY_OPTS -Dderby.security.port=$NS_PORT" export DERBY_OPTS= "$DERBY_OPTS -Dderby.install.url=file:$DERBY_HOME/lib/" export DERBY_OPTS= "$DERBY_OPTS -Djava.security.manager" export DERBY_OPTS= "$DERBY_OPTS -Djava.security.policy=$NS_HOME/security.policy"
DERBY_HOME不言自明。 这是解压缩(安装)Derby的地方。 将Derby的bin
目录添加到PATH
。
JAVA_HOME是不言自明的。 这是解压缩(安装)Java的地方。 将Java的bin
目录添加到PATH
。
NS_HOME是“N etwork 小号 erver家”。 这是Derby网络服务器将用于存储其配置和数据库的目录。 每当在此Derby网络服务器上创建新数据库时,都会在NS_HOME
下为新数据库创建一个新的子目录。 这允许在同一主机上运行的多个Derby网络服务器将其数据分开。
NS_PORT是“N etwork 小号 erver端口”。 这是Derby网络服务器用来侦听连接的端口。 这允许多个Derby网络服务器在同一主机上运行。
NS_HOST是“N etwork 小号 erver主机”。 它设置侦听连接时Derby网络服务器使用的网络接口。 默认情况下,Derby网络服务器仅在127.0.0.1
的环回地址上侦听连接。 此默认值表示客户端必须与网络服务器在同一主机上运行-不太有用。 通过将主机设置为0.0.0.0
,Derby网络服务器将侦听主机上任何网络接口上的连接。 如果您的VM具有多个网络接口,则应将NS_HOST
设置为这些接口之一的IP。 设置此值可使客户端成为远程客户端。
DERBY_OPTS是用于将所有配置选项获取到Derby的系统属性。 通过将适当的Derby系统属性及其关联值连接在一起来创建其值。 使用或不使用安全策略来启动Derby都需要前三个属性。
- derby.drda.host
- derby.drda.portNumber
- derby.system.home
配置Derby使其与安全策略一起运行时,需要后5个属性。
- derby.stream.error.logSeverityLevel
- derby.security.port
- derby.install.url
- java.security.manager
- java.security.policy
其中重要的特性之一是java.security.policy=$NS_HOME/security.policy"
。这个属性指向的值security.policy
文件,该文件将配置Java SecurityManager
,你会读到有关创建security.policy
文件接下来,您将看一下启动服务器的脚本。
清单1.2显示了这些脚本的第二个。 它会启动Derby网络服务器,并传递正确的命令行参数,因此Derby会以安全策略运行。
清单1.2 – start.sh
#!/bin/bash # Directory of the script SD=$( cd "$( dirname " ${BASH_SOURCE[ ]} " )" && pwd ) # Source in common variables source $SD/setenv.sh # Symlink the network server configurations ln -sf $SD/../conf/security.policy $NS_HOME/security.policy ln -sf $SD/../conf/derby.properties $NS_HOME/derby.properties startNetworkServer
SD是S CRIPT d irectory。 该评估确定start.sh
脚本的标准文件系统位置,并将其分配给SD
。 当引用其他脚本时,这很有用。
来源不言自明。 它在系统环境变量中来源以配置Derby网络服务器。 有关详细信息,请参见清单1.1。
Symlink配置适用于security.policy
文件和derby.properties
文件。 符号链接的目的是将这两个文件放入$NS_HOME
目录。 Derby在$NS_HOME
目录中寻找derby.properties
文件,因此它必须存在。 为了保持一致性(不是必需的),您还希望将security.policy
文件放在此处。 在清单1.1中, java.security.policy=$NS_HOME/security.policy"
属性配置了此位置。对于我的环境,我将$NS_HOME
目录与保存管理脚本和其他Derby配置文件的目录分开。我这样做是因为灾难恢复,我认为$NS_HOME
目录是$NS_HOME
,这意味着如果由于某种原因它丢失了(删除,磁盘驱动器错误,损坏,构建新的VM等),我必须能够恢复数据库数据,管理脚本( setenv.sh
, start.sh
, stop.sh
)和配置文件( security.policy
, derby.properties
从我的云备份)。 真正的配置文件的保留之外$NS_HOME
目录, start.sh
将它们在正确的位置符号链接。
startNetworkServer是Derby提供的脚本( $DERBY_HOME/bin
),用于启动网络服务器。 该DERBY_OPTS
变量-在设置setenv.sh
-用于配置网络服务器。 默认情况下,Derby使用有限的安全策略运行。 但是,由于配置了安全策略,因此Derby将使用您的配置而不是默认配置。
现在,您具有Derby服务器环境配置和启动脚本。 您还没有能够停止Derby网络服务器的功能。 停止服务器很容易。 您将查看下一个用于停止服务器的脚本。
注意仍然还需要security.policy
文件。 我保证,您将在短时间内阅读到有关它的信息!
清单1.3显示了这些脚本的第三个。 它将停止Derby网络服务器。 不太令人兴奋,但是对服务器进行有管理的关闭以防止数据损坏很重要。
清单1.3 – stop.sh
#!/bin/bash # Directory of the script SD=$( cd "$( dirname " ${BASH_SOURCE[ ]} " )" && pwd ) # Source in common variables source $SD/setenv.sh stopNetworkServer
所有这些都是不言自明的。 此脚本不需要进一步的注释。
security.policy文件
Derby随附一个演示安全策略文件。 它位于DERBY_HOME/demo/templates/security.policy
。 使用此文件作为起点,我能够生成满足以下要求的终版本:
- 网络(远程)访问
- 本地主机访问
- 启动
- 关掉
- 后备
清单2.1 – security.policy
- // // Licensed to the Apache Software Foundation (ASF) under one or more // contributor license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright ownership. // The ASF licenses this file to You under the Apache License, Version 2.0 // (the "License"); you may not use this file except in compliance with // the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // grant codeBase "${derby.install.url}derby.jar" {
- // These permissions are needed for everyday, embedded Derby usage.
- //
- permission java.lang.RuntimePermission "createClassLoader" ;
- permission java.util.PropertyPermission "derby.*" , "read" ;
- permission java.util.PropertyPermission "user.dir" , "read" ;
- permission org.apache.derby.security.SystemPermission "engine" , "usederbyinternals" ;
- // The next two properties are used to determine if the VM is 32 or 64 bit.
- //
- permission java.util.PropertyPermission "sun.arch.data.model" , "read" ;
- permission java.util.PropertyPermission "os.arch" , "read" ;
- permission java.io.FilePermission "${derby.system.home}" , "read" ;
- permission java.io.FilePermission "${derby.system.home}${/}-" ,
- "read,write,delete" ;
- // Needed by sysinfo. A file permission is needed to check the existence of
- // jars on the classpath. You can limit this permission to just the locations
- // which hold your jar files. This block is reproduced for all codebases
- // which include the sysinfo classes--the policy file syntax does not let you
- // grant permissions to several codebases all at once.
- //
- permission java.util.PropertyPermission "user.*" , "read" ;
- permission java.util.PropertyPermission "java.home" , "read" ;
- permission java.util.PropertyPermission "java.class.path" , "read" ;
- permission java.util.PropertyPermission "java.runtime.version" , "read" ;
- permission java.util.PropertyPermission "java.fullversion" , "read" ;
- permission java.lang.RuntimePermission "getProtectionDomain" ;
- permission java.io.FilePermission "java.runtime.version" , "read" ;
- permission java.io.FilePermission "java.fullversion" , "read" ;
- permission java.io.FilePermission "${derby.install.path}${/}-" , "read" ;
- permission java.io.FilePermission "/tmp${/}-" , "read,write,delete" ;
- // Permissions needed for JMX based management and monitoring.
- //
- // Allows this code to create an MBeanServer:
- //
- permission javax.management.MBeanServerPermission "createMBeanServer" ;
- // Allows access to Derby's built-in MBeans, within the domain
- // org.apache.derby. Derby must be allowed to register and unregister these
- // MBeans. To fine tune this permission, see the javadoc of
- // javax.management.MBeanPermission or the JMX Instrumentation and Agent
- // Specification.
- //
- permission javax.management.MBeanPermission
- "org.apache.derby.*#[org.apache.derby:*]" ,
- "registerMBean,unregisterMBean" ;
- // Trusts Derby code to be a source of MBeans and to register these in the
- // MBean server.
- //
- permission javax.management.MBeanTrustPermission "register" ;
- // Gives permission for jmx to be used against Derby but only if JMX
- // authentication is not being used. In that case the application would need
- // to create a whole set of fine-grained permissions to allow specific users
- // access to MBeans and actions they perform.
- //
- permission org.apache.derby.security.SystemPermission "jmx" , "control" ;
- permission org.apache.derby.security.SystemPermission "engine" , "monitor" ;
- permission org.apache.derby.security.SystemPermission "server" , "monitor" ;
- // getProtectionDomain is an optional permission needed for printing
- // classpath information to derby.log
- //
- permission java.lang.RuntimePermission "getProtectionDomain" ;
- // The following permission must be granted for Connection.abort(Executor) to
- // work. Note that this permission must also be granted to outer
- // (application) code domains.
- //
- permission java.sql.SQLPermission "callAbort" ;
- permission java.sql.SQLPermission "deregisterDriver" ;
- // Needed by FileUtil#limitAccessToOwner
- //
- permission java.lang.RuntimePermission "accessUserInformation" ;
- permission java.lang.RuntimePermission "getFileStoreAttributes" ; }; grant codeBase "${derby.install.url}derbynet.jar" {
- // These permissions lets the Network Server manage connections from clients.
- // Accept connections from any host. Derby is listening to the host interface
- // specified via the -h option to "NetworkServerControl start" on the command
- // line, via the address parameter to the
- // org.apache.derby.drda.NetworkServerControl constructor in the API or via
- // the property derby.drda.host; the default is localhost. You may want to
- // restrict allowed hosts, eg to hosts in a specific subdomain,
- // eg "*.example.com".
- //
- permission java.net.SocketPermission "*" , "accept" ;
- // Allow the server to listen to the socket on the port specified with the
- // -p option to "NetworkServerControl start" on the command line, or with
- // the portNumber parameter to the NetworkServerControl constructor in the
- // API, or with the property derby.drda.portNumber. The default is 1527.
- permission java.net.SocketPermission "localhost:${derby.security.port}" ,
- "listen" ;
- permission java.net.SocketPermission "${derby.drda.host}:${derby.security.port}" ,
- "listen" ;
- // Needed for server tracing.
- //
- permission java.io.FilePermission "${derby.drda.traceDirectory}${/}-" ,
- "read,write,delete" ;
- // Needed by FileUtil#limitAccessToOwner
- //
- permission java.lang.RuntimePermission "accessUserInformation" ;
- permission java.lang.RuntimePermission "getFileStoreAttributes" ;
- // Needed for NetworkServerMBean access (see JMX section above)
- //
- permission org.apache.derby.security.SystemPermission "server" ,
- "control,monitor" ;
- permission org.apache.derby.security.SystemPermission "engine" , "usederbyinternals" ;
- // Needed by sysinfo. A file permission is needed to check the existence of
- // jars on the classpath. You can limit this permission to just the locations
- // which hold your jar files. This block is reproduced for all codebases
- // which include the sysinfo classes--the policy file syntax does not let you
- // grant permissions to several codebases all at once.
- //
- permission java.util.PropertyPermission "user.*" , "read" ;
- permission java.util.PropertyPermission "java.home" , "read" ;
- permission java.util.PropertyPermission "java.class.path" , "read" ;
- permission java.util.PropertyPermission "java.runtime.version" , "read" ;
- permission java.util.PropertyPermission "java.fullversion" , "read" ;
- permission java.lang.RuntimePermission "getProtectionDomain" ;
- permission java.io.FilePermission "java.runtime.version" , "read" ;
- permission java.io.FilePermission "java.fullversion" , "read" ;
- permission java.io.FilePermission "${derby.install.path}${/}-" , "read" ;
- permission java.util.PropertyPermission "derby.*" , "read,write" ;
- permission java.net.SocketPermission "localhost:${derby.security.port}" , "connect,resolve" ;
- permission java.net.SocketPermission "${derby.drda.host}:${derby.security.port}" , "connect,resolve" ; }; grant codeBase "${derby.install.url}derbytools.jar" {
- // Needed by sysinfo. A file permission is needed to check the existence of
- // jars on the classpath. You can limit this permission to just the locations
- // which hold your jar files. This block is for all codebases which include
- // the sysinfo classes--the policy file syntax does not let you grant
- // permissions to several codebases all at once.
- //
- permission java.util.PropertyPermission "user.*" , "read" ;
- permission java.util.PropertyPermission "java.home" , "read" ;
- permission java.util.PropertyPermission "java.class.path" , "read" ;
- permission java.util.PropertyPermission "java.runtime.version" , "read" ;
- permission java.util.PropertyPermission "java.fullversion" , "read" ;
- permission java.lang.RuntimePermission "getProtectionDomain" ;
- permission java.io.FilePermission "<<ALL FILES>>" , "read" ;
- permission java.io.FilePermission "java.runtime.version" , "read" ;
- permission java.io.FilePermission "java.fullversion" , "read" ;
- permission java.util.PropertyPermission "*" , "read,write" ; }; grant codeBase "${derby.install.url}derbyclient.jar" {
- // Needed by sysinfo. A file permission is needed to check the existence of
- // jars on the classpath. You can limit this permission to just the locations
- // which hold your jar files. This block is reproduced for all codebases
- // which include the sysinfo classes--the policy file syntax does not let you
- // grant permissions to several codebases all at once.
- //
- permission java.util.PropertyPermission "user.*" , "read" ;
- permission java.util.PropertyPermission "java.home" , "read" ;
- permission java.util.PropertyPermission "java.class.path" , "read" ;
- permission java.util.PropertyPermission "java.runtime.version" , "read" ;
- permission java.util.PropertyPermission "java.fullversion" , "read" ;
- permission java.lang.RuntimePermission "getProtectionDomain" ;
- permission java.io.FilePermission "${derby.install.path}${/}-" , "read" ;
- // The following permission must be granted for Connection.abort(Executor) to
- // work. Note that this permission must also be granted to outer
- // (application) code domains.
- //
- permission java.sql.SQLPermission "callAbort" ;
- permission java.net.SocketPermission "localhost:${derby.security.port}" , "connect,resolve" ;
- permission java.net.SocketPermission "${derby.drda.host}:${derby.security.port}" , "connect,resolve" ; };
策略文件很多。使用Java 20年后,我只遇到过几次。 我不假装知道策略文件中的所有内容。 我所知道的是,此文件可满足我的所有要求。 每次Derby更新都需要进行测试,并且可能需要进行一些调整。 derby-users@db.apache.org邮件列表是您好的信息来源。
从derby-users@db.apache.org邮件列表向Rick Hillegas大声喊叫,以帮助我获得此版本的策略文件。 他提供了大部分内容,我添加了以下内容以满足我的要求。
第50行permission java.io.FilePermission "/tmp${/}-", "read,write,delete";
。 我的数据库备份过程使用CALL SYSCS_UTIL.SYSCS_BACKUP_DATABASE ('/tmp/resiste-backup/1527')
。 因此, derby.jar
文件需要对文件系统上/tmp
目录的读取,写入,删除权限,以便可以将备份写入该目录。
第92行permission java.sql.SQLPermission "deregisterDriver";
。 使用ij
工具管理我的Derby数据库时,在derby.log
文件中发现了关于deregisterDriver
的异常。 因此,我也将此权限添加到了derby.jar
文件中。
第160行permission java.net.SocketPermission "${derby.drda.host}:${derby.security.port}", "connect,resolve";
。 属性derby.drda.host
和derby.security.port
在设定setenv.sh
脚本(列表1.1)。 我必须添加此权限,因为远程(非本地主机)客户端可以访问我的Derby网络服务器。 在setenv.sh
,我用-Dderby.drda.host=0.0.0.0
覆盖默认的本地主机接口监听。 我还发现在测试stop.sh
脚本(清单1.3)时,我需要在策略文件中使用stop.sh
。
摘要
而已。 希望您喜欢学习如何使用安全策略来运行Derby网络服务器。
翻译自: https://www.javacodegeeks.com/2020/04/apache-derby-database-jvm-security-policy.html