GeoMesa授权¶
本教程演示了将数据级安全性应用于GeoMesa的方法。这是一个更高级的教程;您应该已经熟悉了GeoMesa和Geoserver的基础知识。本教程的目标是Acumulo-GeoMesa也通过相同的机制支持HBase可见性,但这里不介绍所需的HBase配置。看见 HBase可见性 有关HBase的更多信息。
在本教程中,您将学习如何:
设置数据在接收到GeoMesa期间的可见性
通过GeoMesa对您的查询应用授权
通过GeoMesa Geoserver插件实施用户授权,使用PKI证书通过Geoserver进行身份验证,并使用LDAP存储授权
背景¶
可见性和授权¶
Acumulo最强大的功能之一是实现单元级安全,使用 visibilities 和 authorizations 。受可见性保护的数据只能由拥有相应授权的用户查看。这允许基于任意标签对数据进行细粒度保护。
备注
授权不同于表级权限,其操作粒度要精细得多。
公钥基础设施(PKI)¶
公钥基础设施可用于对终端用户进行安全身份验证。在公钥基础设施中, certificate authority (CA)将颁发数字证书,以验证特定公钥属于特定个人。然后,其他用户可以信任该证书,因为它已由CA数字签名。
在本教程中,使用的密钥不是由受信任的CA提供的。因此,有必要将CA的证书导入Java密钥库,这允许Java(以及扩展Tomcat)信任由CA验证的任何密钥。
公钥基础设施解决了 authentication ( who 用户是)但不是 authorization ( what 用户可以这样做)。在本教程中,授权是由一个LDAP服务器提供的。
先决条件¶
在开始之前,您必须具备以下条件:
Java JDK 1.8
Apache Maven 3.6 or later
GitHub客户端
一场积雨 2.0 or 2.1 实例
同时具有CREATE-TABLE和WRITE权限的Acumulo用户
为您的实例安装的GeoMesa分布式运行时
如果您不熟悉Acumulo授权,您应该查看相关的Acumulo documentation 。
关于本教程¶
本教程通过插入数千个要素,然后查询这些要素来进行操作。这些功能插入了可见性标签,然后向两个不同的用户查询,以显示授权是如何工作的。
GeoMesa中的可见性¶
GeoMesa支持为编写的每个功能设置可见性。这可以通过简单功能中的用户数据进行设置:
SimpleFeature sf = ...;
// set user data directly
sf.getUserData().put(SecurityUtils.FEATURE_VISIBILITY, "user&admin");
// alternatively, use static utility methods
org.locationtech.geomesa.security.SecurityUtils.setFeatureVisibilities(sf, "user", "admin");
有关要素级别可见性的详细信息,请参阅 功能级可见性和安全性 。
GeoMesa中的授权¶
执行查询时,GeoMesa将检索授权委托给 service providers 它们实现了以下接口:
package org.locationtech.geomesa.security;
public interface AuthorizationsProvider {
/**
* Gets the authorizations for the current context. This may change over time
* (e.g. in a multi-user environment), so the result should not be cached.
*
* @return
*/
List<String> getAuthorizations();
/**
* Configures this instance with parameters passed into the DataStoreFinder
*
* @param params
*/
void configure(Map<String, Serializable> params);
}
当一个地理台地 DataStore
is instantiated, it will scan for available service providers. Third-party implementations can be enabled by placing them on the classpath and including a special service descriptor file. See the Oracle Javadoc 有关实施服务提供商的详细信息,请参阅。
地理台地 DataStore
会打来电话 configure()
在 AuthorizationsProvider
实现,将参数映射从调用传递到 DataStoreFinder.getDataStore(Map params)
。这允许 AuthorizationsProvider
根据环境进行自我配置。
以确保正确的 AuthorizationsProvider
如果在类路径上发现多个第三方服务提供商,则GeoMesa将抛出异常。在此方案中,要使用的特定服务提供程序类可由以下系统属性指定:
AuthorizationsProvider.AUTH_PROVIDER_SYS_PROPERTY = "geomesa.auth.provider.impl";
对于简单的场景,可在创建GeoMesa时指定应用于所有查询的授权集 DataStore
通过使用 geomesa.security.auths
配置参数。这将使用 DefaultAuthorizationsProvider
由GeoMesa提供的实现。
// create a map containing initialization data for the GeoMesa data store
Map<String, String> configuration = new HashMap<>();
configuration.put("geomesa.security.auths", "user,admin");
DataStore dataStore = DataStoreFinder.getDataStore(configuration);
如果没有 AuthorizationsProvider
类路径上发现的S,以及 geomesa.security.auths
参数,则GeoMesa将默认使用与基础Acumulo连接相关联的授权(即 accumulo.user
配置值)。
警告
对于生产系统,这不是推荐的方法。
另外,请注意,任何场景中使用的授权都不能超过底层Acumulo连接的授权。
在Acumulo中创建可见性¶
本教程要求您指定可见性字符串和关联的授权字符串。可见性可以是对您的Acumulo实例有效的任何内容。在本练习的其余部分中,我们将假定可见性字符串为 user
。您可以通过AcumuloShell查看当前为您的用户启用的可见性:
$ accumulo shell -u <username> -p <password>
一旦进入Shell:
> getauths
user,admin
如果您的用户还没有授权,您可以通过AcumuloShell使用 addauths
命令:
> getauths
user
> addauths -s admin -u myuser
> getauths
user,admin
备注
除非用户具有System.ALTER_USER权限,否则该用户无法设置授权。
运行完教程代码后,当您通过AcumuloShell扫描索引表时,您应该会看到方括号中的可见性标签:
> scan -t mytable_id
\x0100700230-fdfe-422e-b4d1-8072db6f3dda SFT: [user] \x02\x00\x00\x01b00700230...
下载并构建教程¶
在您的计算机上选择一个合理的目录,然后运行:
$ git clone https://github.com/geomesa/geomesa-tutorials.git
$ cd geomesa-tutorials
警告
确保下载或检出与您的GeoMesa版本对应的教程项目版本。看见 关于教程版本 了解更多详细信息。
若要确保快速入门适用于您的环境,请修改 pom.xml
为Acumulo、Hadoop等设置适当的版本。
为了便于使用,该项目构建了一个捆绑的构件,该构件在单个JAR中包含所有必需的依赖项。要构建,请运行:
$ mvn clean install -pl geomesa-tutorials-accumulo/geomesa-tutorials-accumulo-authorizations -am
运行教程¶
在命令行上,运行:
$ java -cp geomesa-tutorials-accumulo/geomesa-tutorials-accumulo-authorizations/target/geomesa-tutorials-accumulo-authorizations-${geomesa.version}.jar \
org.geomesa.example.accumulo.auths.AuthorizationsTutorial \
--accumulo.instance.name <instance> \
--accumulo.zookeepers <zookeepers> \
--accumulo.user <user> \
--accumulo.password <password> \
--accumulo.catalog <table> \
--geomesa.security.auths <authorizations> \
--visibilities <visibilities>
其中,您可以提供以下参数:
<instance>
您的Acumulo实例的名称<zookeepers>
您的ZooKeeper节点,用逗号分隔<user>
有权创建、读取和写入表的Acumulo用户的名称<password>
前面提到的Acumulo用户的密码<table>
将接受这些测试记录的目标表的名称。此表不应存在或应为空<visibilities>
the visibilities label to apply to the data, e.g.user
<authorizations>
与您选择的可见性关联的授权,例如user
。确保您的Acumulo用户拥有您使用的授权
警告
如果已将GeoMesa Acumulo分布式运行时设置为在命名空间内隔离(请参见 命名空间安装 )的价值 <table>
应包括命名空间(例如 myNamespace.geomesa
)。
您还可以指定教程应在完成后删除其数据。使用 --cleanup
标志,当您运行以启用此行为时。
运行后,您应该会看到以下输出:
Loading datastore
Loading datastore
Creating schema: GLOBALEVENTID:String,Actor1Name:String,Actor1CountryCode:String,Actor2Name:String,Actor2CountryCode:String,EventCode:String,NumMentions:Integer,NumSources:Integer,NumArticles:Integer,ActionGeo_Type:Integer,ActionGeo_FullName:String,ActionGeo_CountryCode:String,dtg:Date,geom:Point
Generating test data
Writing test data
Wrote 2356 features
Executing query with AUTHORIZED data store: auths are 'user'
Running query dtg BETWEEN 2017-12-31T00:00:00+00:00 AND 2018-01-02T00:00:00+00:00 AND BBOX(geom, -83.0,33.0,-80.0,35.0)
01 719024887=719024887|DEPUTY||||010|4|1|4|3|Abbeville County, South Carolina, United States|US|2017-12-31T00:00:00.000Z|POINT (-82.4665 34.2334)
02 719024893=719024893|UNITED STATES|USA|DEPUTY||010|6|1|6|3|Abbeville County, South Carolina, United States|US|2017-12-31T00:00:00.000Z|POINT (-82.4665 34.2334)
03 719024895=719024895|UNITED STATES|USA|EMPLOYEE||010|2|1|2|3|Ninety Six, South Carolina, United States|US|2017-12-31T00:00:00.000Z|POINT (-82.024 34.1751)
04 719025110=719025110|||UNITED STATES|USA|051|6|1|6|3|Edgefield, South Carolina, United States|US|2018-01-01T00:00:00.000Z|POINT (-81.9296 33.7896)
05 719025605=719025605|SCHOOL||ADMINISTRATION||043|16|1|16|3|Greenwood County, South Carolina, United States|US|2018-01-01T00:00:00.000Z|POINT (-82.1165 34.1668)
06 719025410=719025410|POLICE||||193|1|1|1|3|Ninety Six National Historic Site, South Carolina, United States|US|2018-01-01T00:00:00.000Z|POINT (-82.0193 34.146)
07 719027188=719027188|UNITED STATES|USA|UNITED STATES|USA|193|1|1|1|3|Ware Shoals, South Carolina, United States|US|2018-01-01T00:00:00.000Z|POINT (-82.2468 34.3985)
08 719024941=719024941|||DEPUTIES||090|8|1|8|3|Edgewood, South Carolina, United States|US|2018-01-01T00:00:00.000Z|POINT (-80.6137 34.2874)
09 719024950=719024950|||DEPUTIES||190|8|1|8|3|Edgewood, South Carolina, United States|US|2018-01-01T00:00:00.000Z|POINT (-80.6137 34.2874)
10 719024894=719024894|UNITED STATES|USA|DEPUTY||010|2|1|2|3|Abbeville County, South Carolina, United States|US|2017-12-31T00:00:00.000Z|POINT (-82.4665 34.2334)
Returned 39 total features
Executing query with UNAUTHORIZED data store: auths are ''
Running query dtg BETWEEN 2017-12-31T00:00:00+00:00 AND 2018-01-02T00:00:00+00:00 AND BBOX(geom, -83.0,33.0,-80.0,35.0)
Returned 0 total features
Done
第一个查询应返回1个或多个结果。第二个查询应该返回0个结果,因为它们被可见性隐藏。
看《守则》¶
源代码对于本教程来说是可以访问的。主要逻辑包含在 org.geomesa.example.accumulo.auths.AuthorizationsTutorial
在 geomesa-tutorials-accumulo/geomesa-tutorials-accumulo-authorizations
模块。一些相关的方法包括:
createDataStore
使用系统属性控制每个数据存储使用的可见性提供程序queryFeatures
对每个数据存储运行相同的查询
// get an instance of the data store that uses our authorizations provider,
// that always returns empty auths
System.setProperty(AuthorizationsProvider.AUTH_PROVIDER_SYS_PROPERTY,
EmptyAuthorizationsProvider.class.getName());
unauthorizedDatastore = super.createDataStore(params);
// get an instance of the data store that uses the default authorizations provider,
// which will use whatever auths the connector has available
System.setProperty(AuthorizationsProvider.AUTH_PROVIDER_SYS_PROPERTY,
DefaultAuthorizationsProvider.class.getName());
return super.createDataStore(params);
此代码片断显示如何指定 AuthorizationProvider
与系统属性一起使用。这个 DefaultAuthorizationsProvider
类由GeoMesa提供,并在找不到其他实现时使用。
这个 EmptyAuthorizationsProvider
类包含在本教程中。这个 EmptyAuthorizationsProvider
将始终返回空的 Authorizations
对象,这意味着不会返回以可见性存储的任何数据。
有一种更有用的实现 AuthorizationsProvider
这将在下一节中更详细地讨论 LdapAuthorizationsProvider
。
使用PKIS和LDAP将授权和可见性应用于Geoserver¶
本节将向您展示如何配置Geoserver以使用PKI对用户进行身份验证、使用LDAP存储授权以及基于每个用户/每个查询应用授权。
基本用户身份验证将通过用户证书进行。每个用户都将拥有自己的公钥/私钥对来唯一地标识他们。
用户授权将来自ldap。一旦通过PKI验证了用户的身份,我们将在LDAP中查找该用户的详细信息。
获得用户的身份验证和授权后,我们将使用自定义 AuthorizationsProvider
实施。
在Tomcat中运行Geoserver¶
备注
如果您已经在Tomcat中运行Geoserver,则可以跳过此步骤。
Geoserver默认附带嵌入式Jetty Servlet。为了使用PKI登录,我们需要将其安装在Tomcat中。
下载并安装 Tomcat 9 。
创建一个指向Tomcat安装的环境变量(您可能希望将其添加到bash init脚本中):
$ export CATALINA_HOME=/path/to/tomcat
如果要重复使用现有的Geoserver配置,请创建一个指向Geoserver数据目录的环境变量(您可能希望将其添加到您的Shell初始化脚本中):
$ export GEOSERVER_DATA_DIR=/path/to/geoserver/data_dir
将Geoserver Web应用程序从Geoserver分发版复制到Tomcat Servlet中:
$ cp -r /path/to/geoserver/webapps/geoserver/ $CATALINA_HOME/webapps/
增加分配给Tomcat的内存,以便在Geoserver中运行复杂查询(此处的值可能不适用于所有安装):
$ cd $CATALINA_HOME/bin $ echo 'CATALINA_OPTS="-Xmx2g -XX:MaxPermSize=128m"' >> setenv.sh
启动Tomcat,作为服务或通过启动脚本,并确保Geoserver在http://localhost:8080/geoserver/web/.上可用
在Geoserver中创建Acumulo数据存储和图层¶
使用您的用户和密码凭据登录到Geoserver。点击“商店”和“添加新商店”。选择 Accumulo (GeoMesa)
矢量数据源,并填写所需参数。
基本店铺信息:
workspace
这取决于您的Geoserver安装data source name
pick a sensible name, such asgeomesa_authorizations
description
this is strictly decorative;GeoMesa authorizations tutorial
连接参数:
这些参数值与您在运行本教程时在命令行上提供的参数值相同;它们描述了如何连接到数据所在的Acumulo实例
geomesa.security.auths
将此字段留空
点击“保存”,Geoserver将在您的累积表中搜索任何GeoMesa管理的要素类型。
发布该层¶
Geoserver应该识别 gdelt-secure
要素类型,并应将其显示为可发布的图层。点击“发布”链接。
您将被带到“编辑层”屏幕。您需要为数据边框输入值。在这种情况下,您可以单击链接以根据数据计算这些值。
完成后,请单击“保存”按钮。
配置Geoserver以进行PKI登录¶
按照Geoserver中的说明操作 documentation 以启用PKI登录到Geoserver。
在将‘cert’过滤器添加到‘Filter Chains’的步骤中,还要将其添加到‘Rest’、‘GWC’和‘Default’链(除Web之外)。
我们将使用‘rod’和‘Scott’用户,因此请确保将它们安装到您的浏览器中。
警告
确保您点击了所有Geoserver屏幕上的“保存”按钮。否则,您的更改可能会丢失。
通过重新启动Tomcat并检查‘web’筛选器链是否选择了‘cert’筛选器来验证更改是否已应用:

