第 21 章 安全性

Apache Karaf 提供高级、灵活的安全系统,它采用 OSGi 兼容,由 JAAS(Java 认证和授权服务)提供支持。

它提供动态安全系统。

在内部使用 Apache Karaf 安全框架来控制对以下的访问:

  • OSGi 服务(包括在开发人员指南中)
  • 控制台命令
  • JMX 层
  • WebConsole

您的应用程序也可以使用安全框架(请参阅开发人员指南)。

21.1. Realms

Apache Karaf 可以管理多个域。realm 包含要用于此域中身份验证和授权的登录模块的定义。登录模块为域定义身份验证和授权。

jaas:realm-list 命令列出当前定义的 realm:

karaf@root()> jaas:realm-list
Index | Realm Name | Login Module Class Name
-----------------------------------------------------------------------------------
1     | karaf      | org.apache.karaf.jaas.modules.properties.PropertiesLoginModule
2     | karaf      | org.apache.karaf.jaas.modules.publickey.PublickeyLoginModule

您可以看到 Apache Karaf 提供名为 karaf 的默认域。

这个 realm 有两个登录模块:

  • PropertiesLoginModule 使用 etc/users.properties 文件作为用户、组、角色和密码的后端。此登录模块验证用户并返回用户的角色。
  • public keyLoginModule 特别由 SSHd 使用。它使用 etc/keys.properties 文件。此文件包含与每个用户关联的用户和一个公钥。

Apache Karaf 提供其他登录模块(请参阅《开发人员指南》以了解详细信息):

  • JDBCLoginModule 使用数据库作为后端
  • LDAPLoginModule 使用 LDAP 服务器作为后端
  • SyncopeLoginModule 使用 Apache Syncope 作为后端
  • OsgiConfigLoginModule 使用配置作为后端
  • Krb5LoginModule 使用 Kerberos 服务器作为后端
  • GSSAPILdapLoginModule 使用 LDAP 服务器作为后端,但将 LDAP 服务器身份验证委托给其他后端(通常是 Krb5LoginModule)

您可以使用 jaas:realm-manage 命令管理现有 realm、login 模块或创建自己的域。

21.1.1. 用户、组、角色和密码

正如我们看到的那样,默认情况下,Apache Karaf 使用 PropertiesLoginModule。

此登录模块使用 etc/users.properties 文件作为用户、组、角色和密码的存储。

初始 etc/users.properties 文件包含:

################################################################################
#
#    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.
#
################################################################################

#
# This file contains the users, groups, and roles.
# Each line has to be of the format:
#
# USER=PASSWORD,ROLE1,ROLE2,...
# USER=PASSWORD,_g_:GROUP,...
# _g_\:GROUP=ROLE1,ROLE2,...
#
# All users, grousp, and roles entered in this file are available after Karaf startup
# and modifiable via the JAAS command group. These users reside in a JAAS domain
# with the name "karaf".
#
karaf = karaf,_g_:admingroup
_g_\:admingroup = group,admin,manager,viewer

我们可以在此文件中看到,默认情况下有一个用户 karaf。默认密码是 karaf

karaf 用户是一个组的成员: admingroup

个组始终以 g : 前缀。没有此前缀的条目是用户。

组定义了一组角色。默认情况下,admin group 定义组、adminmanagerviewer 角色。

这意味着 karaf 用户拥有 admingroup 定义的角色。

21.1.1.1. 命令

jaas:* 命令管理域中的域、用户、组、角色。

21.1.1.1.1. JAAS:realm-list

我们已在本节前面使用 jaas:realm-list

jaas:realm-list 命令列出每个域的域和登录模块:

karaf@root()> jaas:realm-list
Index | Realm Name | Login Module Class Name
-----------------------------------------------------------------------------------
1     | karaf      | org.apache.karaf.jaas.modules.properties.PropertiesLoginModule
2     | karaf      | org.apache.karaf.jaas.modules.publickey.PublickeyLoginModule