Web筛选器面板¶
安装用于存储授权的LDAP服务器¶
备注
如果您已经设置了一个LDAP服务器,则可以跳过此步骤。
下载并安装 ApacheDS
作为服务运行,或通过启动脚本运行:
$ cd apacheds-2.0.0-M20/bin
$ chmod 755 *.sh
$ ./apacheds.sh
配置用于存储授权的LDAP¶
我们希望使用与我们正在测试的Spring Security PKI相匹配的用户来配置LDAP。我们希望的最终结果是创建以下用户:
DN: cn=rod,ou=Spring Security,o=Spring Framework
为此,我们将使用ApacheDirectoryStudio。
下载并运行 Apache Directory Studio 。
按照说明连接到您的LDAP实例(ApacheDS here (注:除非您愿意,否则不需要更改密码)。
为我们的数据创建分区:
右键单击“Connection”选项卡下的“ApacheDS(Localhost)”条目,然后选择“Open Configuration”。
点击‘高级分区配置...’。
点击‘添加’。
将ID字段设置为‘Spring框架’。
将Suffix字段设置为‘o=Spring框架’。
取消选中“从后缀dn自动生成上下文项”。
在上下文条目中设置以下属性:
对象类:ExtensibleObject
对象类:顶部
对象类:域
DC:弹簧框架2
O:弹簧框架2
命中 Ctrl-s 以保存分区。ApacheDS Partition
Restart ApacheDS. 否则,分区将不可用,LDIF导入将失败。
加载以下LDIF文件,该文件将创建Spring Security OU和‘rod’用户:
在ldap浏览器中右键点击‘Root DSE’节点,然后选择‘导入->LDIF导入...’
使用教程代码测试LDAP连接¶
该教程代码包括一个 AuthorizationsProvider
将连接到LDAP以检索授权的实现,在类中 com.example.geomesa.auths.LdapAuthorizationsProvider
。
提供程序将根据 geomesa-ldap.properties
类路径上的文件(在 src/main/resources
):
# ldap connection properties
java.naming.factory.initial=com.sun.jndi.ldap.LdapCtxFactory
java.naming.provider.url=ldap://localhost:10389
java.naming.security.authentication=simple
java.naming.security.principal=uid=admin,ou=system
java.naming.security.credentials=secret
# the ldap node to start the query from
geomesa.ldap.search.root=o=Spring Framework
# the query that will be applied to find the user's record
# the '{}' will be replaced with the common name from the certificate the user has logged in with
geomesa.ldap.search.filter=(&(objectClass=person)(cn={}))
# the ldap attribute that holds the comma-delimited authorizations for the user
geomesa.ldap.auths.attribute=employeeType
本教程中包含的默认文件将连接到我们在前面的步骤中设置的LDAP实例。如果您使用的是不同的LDAP配置,则需要适当修改该文件。
这个 LdapAuthorizationsProvider
将在逗号分隔的列表中查找存储用户授权的特定LDAP属性。为简单起见,在本教程中,我们重新调整了现有属性的用途, employeeType
。可以通过属性文件修改要使用的属性。
当我们将‘rod’记录插入到ldap时,我们设置了他的 employeeType
设置为‘USER,ADMIN’,对应于我们的Acumulo授权。如果使用不同的授权,则需要更新属性以进行匹配。
教程代码在类中包含了一个测试用例,用于连接到LDAP LdapAuthorizationsProviderTest
。
一旦您修改了 geomesa-ldap.properties
要连接到您的LDAP,您可以通过运行以下测试类来测试连接:
$ java -cp geomesa-tutorials-accumulo/geomesa-tutorials-accumulo-authorizations/target/geomesa-tutorials-accumulo-authorizations-${geomesa.version}.jar \
org.geomesa.example.accumulo.auths.LdapAuthorizationsProviderTest rod
程序(‘rod’)的参数是要检索其授权的用户。您应该会得到以下输出:
Checking auths from LDAP for user 'rod'
Retrieved auths: user,admin
在Geoserver中安装LDAP AuthorizationProvider¶
为了使用 LdapAuthorizationsProvider
,我们需要将其作为服务提供商安装到Geoserver中,在那里它将被GeoMesa自动拾取。
教程代码包括服务提供者注册表 META-INF/services
文件夹。默认情况下,提供程序类被指定为 EmptyAuthorizationsProvider
。
通过运行以下命令确保您的LDAP配置正确
LdapAuthorizationsProviderTest
,如上所述。更改单行文件中的提供程序类
src/main/resources/META-INF/services/org.locationtech.geomesa.security.AuthorizationsProvider
成为org.geomesa.example.accumulo.auths.LdapAuthorizationsProvider
重新构建教程JAR并安装 unshaded original Geoserver中的JAR:
$ mvn clean install -pl geomesa-tutorials-accumulo/geomesa-tutorials-accumulo-authorizations $ cp geomesa-tutorials-accumulo/geomesa-tutorials-accumulo-authorizations/target/geomesa-tutorials-accumulo-authorizations-${geomesa.version}.jar \ /path/to/tomcat/webapps/geoserver/WEB-INF/lib/
备注
我们希望使用未着色的JAR,因为所有必需的依赖项都已安装在Geoserver中。
重新启动Geoserver(如果Geoserver未运行,则将其启动)。
在这一点上,您应该已经完成了所有配置并就位。
验证Geoserver中的LDAP授权¶
为了验证授权是否正常工作,请在您的浏览器中通过HTTPS调用WMS提供商来对GeoMesa执行查询:
https://localhost:8443/geoserver/wms?service=WMS&version=1.1.0&request=GetMap&layers=geomesa:gdelt_auths&styles=&bbox=31.6,44,37.4,47.75&width=1200&height=600&srs=EPSG:4326&format=application/openlayers
出现提示时,选择“rod”证书。
您应该会看到正常数据返回,许多红点表示数据:

授权结果¶
现在尝试相同的查询,但使用‘Scott’证书。这一次,应该不会返回任何数据,因为‘Scott’用户没有在LDAP中设置任何授权。
备注
一种同时使用不同证书的简单方法是打开多个“隐姓埋名”或“私人”的浏览器窗口。