在这里有一个域(karaf),其中包含两个登录模块(PropertiesLoginModulePublickeyLoginModule)。

索引jaas:realm-manage 命令用来轻松识别我们要管理的 realm/login 模块。

21.1.1.1.2. JAAS:realm-manage

在 realm/login 模块编辑模式下的 jaas:realm-manage 命令切换,您可以在其中管理登录模块中的用户、组和角色。

要识别您要管理的域和登录模块,您可以使用 --index 选项。索引通过 jaas:realm-list 命令显示:

karaf@root()> jaas:realm-manage --index 1

另一种方法是使用 --realm--module 选项。domain 选项需要 realm 名称,-- module 选项需要 login 模块类名称:

karaf@root()> jaas:realm-manage --realm karaf --module org.apache.karaf.jaas.modules.properties.PropertiesLoginModule
21.1.1.1.3. JAAS:user-list

当您处于编辑模式时,您可以使用 jaas:user-list 列出登录模块中的用户:

karaf@root()> jaas:user-list
User Name | Group      | Role
--------------------------------
karaf     | admingroup | admin
karaf     | admingroup | manager
karaf     | admingroup | viewer

您可以根据角色查看用户名和组。

21.1.1.1.4. JAAS:user-add

jaas:user-add 命令在当前编辑的登录模块中添加一个新用户(以及密码):

karaf@root()> jaas:user-add foo bar

要"提交"您的更改(这里添加用户),您必须执行 jaas:update 命令:

karaf@root()> jaas:update
karaf@root()> jaas:realm-manage --index 1
karaf@root()> jaas:user-list
User Name | Group      | Role
--------------------------------
karaf     | admingroup | admin
karaf     | admingroup | manager
karaf     | admingroup | viewer
foo       |            |

另外,如果要回滚用户添加,可以使用 jaas:cancel 命令。

21.1.1.1.5. jaas:user-delete

jaas:user-delete 命令从当前编辑的登录模块中删除用户:

karaf@root()> jaas:user-delete foo

jaas:user-add 命令类似,您必须使用 jaas:update 来提交您的更改(或者 jaas:cancel to rollback):

karaf@root()> jaas:update
karaf@root()> jaas:realm-manage --index 1
karaf@root()> jaas:user-list
User Name | Group      | Role
--------------------------------
karaf     | admingroup | admin
karaf     | admingroup | manager
karaf     | admingroup | viewer
21.1.1.1.6. jaas:group-add

jaas:group-add 命令可以为当前编辑的登录模块中的用户分配一个组(并最终创建组):

karaf@root()> jaas:group-add karaf mygroup
21.1.1.1.7. jaas:group-delete

jaas:group-delete 命令可从当前编辑的登录模块中的组中删除用户:

karaf@root()> jaas:group-delete karaf mygroup
21.1.1.1.8. jaas:group-role-add

jaas:group-role-add 命令在当前编辑的登录模块的组中添加一个角色:

karaf@root()> jaas:group-role-add mygroup myrole
21.1.1.1.9. jaas:group-role-delete

jaas:group-role-delete 命令可从当前编辑的登录模块的组中删除角色:

karaf@root()> jaas:group-role-delete mygroup myrole
21.1.1.1.10. JAAS:update

jaas:update 命令会在登录模块后端提交您的更改。例如,如果是 PropertiesLoginModule,只有执行 jaas:update 命令后才会更新 etc/users.properties

21.1.1.1.11. JAAS:cancel

jaas:cancel 命令回滚您的更改,不更新登录模块后端。

21.1.2. 密码加密

默认情况下,密码以明文形式存储在 etc/users.properties 文件中。

可以在 etc/org.apache.karaf.jaas.cfg 配置文件中启用加密:

################################################################################
#
#    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.
#
################################################################################

#
# Boolean enabling / disabling encrypted passwords
#
encryption.enabled = false

#
# Encryption Service name
#   the default one is 'basic'
#   a more powerful one named 'jasypt' is available
#       when installing the encryption feature
#
encryption.name =

#
# Encryption prefix
#
encryption.prefix = {CRYPT}

#
# Encryption suffix
#
encryption.suffix = {CRYPT}

#
# Set the encryption algorithm to use in Karaf JAAS login module
# Supported encryption algorithms follow:
#   MD2
#   MD5
#   SHA-1
#   SHA-256
#   SHA-384
#   SHA-512
#
encryption.algorithm = MD5

#
# Encoding of the encrypted password.
# Can be:
#   hexadecimal
#   base64
#
encryption.encoding = hexadecimal

如果启用 encryption.enabled y 被设置为 true,则启用密码加密。

启用加密后,密码在第一次登录时会加密。加密的密码带有 \{CRYPT\} 的前缀和后缀。要重新加密密码,您可以以明文( etc/users.properties 文件中)重置密码,而无需 \{CRYPT\} 前缀和后缀。Apache Karaf 将检测此密码处于明确状态(因为它没有带有 \{CRYPT\} 前缀并后缀),然后再次对其进行加密。

etc/org.apache.karaf.jaas.cfg 配置文件允许您定义高级加密机制:

  • encryption.prefix 属性将前缀定义为"flag"密码进行加密。默认值为 \{CRYPT\}。
  • encryption.suffix 属性定义"flag"密码加密的后缀。默认值为 \{CRYPT\}。
  • encryption.algorithm 属性定义用于加密的算法(digest)。可能的值有 MD2MD5SHA-1SHA-256SHA-384SHA-512。默认值为 MD5
  • encryption.encoding 属性定义加密密码的编码。可能的值有 十六进制base64。默认值为 十六进制

21.1.3. 通过密钥管理身份验证

对于 SSH 层,chronyc 支持通过密钥进行身份验证,允许在不提供密码的情况下登录。

SSH 客户端(因此 bin/client 由 Karaf 本身提供),或者任何 ssh 客户端(如 OpenSSH)使用公钥/私钥对,它将标识自己在 Karaf SSHD(服务器端)上的 public/私钥对。

允许连接的密钥存储在 etc/keys.properties 文件中,其格式如下:

user=key,role

默认情况下,Packspace 允许 karaf 用户的密钥:

# karaf=AAAAB3NzaC1kc3MAAACBAP1/U4EddRIpUt9KnC7s5Of2EbdSPO9EAMMeP4C2USZpRV1AIlH7WT2NWPq/xfW6MPbLm1Vs14E7gB00b/JmYLdrmVClpJ+f6AR7ECLCT7up1/63xhv4O1fnxqimFQ8E+4P208UewwI1VBNaFpEy9nXzrith1yrv8iIDGZ3RSAHHAAAAFQCXYFCPFSMLzLKSuYKi64QL8Fgc9QAAAIEA9+GghdabPd7LvKtcNrhXuXmUr7v6OuqC+VdMCz0HgmdRWVeOutRZT+ZxBxCBgLRJFnEj6EwoFhO3zwkyjMim4TwWeotUfI0o4KOuHiuzpnWRbqN/C/ohNWLx+2J6ASQ7zKTxvqhRkImog9/hWuWfBpKLZl6Ae1UlZAFMO/7PSSoAAACBAKKSU2PFl/qOLxIwmBZPPIcJshVe7bVUpFvyl3BbJDow8rXfskl8wO63OzP/qLmcJM0+JbcRU/53JjTuyk31drV2qxhIOsLDC9dGCWj47Y7TyhPdXh/0dthTRBy6bqGtRPxGa7gJov1xm/UuYYXPIUR/3x9MAZvZ5xvE0kYXO+rx,admin
注意

出于安全考虑,这个密钥已被禁用。我们鼓励每个客户端创建密钥对,并更新 etc/keys.properties 文件。

创建密钥对的最简单方法是使用 OpenSSH。

您可以使用以下命令创建密钥对:

ssh-keygen -t dsa -f karaf.id_dsa -N karaf

您现在有公钥和私钥:

-rw-------  1 jbonofre jbonofre    771 Jul 25 22:05 karaf.id_dsa
-rw-r--r--  1 jbonofre jbonofre    607 Jul 25 22:05 karaf.id_dsa.pub

您可以在 etc/keys.propertieskaraf.id_dsa.pub 文件的内容中复制:

karaf=AAAAB3NzaC1kc3MAAACBAJLj9vnEhu3/Q9Cvym2jRDaNWkATgQiHZxmErCmiLRuD5Klfv+HT/+8WoYdnvj0YaXFP80phYhzZ7fbIO2LRFhYhPmGLa9nSeOsQlFuX5A9kY1120yB2kxSIZI0fU2hy1UCgmTxdTQPSYtdWBJyvO/vczoX/8I3FziEfss07Hj1NAAAAFQD1dKEzkt4e7rBPDokPOMZigBh4kwAAAIEAiLnpbGNbKm8SNLUEc/fJFswg4G4VjjngjbPZAjhkYe4+H2uYmynry6V+GOTS2kaFQGZRf9XhSpSwfdxKtx7vCCaoH9bZ6S5Pe0voWmeBhJXi/Sww8f2stpitW2Oq7V7lDdDG81+N/D7/rKDD5PjUyMsVqc1n9wCTmfqmi6XPEw8AAACAHAGwPn/Mv7P9Q9+JZRWtGq+i4pL1zs1OluiStCN9e/Ok96t3gRVKPheQ6IwLacNjC9KkSKrLtsVyepGA+V5j/N+Cmsl6csZilnLvMUTvL/cmHDEEhTIQnPNrDDv+tED2BFqkajQqYLgMWeGVqXsBU6IT66itZlYtrq4v6uDQG/o=,admin

然后,指定客户端使用 karaf.id_dsa 私钥:

bin/client -k ~/karaf.id_dsa

或 ssh

ssh -p 8101 -i ~/karaf.id_dsa karaf@localhost

21.1.4. RBAC

Apache Karaf 使用角色来控制对资源的访问:它是 RBAC(基于角色的访问控制)系统。

角色可用于控制:

  • 了解 OSGi 服务
  • 访问控制台(控制命令的执行)
  • 访问 JMX(MBeans 和/或操作)
  • 访问 WebConsole

21.1.4.1. OSGi 服务

有关 OSGi 服务 RBAC 支持的详细信息,请参阅开发人员指南。

21.1.4.2. 控制台(Console)

控制台 RBAC 支持对 OSGi 服务 RBAC 的分类。实际上,在 Apache Karaf 中,所有控制台命令都定义为 OSGi 服务。

控制台命令名称采用 scope:name 格式。

ACL(Access Lists)在 etc/org.apache.karaf.command.acl.<scope>.cfg 配置文件中定义,其中 &lt ;scope&gt; 是命令范围。

例如,我们可以通过创建 etc/org.apache.karaf.command.feature.cfg 配置文件来定义对功能的 ACL :* 命令。在这个 etc/org.apache.karaf.command.acl.feature.cfg 配置文件中,我们可以设置:

list = viewer
info = viewer
install = admin
uninstall = admin

在这里,我们定义了 该功能:listfeature:info 命令可由具有 viewer 角色的用户执行,而 feature:installfeature:uninstall 命令只能由具有 admin 角色的用户执行。请注意,admin 组中的用户也具有查看器角色,因此能够完成所有操作。

Apache Karaf 命令 ACL 可以使用 (在指定命令范围内)控制访问:

  • 命令名称 regex(如 name = role
  • 命令名称和选项或参数值 regex(例如,名称[/.[/.[0-90-9][0-9]+./] = role 只能执行名称,且值为 100 以上)

命令名称和选项/参数都支持完全匹配或正则表达式匹配。

默认情况下,Apache Karaf 定义以下命令 ACL:

  • etc/org.apache.karaf.command.acl.bundle.cfg 配置文件定义 bundle:* 命令的 ACL。此 ACL 仅将 bundle:* 命令的执行限制为具有 admin 角色的用户,而非系统捆绑包的 bundle:* 命令可由具有 manager 角色的用户执行。
  • etc/org.apache.karaf.command.acl.config.cfg 配置文件定义了 config:* 命令的 ACL。此 ACL 使用 jmx.acl.*org.apache.karaf.command.acl.*org.apache.karaf.service.acl.* 配置 PID 将 config:* 命令限制为具有 admin 角色的用户。对于其他配置 PID,具有 manager 角色的用户可以执行 config:* 命令。
  • etc/org.apache.karaf.command.acl.feature.cfg 配置文件定义 feature:* 命令的 ACL。只有具有 admin 角色的用户才能执行 feature:installfeature:uninstall 命令。其它 功能:* 命令可以由任何用户执行。
  • etc/org.apache.karaf.command.acl.jaas.cfg 配置文件定义了 jaas:* 命令的 ACL。只有具有 admin 角色的用户才能执行 jaas:update 命令。其它 jaas:* 命令可由任何用户执行。
  • etc/org.apache.karaf.command.acl.kar.cfg 配置文件为 kar:* 命令定义 ACL。只有具有 admin 角色的用户才能执行 kar:installkar:uninstall 命令。其他 kar:* 命令可由任何用户执行。
  • etc/org.apache.karaf.command.acl.shell.cfg 配置文件定义了 shell 的 ACL:* 和 "direct" 命令。只有具有 admin 角色的用户才能执行 shell:editshell:execshell:new、和 shell:java 命令。其他 shell:* 命令可以由任何用户执行。

您可以更改这些默认 ACL,并为附加命令范围添加您自己的 ACL(例如,如 etc/org.apache.karaf.command.acl.cluster.cfg for Apache Karaf Ce llar 等/org.apache.karaf.command.acl.camel.cfg )。

您可以通过编辑 etc/system.properties 中的 karaf.secured.services 属性来微调命令 RBAC 支持:

#
# By default, only Karaf shell commands are secured, but additional services can be
# secured by expanding this filter
#
karaf.secured.services = (&(osgi.command.scope=*)(osgi.command.function=*))

21.1.4.3. JMX

与控制台命令类似,您可以定义 ACL(AccessLists)到 JMX 层。

JMX ACL 在 etc/jmx.acl<ObjectName>.cfg 配置文件中定义,其中 <ObjectName > 是一个 MBean 对象名称(例如 org.apache.karaf.bundle 代表 org.apache.karaf;type=Bundle MBean)。

etc/jmx.acl.cfg 是最通用的配置文件,在找不到特定配置文件时使用。它包含"全局"ACL 定义。

JMX ACL 可以使用 (在 JMX MBean 旁边)控制访问:

  • 操作名称 regex(如 operation* = role
  • 操作参数值 regex(如 operation(java.lang.String, int)[/([1-4])?[0-9]/,/.*/] = role

默认情况下,Apache Karaf 定义以下 JMX ACL:

  • etc/jmx.acl.org.apache.karaf.bundle.cfg 配置文件定义 org.apache.karaf:type=bundle MBean 的 ACL。此 ACL 限制 setStartLevel()start()stop()update() 操作,仅适用于具有 admin 角色的用户。其他操作可以由具有 manager 角色的用户执行。
  • etc/jmx.acl.org.apache.karaf.config.cfg 配置文件定义 org.apache.karaf:type=config MBean 的 ACL。此 ACL 对 jmx.acl*org.apache.karaf.command.acl*org.apache.karaf.service.acl* 配置 PID 仅限具有 admin 角色的用户进行限制。其他操作可以由具有 manager 角色的用户执行。
  • etc/jmx.acl.org.apache.karaf.security.jmx.cfg 配置文件定义 org.apache.karaf:type=security,area=jmx MBean 的 ACL。这个 ACL 限制了具有 viewer 角色的用户调用 canInvoke() 操作。
  • etc/jmx.acl.osgi.compendium.cm.cfg 配置文件为 osgi.compendium:type=cm MBean 定义 ACL。这个 ACL 会限制 jmx.acl*org.apache.karaf.command.acl*org.apache.karaf.service.acl* 配置 PID 的配置 PID。其他操作可以由具有 manager 角色的用户执行。
  • etc/jmx.acl.java.lang.Memory.cfg 配置文件为核心 JVM 内存 MBean 定义 ACL。这个 ACL 限制了 gc 操作只对具有 manager 角色的用户的调用。
  • etc/jmx.acl.cfg 配置文件是最通用的文件。此处定义的 ACL 不在其他特定 ACL 匹配时使用(根据特定 ACL,它在另一个 MBean 特定 etc/jmx.acl.*.cfg 配置文件中定义的 ACL)。list*(), get*() 是*() 操作,可由具有 viewer 角色的用户执行。set*() 和所有其他 *() 操作都可以由具有 admin 角色的用户执行。

21.1.4.4. WebConsole

默认情况下,Apache Karaf WebConsole 不可用。要启用它,您必须安装 webconsole 功能:

karaf@root()> feature:install webconsole

WebConsole 不支持现在不支持精细的 RBAC,如 console 或 JMX。

具有 admin 角色的所有用户可以登录 WebConsole 并执行任何操作。

21.1.5. SecurityMBean

Apache Karaf 提供了一个 JMX MBean,可检查当前用户是否可以调用给定的 MBean 和/或操作。

canInvoke() 操作获取当前用户的角色,并检查一个角色是否可以调用 MBean 和/或操作,最后使用一个给定参数值。

21.1.5.1. 操作

  • 如果当前用户可以使用 objectName 调用 MBean,则 canInvoke(objectName) 会返回 true
  • 如果当前用户可以使用 objectName 的 MBean 调用 operation methodName,则 canInvoke(objectName, methodName) 会返回 true
  • 如果当前用户可以使用带有 objectName 的参数类型参数Types 数组调用 operation methodName,则 canInvoke(objectName, methodName, argumentTypes ) 返回 true
  • canInvoke(bulkQuery) 返回一个表格数据,如果 canInvoketruefalse,则返回包括为 bulkQuery tabular data 的每个操作的表格数据。

21.1.6. 安全供应商

有些应用程序需要特定的安全供应商可用,如 [BouncyCastle|http://www.bouncycastle.org]。

JVM 对使用这些 jars 的一些限制施加一些限制:它们必须经过签名并在引导类路径中可用。

部署这些提供程序的一种方法是将它们放到 $JAVA_HOME/jre/lib/ext 的 JRE 文件夹中,再修改安全策略配置($JAVA_HOME/jre/lib/security/java.security.security),才能注册这些提供程序。

虽然此方法可以正常工作,但它具有全局效果,但需要您相应地配置所有服务器。

Apache Karaf 提供配置额外安全提供程序的简单方法:* 将供应商 jar 放在 lib/ext * 中修改 etc/config.properties 配置文件以添加以下属性

org.apache.karaf.security.providers = xxx,yyy

此属性的值是要注册的供应商类名称的逗号分隔列表。

例如,要添加 bouncycastle 安全供应商,您可以定义:

org.apache.karaf.security.providers = org.bouncycastle.jce.provider.BouncyCastleProvider

另外,您可能想要从系统捆绑包中提供对这些供应商的类的访问权限,以便所有捆绑包都可以访问它们。

这可以通过修改同一配置文件中的 org.osgi.framework.bootdelegation 属性来实现:

org.osgi.framework.bootdelegation = ...,org.bouncycastle*