This is an automated email from the ASF dual-hosted git repository.
hxd pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-iotdb.git
The following commit(s) were added to refs/heads/master by this push:
new 5ed15e1 [IOTDB-700]Feature/iotdb 700 add openid (#1255)
5ed15e1 is described below
commit 5ed15e1d6b20845c535cdd223d2aa7a1e4e4f9dd
Author: Julian <[email protected]>
AuthorDate: Fri May 29 06:46:12 2020 +0200
[IOTDB-700]Feature/iotdb 700 add openid (#1255)
* IOTBD-700 Implemented OpenID Connect integration in IoTDB.
Further Changes:
- UserNames can now contain colon "-"
* add OpenIdAuthorizer into configuation file
authored by: Julian Feinauer
Co-authored-by: xiangdong huang <[email protected]>
---
docs/UserGuide/Client/Command Line Interface.md | 30 +++
docs/UserGuide/Server/Config Manual.md | 21 ++
docs/zh/UserGuide/Client/Command Line Interface.md | 31 +++
docs/zh/UserGuide/Server/Config Manual.md | 20 ++
server/pom.xml | 25 ++
.../resources/conf/iotdb-engine.properties | 15 ++
.../org/apache/iotdb/db/qp/strategy/SqlBase.g4 | 1 +
.../org/apache/iotdb/db/auth/AuthorityChecker.java | 4 +-
.../iotdb/db/auth/authorizer/BasicAuthorizer.java | 54 ++++-
.../db/auth/authorizer/LocalFileAuthorizer.java | 28 +--
.../iotdb/db/auth/authorizer/OpenIdAuthorizer.java | 257 +++++++++++++++++++++
.../java/org/apache/iotdb/db/conf/IoTDBConfig.java | 23 ++
.../org/apache/iotdb/db/conf/IoTDBDescriptor.java | 6 +
.../apache/iotdb/db/mqtt/BrokerAuthenticator.java | 4 +-
.../apache/iotdb/db/qp/executor/PlanExecutor.java | 4 +-
.../org/apache/iotdb/db/service/TSServiceImpl.java | 11 +-
.../iotdb/db/auth/LocalFileAuthorizerTest.java | 8 +-
.../db/auth/authorizer/OpenIdAuthorizerTest.java | 66 ++++++
.../apache/iotdb/db/utils/EnvironmentUtils.java | 4 +-
.../apache/iotdb/spark/db/EnvironmentUtils.java | 4 +-
20 files changed, 565 insertions(+), 51 deletions(-)
diff --git a/docs/UserGuide/Client/Command Line Interface.md
b/docs/UserGuide/Client/Command Line Interface.md
index 7b03398..fc3c41d 100644
--- a/docs/UserGuide/Client/Command Line Interface.md
+++ b/docs/UserGuide/Client/Command Line Interface.md
@@ -105,6 +105,36 @@ The Windows system startup commands are as follows:
```
Shell > sbin\start-cli.bat -h 10.129.187.21 -p 6667 -u root -pw root
-disableIS08601 -maxPRC 10
```
+
+### Note on using the CLI with OpenID Connect Auth enabled on Server side
+
+If OIDC is enabled on server side then no username / passwort is needed but a
valid Access Token from the OIDC Provider.
+So as username you use the token and the password has to be empty, e.g.
+
+```
+ Shell > sbin/start-cli.sh -h 10.129.187.21 -p 6667 -u {my-access-token} -pw
""
+```
+
+How to get the token is dependent on your OpenID Connect setup and not covered
here.
+In the simplest case you can get this via the command line with the
`passwort-grant`.
+For example, if you use keycloack as OIDC and you have a realm with a client
`iotdb` defined as public you could use
+the following `curl` command to fetch a token (replace all `{}` with
appropriate values).
+```
+curl -X POST
"https://{your-keycloack-server}/auth/realms/{your-realm}/protocol/openid-connect/token"
\
✔ 1613 11:09:38
+ -H "Content-Type: application/x-www-form-urlencoded" \
+ -d "username={username}" \
+ -d "password={password}" \
+ -d 'grant_type=password' \
+ -d "client_id=iotdb"
+```
+The response looks something like
+```json
+{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJxMS1XbTBvelE1TzBtUUg4LVNKYXAyWmNONE1tdWNXd25RV0tZeFpKNG93In0.eyJleHAiOjE1OTAzOTgwNzEsImlhdCI6MTU5MDM5Nzc3MSwianRpIjoiNjA0ZmYxMDctN2NiNy00NTRmLWIwYmQtY2M2ZDQwMjFiNGU4IiwiaXNzIjoiaHR0cDovL2F1dGguZGVtby5wcmFnbWF0aWNpbmR1c3RyaWVzLmRlL2F1dGgvcmVhbG1zL0lvVERCIiwiYXVkIjoiYWNjb3VudCIsInN1YiI6ImJhMzJlNDcxLWM3NzItNGIzMy04ZGE2LTZmZThhY2RhMDA3MyIsInR5cCI6IkJlYXJlciIsImF6cCI6ImlvdGRiIiwic2Vzc2lvbl9zdGF0ZSI6IjA2MGQyODYyLTE0ZWQtNDJmZS1
[...]
+```
+
+The interesting part here is the access token with the key `access_token`.
+This has to be passed as username (with parameter `-u`) and empty password to
the CLI.
+
## Cli/shell tool with -e parameter
-e parameter is designed for the Cli/shell tool in the situation where you
would like to manipulate IoTDB in batches through scripts. By using the -e
parameter, you can operate IoTDB without entering the cli's input mode.
diff --git a/docs/UserGuide/Server/Config Manual.md
b/docs/UserGuide/Server/Config Manual.md
index dbc40fb..e3ebc6e 100644
--- a/docs/UserGuide/Server/Config Manual.md
+++ b/docs/UserGuide/Server/Config Manual.md
@@ -553,6 +553,27 @@ The permission definitions are in
${IOTDB\_CONF}/conf/jmx.access.
|Default|your principal |
|Effective|After restart system|
+
+* authorizer\_provider\_class
+
+|Name| authorizer\_provider\_class |
+|:---:|:---|
+|Description| the class name of the authorization service|
+|Type| String |
+|Default|org.apache.iotdb.db.auth.authorizer.LocalFileAuthorizer |
+|Effective|After restart system|
+|Other available values| org.apache.iotdb.db.auth.authorizer.OpenIdAuthorizer |
+
+* openID\_url
+
+|Name| openID\_url |
+|:---:|:---|
+|Description| the openID server if OpenIdAuthorizer is enabled|
+|Type| String (a http url) |
+|Default|no |
+|Effective|After restart system|
+
+
## Enable GC log
GC log is off by default.
For performance tuning, you may want to collect the GC info.
diff --git a/docs/zh/UserGuide/Client/Command Line Interface.md
b/docs/zh/UserGuide/Client/Command Line Interface.md
index 15fd54d..fdc1515 100644
--- a/docs/zh/UserGuide/Client/Command Line Interface.md
+++ b/docs/zh/UserGuide/Client/Command Line Interface.md
@@ -102,6 +102,37 @@ Windows系统启动命令如下:
```
Shell > sbin\start-cli.bat -h 10.129.187.21 -p 6667 -u root -pw root
-disableIS08601 -maxPRC 10
```
+
+## 使用OpenID作为用户名认证登录
+
+若对应的IoTDB服务器开启了使用OpenID Connect (OIDC)作为权限认证服务,那么就不再需要使用用户名密码进行登录。
+替而代之的是使用Token,以及空密码。
+此时,登录命令如下:
+
+```
+ Shell > sbin/start-cli.sh -h 10.129.187.21 -p 6667 -u {my-access-token} -pw
""
+```
+
+其中,需要将{my-access-token} (注意,包括{})替换成你的token。
+
+如何获取token取决于你的OIDC设置。 最简单的一种情况是使用`password-grant`。例如,假设你在用keycloack作为你的OIDC服务,
+并且你在keycloack中有一个被定义成publich的`iotdb`客户的realm,那么你可以使用如下`curl`命令获得token。
+(注意例子中的{}和里面的内容需要替换成具体的服务器地址和realm名字):
+```
+curl -X POST
"https://{your-keycloack-server}/auth/realms/{your-realm}/protocol/openid-connect/token"
\
✔ 1613 11:09:38
+ -H "Content-Type: application/x-www-form-urlencoded" \
+ -d "username={username}" \
+ -d "password={password}" \
+ -d 'grant_type=password' \
+ -d "client_id=iotdb"
+```
+
+示例结果如下:
+
+```json
+{"access_token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJxMS1XbTBvelE1TzBtUUg4LVNKYXAyWmNONE1tdWNXd25RV0tZeFpKNG93In0.eyJleHAiOjE1OTAzOTgwNzEsImlhdCI6MTU5MDM5Nzc3MSwianRpIjoiNjA0ZmYxMDctN2NiNy00NTRmLWIwYmQtY2M2ZDQwMjFiNGU4IiwiaXNzIjoiaHR0cDovL2F1dGguZGVtby5wcmFnbWF0aWNpbmR1c3RyaWVzLmRlL2F1dGgvcmVhbG1zL0lvVERCIiwiYXVkIjoiYWNjb3VudCIsInN1YiI6ImJhMzJlNDcxLWM3NzItNGIzMy04ZGE2LTZmZThhY2RhMDA3MyIsInR5cCI6IkJlYXJlciIsImF6cCI6ImlvdGRiIiwic2Vzc2lvbl9zdGF0ZSI6IjA2MGQyODYyLTE0ZWQtNDJmZS1
[...]
+```
+
## Cli / Shell的-e参数
当您想要通过脚本的方式通过Cli /
Shell对IoTDB进行批量操作时,可以使用-e参数。通过使用该参数,您可以在不进入客户端输入模式的情况下操作IoTDB。
diff --git a/docs/zh/UserGuide/Server/Config Manual.md
b/docs/zh/UserGuide/Server/Config Manual.md
index 7589fed..0452454 100644
--- a/docs/zh/UserGuide/Server/Config Manual.md
+++ b/docs/zh/UserGuide/Server/Config Manual.md
@@ -499,6 +499,26 @@
|改后生效方式|重启服务器生效|
+* authorizer\_provider\_class
+
+|名字| authorizer\_provider\_class |
+|:---:|:---|
+|描述| 权限服务的类名|
+|类型| String |
+|默认值|org.apache.iotdb.db.auth.authorizer.LocalFileAuthorizer |
+|改后生效方式|重启服务器生效|
+|其他可选值| org.apache.iotdb.db.auth.authorizer.OpenIdAuthorizer |
+
+* openID\_url
+
+|名字| openID\_url |
+|:---:|:---|
+|描述| openID 服务器地址 (当OpenIdAuthorizer被启用时必须设定)|
+|类型| String (一个http地址) |
+|默认值| 无 |
+|改后生效方式|重启服务器生效|
+
+
## 开启GC日志
GC日志默认是关闭的。为了性能调优,用户可能会需要手机GC信息。
若要打开GC日志,则需要在启动IoTDB Server的时候加上"printgc"参数:
diff --git a/server/pom.xml b/server/pom.xml
index b6cb127..351f6a6 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -145,6 +145,31 @@
<artifactId>stream</artifactId>
<version>2.9.5</version>
</dependency>
+ <!-- compile group: 'io.jsonwebtoken', name: 'jjwt', version:
'0.9.1'-->
+ <dependency>
+ <groupId>io.jsonwebtoken</groupId>
+ <artifactId>jjwt-api</artifactId>
+ <version>0.10.7</version>
+ </dependency>
+ <!-- Impl -->
+ <dependency>
+ <groupId>io.jsonwebtoken</groupId>
+ <artifactId>jjwt-impl</artifactId>
+ <version>0.10.7</version>
+ <scope>runtime</scope>
+ </dependency>
+ <!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-jackson
-->
+ <dependency>
+ <groupId>io.jsonwebtoken</groupId>
+ <artifactId>jjwt-jackson</artifactId>
+ <version>0.10.7</version>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.nimbusds</groupId>
+ <artifactId>oauth2-oidc-sdk</artifactId>
+ <version>8.3</version>
+ </dependency>
</dependencies>
<build>
<plugins>
diff --git a/server/src/assembly/resources/conf/iotdb-engine.properties
b/server/src/assembly/resources/conf/iotdb-engine.properties
index 19f1f40..5169c85 100644
--- a/server/src/assembly/resources/conf/iotdb-engine.properties
+++ b/server/src/assembly/resources/conf/iotdb-engine.properties
@@ -470,3 +470,18 @@ mqtt_handler_pool_size=1
# the mqtt message payload formatter.
mqtt_payload_formatter=json
+
+
+####################
+### Authorization Configuration
+####################
+
+#which class to serve for authorization. By default, it is LocalFileAuthorizer.
+#Another choice is org.apache.iotdb.db.auth.authorizer.OpenIdAuthorizer
+authorizer_provider_class=org.apache.iotdb.db.auth.authorizer.LocalFileAuthorizer
+
+
+#If OpenIdAuthorizer is enabled, then openID_url must be set.
+
+#openID_url=
+
diff --git a/server/src/main/antlr4/org/apache/iotdb/db/qp/strategy/SqlBase.g4
b/server/src/main/antlr4/org/apache/iotdb/db/qp/strategy/SqlBase.g4
index ecf7b80..733e721 100644
--- a/server/src/main/antlr4/org/apache/iotdb/db/qp/strategy/SqlBase.g4
+++ b/server/src/main/antlr4/org/apache/iotdb/db/qp/strategy/SqlBase.g4
@@ -944,6 +944,7 @@ NAME_CHAR
| '0'..'9'
| '_'
| '-'
+ | ':'
| '/'
| '@'
| '#'
diff --git
a/server/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java
b/server/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java
index 990e7a1..ef3f1a4 100644
--- a/server/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java
+++ b/server/src/main/java/org/apache/iotdb/db/auth/AuthorityChecker.java
@@ -19,8 +19,8 @@
package org.apache.iotdb.db.auth;
import java.util.List;
+import org.apache.iotdb.db.auth.authorizer.BasicAuthorizer;
import org.apache.iotdb.db.auth.authorizer.IAuthorizer;
-import org.apache.iotdb.db.auth.authorizer.LocalFileAuthorizer;
import org.apache.iotdb.db.auth.entity.PrivilegeType;
import org.apache.iotdb.db.conf.IoTDBConstant;
import org.apache.iotdb.db.qp.logical.Operator;
@@ -76,7 +76,7 @@ public class AuthorityChecker {
private static boolean checkOnePath(String username, Path path, int
permission)
throws AuthException {
- IAuthorizer authorizer = LocalFileAuthorizer.getInstance();
+ IAuthorizer authorizer = BasicAuthorizer.getInstance();
try {
String fullPath = path == null ? IoTDBConstant.PATH_ROOT :
path.getFullPath();
if (authorizer.checkUserPrivileges(username, fullPath, permission)) {
diff --git
a/server/src/main/java/org/apache/iotdb/db/auth/authorizer/BasicAuthorizer.java
b/server/src/main/java/org/apache/iotdb/db/auth/authorizer/BasicAuthorizer.java
index 3659d2d..f699e31 100644
---
a/server/src/main/java/org/apache/iotdb/db/auth/authorizer/BasicAuthorizer.java
+++
b/server/src/main/java/org/apache/iotdb/db/auth/authorizer/BasicAuthorizer.java
@@ -18,9 +18,6 @@
*/
package org.apache.iotdb.db.auth.authorizer;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
import org.apache.iotdb.db.auth.AuthException;
import org.apache.iotdb.db.auth.entity.PrivilegeType;
import org.apache.iotdb.db.auth.entity.Role;
@@ -28,6 +25,7 @@ import org.apache.iotdb.db.auth.entity.User;
import org.apache.iotdb.db.auth.role.IRoleManager;
import org.apache.iotdb.db.auth.user.IUserManager;
import org.apache.iotdb.db.conf.IoTDBConstant;
+import org.apache.iotdb.db.conf.IoTDBDescriptor;
import org.apache.iotdb.db.exception.StartupException;
import org.apache.iotdb.db.service.IService;
import org.apache.iotdb.db.service.ServiceType;
@@ -35,6 +33,10 @@ import org.apache.iotdb.db.utils.AuthUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
public abstract class BasicAuthorizer implements IAuthorizer, IService {
private static final Logger logger =
LoggerFactory.getLogger(BasicAuthorizer.class);
@@ -48,8 +50,8 @@ public abstract class BasicAuthorizer implements IAuthorizer,
IService {
}
}
- private IUserManager userManager;
- private IRoleManager roleManager;
+ IUserManager userManager;
+ IRoleManager roleManager;
BasicAuthorizer(IUserManager userManager, IRoleManager roleManager) throws
AuthException {
this.userManager = userManager;
@@ -63,6 +65,38 @@ public abstract class BasicAuthorizer implements
IAuthorizer, IService {
logger.info("Initialization of Authorizer completes");
}
+ /**
+ * function for getting the instance of the local file authorizer.
+ */
+ public static IAuthorizer getInstance() throws AuthException {
+ if (InstanceHolder.instance == null) {
+ throw new AuthException("Authorizer uninitialized");
+ }
+ return InstanceHolder.instance;
+ }
+
+ private static class InstanceHolder {
+ private static IAuthorizer instance;
+
+ static {
+ Class<BasicAuthorizer> c = null;
+ try {
+ c = (Class<BasicAuthorizer>)
Class.forName(IoTDBDescriptor.getInstance().getConfig().getAuthorizerProvider());
+ logger.info("Authorizer provider class: {}",
IoTDBDescriptor.getInstance().getConfig().getAuthorizerProvider());
+ instance = c.getDeclaredConstructor().newInstance();
+ } catch (Exception e) {
+ instance = null;
+ //startup failed.
+ throw new IllegalStateException("Authorizer could not be
initialized!", e);
+ }
+ }
+ }
+
+
+
+ /** Checks if a user has admin privileges */
+ abstract boolean isAdmin(String username);
+
@Override
public boolean login(String username, String password) throws AuthException {
User user = userManager.getUser(username);
@@ -78,7 +112,7 @@ public abstract class BasicAuthorizer implements
IAuthorizer, IService {
@Override
public void deleteUser(String username) throws AuthException {
- if (IoTDBConstant.ADMIN_NAME.equals(username)) {
+ if (isAdmin(username)) {
throw new AuthException("Default administrator cannot be deleted");
}
if (!userManager.deleteUser(username)) {
@@ -90,7 +124,7 @@ public abstract class BasicAuthorizer implements
IAuthorizer, IService {
public void grantPrivilegeToUser(String username, String path, int
privilegeId)
throws AuthException {
String newPath = path;
- if (IoTDBConstant.ADMIN_NAME.equals(username)) {
+ if (isAdmin(username)) {
throw new AuthException("Invalid operation, administrator already has
all privileges");
}
if (!PrivilegeType.isPathRelevant(privilegeId)) {
@@ -105,7 +139,7 @@ public abstract class BasicAuthorizer implements
IAuthorizer, IService {
@Override
public void revokePrivilegeFromUser(String username, String path, int
privilegeId)
throws AuthException {
- if (IoTDBConstant.ADMIN_NAME.equals(username)) {
+ if (isAdmin(username)) {
throw new AuthException("Invalid operation, administrator must have all
privileges");
}
String p = path;
@@ -204,7 +238,7 @@ public abstract class BasicAuthorizer implements
IAuthorizer, IService {
@Override
public Set<Integer> getPrivileges(String username, String path) throws
AuthException {
- if (IoTDBConstant.ADMIN_NAME.equals(username)) {
+ if (isAdmin(username)) {
return ADMIN_PRIVILEGES;
}
User user = userManager.getUser(username);
@@ -233,7 +267,7 @@ public abstract class BasicAuthorizer implements
IAuthorizer, IService {
@Override
public boolean checkUserPrivileges(String username, String path, int
privilegeId)
throws AuthException {
- if (IoTDBConstant.ADMIN_NAME.equals(username)) {
+ if (isAdmin(username)) {
return true;
}
User user = userManager.getUser(username);
diff --git
a/server/src/main/java/org/apache/iotdb/db/auth/authorizer/LocalFileAuthorizer.java
b/server/src/main/java/org/apache/iotdb/db/auth/authorizer/LocalFileAuthorizer.java
index c2d94ce..b040fcf 100644
---
a/server/src/main/java/org/apache/iotdb/db/auth/authorizer/LocalFileAuthorizer.java
+++
b/server/src/main/java/org/apache/iotdb/db/auth/authorizer/LocalFileAuthorizer.java
@@ -23,40 +23,22 @@ import org.apache.iotdb.db.auth.AuthException;
import org.apache.iotdb.db.auth.role.LocalFileRoleManager;
import org.apache.iotdb.db.auth.user.LocalFileUserManager;
import org.apache.iotdb.db.conf.IoTDBConfig;
+import org.apache.iotdb.db.conf.IoTDBConstant;
import org.apache.iotdb.db.conf.IoTDBDescriptor;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
public class LocalFileAuthorizer extends BasicAuthorizer {
private static IoTDBConfig config =
IoTDBDescriptor.getInstance().getConfig();
- private static Logger logger =
LoggerFactory.getLogger(LocalFileAuthorizer.class);
- private LocalFileAuthorizer() throws AuthException {
+ public LocalFileAuthorizer() throws AuthException {
super(new LocalFileUserManager(config.getSystemDir() + File.separator +
"users"),
new LocalFileRoleManager(config.getSystemDir() + File.separator +
"roles"));
}
- /**
- * function for getting the instance of the local file authorizer.
- */
- public static LocalFileAuthorizer getInstance() throws AuthException {
- if (InstanceHolder.instance == null) {
- throw new AuthException("Authorizer uninitialized");
- }
- return InstanceHolder.instance;
+ @Override
+ boolean isAdmin(String username) {
+ return IoTDBConstant.ADMIN_NAME.equals(username);
}
- private static class InstanceHolder {
- private static LocalFileAuthorizer instance;
- static {
- try {
- instance = new LocalFileAuthorizer();
- } catch (AuthException e) {
- logger.error("Authorizer initialization failed due to ", e);
- instance = null;
- }
- }
- }
}
diff --git
a/server/src/main/java/org/apache/iotdb/db/auth/authorizer/OpenIdAuthorizer.java
b/server/src/main/java/org/apache/iotdb/db/auth/authorizer/OpenIdAuthorizer.java
new file mode 100644
index 0000000..8c2cf00
--- /dev/null
+++
b/server/src/main/java/org/apache/iotdb/db/auth/authorizer/OpenIdAuthorizer.java
@@ -0,0 +1,257 @@
+/*
+ * 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 ag [...]
+ */
+
+package org.apache.iotdb.db.auth.authorizer;
+
+import com.nimbusds.jose.JOSEException;
+import com.nimbusds.jose.jwk.RSAKey;
+import com.nimbusds.oauth2.sdk.ParseException;
+import com.nimbusds.oauth2.sdk.util.JSONObjectUtils;
+import com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata;
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.JwtException;
+import io.jsonwebtoken.Jwts;
+import net.minidev.json.JSONArray;
+import net.minidev.json.JSONObject;
+import org.apache.iotdb.db.auth.AuthException;
+import org.apache.iotdb.db.auth.entity.Role;
+import org.apache.iotdb.db.auth.entity.User;
+import org.apache.iotdb.db.auth.role.LocalFileRoleManager;
+import org.apache.iotdb.db.auth.user.LocalFileUserManager;
+import org.apache.iotdb.db.conf.IoTDBConfig;
+import org.apache.iotdb.db.conf.IoTDBDescriptor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.security.interfaces.RSAPublicKey;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Scanner;
+import java.util.UUID;
+
+/**
+ * Uses an OpenID Connect provider for Authorization / Authentication.
+ */
+public class OpenIdAuthorizer extends BasicAuthorizer {
+
+ private static final Logger logger =
LoggerFactory.getLogger(OpenIdAuthorizer.class);
+ public static final String IOTDB_ADMIN_ROLE_NAME = "iotdb_admin";
+ public static final String OPENID_USER_PREFIX = "openid-";
+
+ private static IoTDBConfig config =
IoTDBDescriptor.getInstance().getConfig();
+
+ private RSAPublicKey providerKey;
+
+ /** Stores all claims to the respective user */
+ private Map<String, Claims> loggedClaims = new HashMap<>();
+
+ public OpenIdAuthorizer() throws AuthException, ParseException,
IOException, URISyntaxException {
+ this(config.getOpenIdProviderUrl());
+ }
+
+ OpenIdAuthorizer(JSONObject jwk) throws AuthException {
+ super(new LocalFileUserManager(config.getSystemDir() + File.separator
+ "users"),
+ new LocalFileRoleManager(config.getSystemDir() +
File.separator + "roles"));
+ try {
+ providerKey = RSAKey.parse(jwk).toRSAPublicKey();
+ } catch (java.text.ParseException | JOSEException e) {
+ throw new AuthException("Unable to get OIDC Provider Key from JWK
" + jwk.toString(), e);
+ }
+ logger.info("Initialized with providerKey: {}", providerKey);
+ }
+
+ OpenIdAuthorizer(String providerUrl) throws AuthException,
URISyntaxException, ParseException, IOException {
+ this(getJWKfromProvider(providerUrl));
+ }
+
+ private static JSONObject getJWKfromProvider(String providerUrl) throws
URISyntaxException, IOException, ParseException, AuthException {
+ if (providerUrl == null) {
+ throw new IllegalArgumentException("OpenID Connect Provider URI
must be given!");
+ }
+
+ // Fetch Metadata
+ OIDCProviderMetadata providerMetadata = fetchMetadata(providerUrl);
+
+ logger.debug("Using Provider Metadata: {}", providerMetadata);
+
+ try {
+ URL url = new
URI(providerMetadata.getJWKSetURI().toString().replace("http",
"https")).toURL();
+ logger.debug("Using url {}", url);
+ return getProviderRSAJWK(url.openStream());
+ } catch (IOException e) {
+ throw new AuthException("Unable to start the Auth", e);
+ }
+ }
+
+ private static JSONObject getProviderRSAJWK(InputStream is) throws
ParseException {
+ // Read all data from stream
+ StringBuilder sb = new StringBuilder();
+ try (Scanner scanner = new Scanner(is);) {
+ while (scanner.hasNext()) {
+ sb.append(scanner.next());
+ }
+ }
+
+ // Parse the data as json
+ String jsonString = sb.toString();
+ JSONObject json = JSONObjectUtils.parse(jsonString);
+
+ // Find the RSA signing key
+ JSONArray keyList = (JSONArray) json.get("keys");
+ for (Object key : keyList) {
+ JSONObject k = (JSONObject) key;
+ if (k.get("use").equals("sig") && k.get("kty").equals("RSA")) {
+ return k;
+ }
+ }
+ return null;
+ }
+
+ static OIDCProviderMetadata fetchMetadata(String providerUrl) throws
URISyntaxException, IOException, ParseException {
+ URI issuerURI = new URI(providerUrl);
+ URL providerConfigurationURL =
issuerURI.resolve(".well-known/openid-configuration").toURL();
+ InputStream stream = providerConfigurationURL.openStream();
+ // Read all data from URL
+ String providerInfo = null;
+ try (java.util.Scanner s = new java.util.Scanner(stream)) {
+ providerInfo = s.useDelimiter("\\A").hasNext() ? s.next() : "";
+ }
+ return OIDCProviderMetadata.parse(providerInfo);
+ }
+
+ @Override
+ public boolean login(String token, String password) throws AuthException {
+ if (password != null && !password.isEmpty()) {
+ logger.error("JWT Login failed as a non-empty Password was given
username (token): {}, password: {}", token, password);
+ return false;
+ }
+ if (token == null || token.isEmpty()) {
+ logger.error("JWT Login failed as a Username (token) was empty!");
+ return false;
+ }
+ //This line will throw an exception if it is not a signed JWS (as
expected)
+ Claims claims;
+ try {
+ claims = validateToken(token);
+ } catch (JwtException e) {
+ logger.error("Unable to login the user wit jwt {}", password, e);
+ return false;
+ }
+ logger.debug("JWT was validated successfully!");
+ logger.debug("ID: {}", claims.getId());
+ logger.debug("Subject: {}", claims.getSubject());
+ logger.debug("Issuer: {}", claims.getIssuer());
+ logger.debug("Expiration: {}", claims.getExpiration());
+ // Create User if not exists
+ String iotdbUsername = getUsername(claims);
+ if (!super.listAllUsers().contains(iotdbUsername)) {
+ logger.info("User {} logs in for first time, storing it locally!",
iotdbUsername);
+ // We give the user a random password so that no one could hijack
them via local login
+ super.createUser(iotdbUsername, UUID.randomUUID().toString());
+ }
+ // Always store claims and user
+ this.loggedClaims.put(getUsername(claims), claims);
+ return true;
+ }
+
+ private Claims validateToken(String token) {
+ return Jwts
+ .parser()
+ // Basically ignore the Expiration Date, if there is any???
+ .setAllowedClockSkewSeconds(Long.MAX_VALUE / 1000)
+ // .setSigningKey(DatatypeConverter.parseBase64Binary(secret))
+ .setSigningKey(providerKey)
+ .parseClaimsJws(token)
+ .getBody();
+ }
+
+ private String getUsername(Claims claims) {
+ return OPENID_USER_PREFIX + claims.getSubject();
+ }
+
+ private String getUsername(String token) {
+ return getUsername(validateToken(token));
+ }
+
+ @Override
+ public void createUser(String username, String password) throws
AuthException {
+ throwUnsupportedOperationException();
+ }
+
+ private void throwUnsupportedOperationException() {
+ throw new UnsupportedOperationException("This operation is not
supported for JWT Auth Provider!");
+ }
+
+ @Override
+ public void deleteUser(String username) throws AuthException {
+ throwUnsupportedOperationException();
+ }
+
+ /**
+ * So not with the token!
+ * @param token Usually the JWT but could also be just the name of the
user ({@link #getUsername(String)}.
+ * @return true if the user is an admin
+ */
+ @Override
+ boolean isAdmin(String token) {
+ Claims claims;
+ if (this.loggedClaims.containsKey(token)) {
+ // This is a username!
+ claims = this.loggedClaims.get(token);
+ } else {
+ // Its a token
+ try {
+ claims = validateToken(token);
+ } catch (JwtException e) {
+ logger.warn("Unable to validate token {}!", token, e);
+ return false;
+ }
+ }
+ // Get available roles (from keycloack)
+ List<String> availableRoles = ((Map<String, List<String>>)
claims.get("realm_access")).get("roles");
+ if (!availableRoles.contains(IOTDB_ADMIN_ROLE_NAME)) {
+ logger.warn("Given Token has no admin rights, is there a ROLE with
name {} in 'realm_access' role set?", IOTDB_ADMIN_ROLE_NAME);
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean checkUserPrivileges(String username, String path, int
privilegeId)
+ throws AuthException {
+ if (isAdmin(username)) {
+ return true;
+ }
+
+ User user = userManager.getUser(getUsername(username));
+ if (user == null) {
+ throw new AuthException(String.format("No such user : %s",
getUsername(username)));
+ }
+ // get privileges of the user
+ if (user.checkPrivilege(path, privilegeId)) {
+ return true;
+ }
+ // merge the privileges of the roles of the user
+ for (String roleName : user.getRoleList()) {
+ Role role = roleManager.getRole(roleName);
+ if (role.checkPrivilege(path, privilegeId)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void updateUserPassword(String username, String newPassword) throws
AuthException {
+ throwUnsupportedOperationException();
+ }
+
+}
diff --git a/server/src/main/java/org/apache/iotdb/db/conf/IoTDBConfig.java
b/server/src/main/java/org/apache/iotdb/db/conf/IoTDBConfig.java
index 1aecad9..642cc3e 100644
--- a/server/src/main/java/org/apache/iotdb/db/conf/IoTDBConfig.java
+++ b/server/src/main/java/org/apache/iotdb/db/conf/IoTDBConfig.java
@@ -569,6 +569,13 @@ public class IoTDBConfig {
// max size for tag and attribute of one time series
private int tagAttributeTotalSize = 700;
+ // Open ID Secret
+ private String openIdProviderUrl = null;
+
+ // the authorizer provider class which extends BasicAuthorizer
+ private String authorizerProvider =
"org.apache.iotdb.db.auth.authorizer.LocalFileAuthorizer";
+
+
public IoTDBConfig() {
// empty constructor
}
@@ -1560,4 +1567,20 @@ public class IoTDBConfig {
public void setPrimitiveArraySize(int primitiveArraySize) {
this.primitiveArraySize = primitiveArraySize;
}
+
+ public String getOpenIdProviderUrl() {
+ return openIdProviderUrl;
+ }
+
+ public void setOpenIdProviderUrl(String openIdProviderUrl) {
+ this.openIdProviderUrl = openIdProviderUrl;
+ }
+
+ public String getAuthorizerProvider() {
+ return authorizerProvider;
+ }
+
+ public void setAuthorizerProvider(String authorizerProvider) {
+ this.authorizerProvider = authorizerProvider;
+ }
}
diff --git a/server/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java
b/server/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java
index fe033ee..790487d 100644
--- a/server/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java
+++ b/server/src/main/java/org/apache/iotdb/db/conf/IoTDBDescriptor.java
@@ -412,6 +412,12 @@ public class IoTDBDescriptor {
Boolean.parseBoolean(properties.getProperty(IoTDBConstant.ENABLE_MQTT)));
}
+
conf.setAuthorizerProvider(properties.getProperty("authorizer_provider_class",
+ "org.apache.iotdb.db.auth.authorizer.LocalFileAuthorizer"));
+ //if using org.apache.iotdb.db.auth.authorizer.OpenIdAuthorizer,
openID_url is needed.
+ conf.setOpenIdProviderUrl(properties.getProperty("openID_url", ""));
+
+
// At the same time, set TSFileConfig
TSFileDescriptor.getInstance().getConfig()
.setTSFileStorageFs(FSType.valueOf(
diff --git
a/server/src/main/java/org/apache/iotdb/db/mqtt/BrokerAuthenticator.java
b/server/src/main/java/org/apache/iotdb/db/mqtt/BrokerAuthenticator.java
index 8d2d0ff..e572602 100644
--- a/server/src/main/java/org/apache/iotdb/db/mqtt/BrokerAuthenticator.java
+++ b/server/src/main/java/org/apache/iotdb/db/mqtt/BrokerAuthenticator.java
@@ -21,7 +21,7 @@ import io.moquette.broker.security.IAuthenticator;
import org.apache.commons.lang.StringUtils;
import org.apache.iotdb.db.auth.AuthException;
import org.apache.iotdb.db.auth.authorizer.IAuthorizer;
-import org.apache.iotdb.db.auth.authorizer.LocalFileAuthorizer;
+import org.apache.iotdb.db.auth.authorizer.BasicAuthorizer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -38,7 +38,7 @@ public class BrokerAuthenticator implements IAuthenticator {
}
try {
- IAuthorizer authorizer = LocalFileAuthorizer.getInstance();
+ IAuthorizer authorizer = BasicAuthorizer.getInstance();
return authorizer.login(username, new String(password));
} catch (AuthException e) {
LOG.info("meet error while logging in.", e);
diff --git
a/server/src/main/java/org/apache/iotdb/db/qp/executor/PlanExecutor.java
b/server/src/main/java/org/apache/iotdb/db/qp/executor/PlanExecutor.java
index 899b486..a3fb017 100644
--- a/server/src/main/java/org/apache/iotdb/db/qp/executor/PlanExecutor.java
+++ b/server/src/main/java/org/apache/iotdb/db/qp/executor/PlanExecutor.java
@@ -52,7 +52,7 @@ import java.util.Set;
import java.util.TreeSet;
import org.apache.iotdb.db.auth.AuthException;
import org.apache.iotdb.db.auth.authorizer.IAuthorizer;
-import org.apache.iotdb.db.auth.authorizer.LocalFileAuthorizer;
+import org.apache.iotdb.db.auth.authorizer.BasicAuthorizer;
import org.apache.iotdb.db.auth.entity.PathPrivilege;
import org.apache.iotdb.db.auth.entity.Role;
import org.apache.iotdb.db.auth.entity.User;
@@ -159,7 +159,7 @@ public class PlanExecutor implements IPlanExecutor {
queryRouter = new QueryRouter();
mManager = MManager.getInstance();
try {
- authorizer = LocalFileAuthorizer.getInstance();
+ authorizer = BasicAuthorizer.getInstance();
} catch (AuthException e) {
throw new QueryProcessException(e.getMessage());
}
diff --git
a/server/src/main/java/org/apache/iotdb/db/service/TSServiceImpl.java
b/server/src/main/java/org/apache/iotdb/db/service/TSServiceImpl.java
index 9d7c505..d0cff5d 100644
--- a/server/src/main/java/org/apache/iotdb/db/service/TSServiceImpl.java
+++ b/server/src/main/java/org/apache/iotdb/db/service/TSServiceImpl.java
@@ -40,7 +40,7 @@ import org.antlr.v4.runtime.misc.ParseCancellationException;
import org.apache.iotdb.db.auth.AuthException;
import org.apache.iotdb.db.auth.AuthorityChecker;
import org.apache.iotdb.db.auth.authorizer.IAuthorizer;
-import org.apache.iotdb.db.auth.authorizer.LocalFileAuthorizer;
+import org.apache.iotdb.db.auth.authorizer.BasicAuthorizer;
import org.apache.iotdb.db.conf.IoTDBConfig;
import org.apache.iotdb.db.conf.IoTDBConstant;
import org.apache.iotdb.db.conf.IoTDBDescriptor;
@@ -181,15 +181,17 @@ public class TSServiceImpl implements TSIService.Iface,
ServerContext {
boolean status;
IAuthorizer authorizer;
try {
- authorizer = LocalFileAuthorizer.getInstance();
+ authorizer = BasicAuthorizer.getInstance();
} catch (AuthException e) {
throw new TException(e);
}
+ String loginMessage = null;
try {
status = authorizer.login(req.getUsername(), req.getPassword());
} catch (AuthException e) {
logger.info("meet error while logging in.", e);
status = false;
+ loginMessage = e.getMessage();
}
TSStatus tsStatus;
@@ -213,6 +215,7 @@ public class TSServiceImpl implements TSIService.Iface,
ServerContext {
currSessionId.set(sessionId);
} else {
tsStatus = RpcUtils.getStatus(TSStatusCode.WRONG_LOGIN_PASSWORD_ERROR);
+ tsStatus.setMessage(loginMessage);
}
TSOpenSessionResp resp = new TSOpenSessionResp(tsStatus,
TSProtocolVersion.IOTDB_SERVICE_PROTOCOL_V2);
@@ -856,7 +859,7 @@ public class TSServiceImpl implements TSIService.Iface,
ServerContext {
throws TException, AuthException, IOException, InterruptedException {
IAuthorizer authorizer;
try {
- authorizer = LocalFileAuthorizer.getInstance();
+ authorizer = BasicAuthorizer.getInstance();
} catch (AuthException e) {
throw new TException(e);
}
@@ -893,7 +896,7 @@ public class TSServiceImpl implements TSIService.Iface,
ServerContext {
throws TException, AuthException, InterruptedException {
IAuthorizer authorizer;
try {
- authorizer = LocalFileAuthorizer.getInstance();
+ authorizer = BasicAuthorizer.getInstance();
} catch (AuthException e) {
throw new TException(e);
}
diff --git
a/server/src/test/java/org/apache/iotdb/db/auth/LocalFileAuthorizerTest.java
b/server/src/test/java/org/apache/iotdb/db/auth/LocalFileAuthorizerTest.java
index f4a01d7..485bb5b 100644
--- a/server/src/test/java/org/apache/iotdb/db/auth/LocalFileAuthorizerTest.java
+++ b/server/src/test/java/org/apache/iotdb/db/auth/LocalFileAuthorizerTest.java
@@ -26,7 +26,7 @@ import static org.junit.Assert.fail;
import java.util.List;
import java.util.Set;
import org.apache.iotdb.db.auth.authorizer.IAuthorizer;
-import org.apache.iotdb.db.auth.authorizer.LocalFileAuthorizer;
+import org.apache.iotdb.db.auth.authorizer.BasicAuthorizer;
import org.apache.iotdb.db.auth.entity.User;
import org.apache.iotdb.db.conf.IoTDBConstant;
import org.apache.iotdb.db.utils.EnvironmentUtils;
@@ -49,7 +49,7 @@ public class LocalFileAuthorizerTest {
@Test
public void testAuthorizer() throws AuthException {
- IAuthorizer authorizer = LocalFileAuthorizer.getInstance();
+ IAuthorizer authorizer = BasicAuthorizer.getInstance();
/*
* login
*/
@@ -276,7 +276,7 @@ public class LocalFileAuthorizerTest {
@Test
public void testListUser() throws AuthException {
- IAuthorizer authorizer = LocalFileAuthorizer.getInstance();
+ IAuthorizer authorizer = BasicAuthorizer.getInstance();
List<String> userList = authorizer.listAllUsers();
assertEquals(1, userList.size());
assertEquals(IoTDBConstant.ADMIN_NAME, userList.get(0));
@@ -307,7 +307,7 @@ public class LocalFileAuthorizerTest {
@Test
public void testListRole() throws AuthException {
- IAuthorizer authorizer = LocalFileAuthorizer.getInstance();
+ IAuthorizer authorizer = BasicAuthorizer.getInstance();
List<String> roleList = authorizer.listAllRoles();
assertEquals(0, roleList.size());
diff --git
a/server/src/test/java/org/apache/iotdb/db/auth/authorizer/OpenIdAuthorizerTest.java
b/server/src/test/java/org/apache/iotdb/db/auth/authorizer/OpenIdAuthorizerTest.java
new file mode 100644
index 0000000..41cd591
--- /dev/null
+++
b/server/src/test/java/org/apache/iotdb/db/auth/authorizer/OpenIdAuthorizerTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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 ag [...]
+ */
+
+package org.apache.iotdb.db.auth.authorizer;
+
+import com.nimbusds.oauth2.sdk.ParseException;
+import com.nimbusds.oauth2.sdk.util.JSONObjectUtils;
+import org.apache.iotdb.db.auth.AuthException;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class OpenIdAuthorizerTest {
+
+ private static final String OPEN_ID_PUBLIC_JWK =
"{\"kty\":\"RSA\",\"x5t#S256\":\"TZFbbj6HsRU28HYvrcVnDs03KreV3DE24-Cxb9EPdS4\",\"e\":\"AQAB\",\"use\":\"sig\",\"x5t\":\"l_N2UlC_a624iu5eYFypnB1Wr20\",\"kid\":\"q1-Wm0ozQ5O0mQH8-SJap2ZcN4MmucWwnQWKYxZJ4ow\",\"x5c\":[\"MIICmTCCAYECBgFyRdXW2DANBgkqhkiG9w0BAQsFADAQMQ4wDAYDVQQDDAVJb1REQjAeFw0yMDA1MjQwODM3MjJaFw0zMDA1MjQwODM5MDJaMBAxDjAMBgNVBAMMBUlvVERCMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAozDCZTVc9946VvhZ6E\\/OP8Yx6tJe0i9GR2Q9jR9S3jQo
[...]
+
+ @Test
+ public void loginWithJWT() throws AuthException, ParseException,
IOException, URISyntaxException {
+ String jwt =
"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJxMS1XbTBvelE1TzBtUUg4LVNKYXAyWmNONE1tdWNXd25RV0tZeFpKNG93In0.eyJleHAiOjE1OTAzMTcxNzYsImlhdCI6MTU5MDMxNjg3NiwianRpIjoiY2MyNWQ3MDAtYjc5NC00OTA4LTg0OGUtOTRhNzYzNmM5YzQxIiwiaXNzIjoiaHR0cDovL2F1dGguZGVtby5wcmFnbWF0aWNpbmR1c3RyaWVzLmRlL2F1dGgvcmVhbG1zL0lvVERCIiwiYXVkIjoiYWNjb3VudCIsInN1YiI6Ijg2YWRmNGIzLWE4ZTUtNDc1NC1iNWEwLTQ4OGI0OWY0M2VkMiIsInR5cCI6IkJlYXJlciIsImF6cCI6ImlvdGRiIiwic2Vzc2lvbl9zdGF0ZSI6Ijk0ZmI5NGZjLTg3YTMtND
[...]
+
+ OpenIdAuthorizer authorizer = new
OpenIdAuthorizer(JSONObjectUtils.parse(OPEN_ID_PUBLIC_JWK));
+ boolean login = authorizer.login(jwt, null);
+
+ assertTrue(login);
+ }
+
+ @Test
+ public void isAdmin_hasAccess() throws AuthException, ParseException,
IOException, URISyntaxException {
+ // IOTDB_ADMIN = true
+ String jwt =
"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJxMS1XbTBvelE1TzBtUUg4LVNKYXAyWmNONE1tdWNXd25RV0tZeFpKNG93In0.eyJleHAiOjE1OTAzMjM5MjgsImlhdCI6MTU5MDMyMzYyOCwianRpIjoiZGQ5ZDZhNmItZjgzOC00Mjk3LTg5YWUtMjdlZTgxNzVhMThiIiwiaXNzIjoiaHR0cDovL2F1dGguZGVtby5wcmFnbWF0aWNpbmR1c3RyaWVzLmRlL2F1dGgvcmVhbG1zL0lvVERCIiwiYXVkIjoiYWNjb3VudCIsInN1YiI6ImJhMzJlNDcxLWM3NzItNGIzMy04ZGE2LTZmZThhY2RhMDA3MyIsInR5cCI6IkJlYXJlciIsImF6cCI6ImlvdGRiIiwic2Vzc2lvbl9zdGF0ZSI6IjViZDRhNmM5LTBmYzItNG
[...]
+
+ OpenIdAuthorizer authorizer = new
OpenIdAuthorizer(JSONObjectUtils.parse(OPEN_ID_PUBLIC_JWK));
+ boolean admin = authorizer.isAdmin(jwt);
+
+ assertTrue(admin);
+ }
+
+ @Test
+ public void isAdmin_noAdminClaim() throws AuthException, ParseException,
IOException, URISyntaxException {
+ // IOTDB_ADMIN = false
+ String jwt =
"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJxMS1XbTBvelE1TzBtUUg4LVNKYXAyWmNONE1tdWNXd25RV0tZeFpKNG93In0.eyJleHAiOjE1OTAzMTcxNzYsImlhdCI6MTU5MDMxNjg3NiwianRpIjoiY2MyNWQ3MDAtYjc5NC00OTA4LTg0OGUtOTRhNzYzNmM5YzQxIiwiaXNzIjoiaHR0cDovL2F1dGguZGVtby5wcmFnbWF0aWNpbmR1c3RyaWVzLmRlL2F1dGgvcmVhbG1zL0lvVERCIiwiYXVkIjoiYWNjb3VudCIsInN1YiI6Ijg2YWRmNGIzLWE4ZTUtNDc1NC1iNWEwLTQ4OGI0OWY0M2VkMiIsInR5cCI6IkJlYXJlciIsImF6cCI6ImlvdGRiIiwic2Vzc2lvbl9zdGF0ZSI6Ijk0ZmI5NGZjLTg3YTMtND
[...]
+
+ OpenIdAuthorizer authorizer = new
OpenIdAuthorizer(JSONObjectUtils.parse(OPEN_ID_PUBLIC_JWK));
+ boolean admin = authorizer.isAdmin(jwt);
+
+ assertFalse(admin);
+ }
+
+ /**
+ * Can be run manually as long as the site below is active...
+ */
+ @Test
+ @Ignore("We have to find a way to test this against a defined OIDC
Provider")
+ public void fetchMetadata() throws ParseException, IOException,
URISyntaxException, AuthException {
+ OpenIdAuthorizer openIdAuthorizer = new
OpenIdAuthorizer("https://auth.demo.pragmaticindustries.de/auth/realms/IoTDB/");
+ final boolean login =
openIdAuthorizer.login("eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJxMS1XbTBvelE1TzBtUUg4LVNKYXAyWmNONE1tdWNXd25RV0tZeFpKNG93In0.eyJleHAiOjE1OTAzMTcxNzYsImlhdCI6MTU5MDMxNjg3NiwianRpIjoiY2MyNWQ3MDAtYjc5NC00OTA4LTg0OGUtOTRhNzYzNmM5YzQxIiwiaXNzIjoiaHR0cDovL2F1dGguZGVtby5wcmFnbWF0aWNpbmR1c3RyaWVzLmRlL2F1dGgvcmVhbG1zL0lvVERCIiwiYXVkIjoiYWNjb3VudCIsInN1YiI6Ijg2YWRmNGIzLWE4ZTUtNDc1NC1iNWEwLTQ4OGI0OWY0M2VkMiIsInR5cCI6IkJlYXJlciIsImF6cCI6ImlvdGRiIiwic2Vzc2lvbl
[...]
+
+ assertTrue(login);
+ }
+}
\ No newline at end of file
diff --git
a/server/src/test/java/org/apache/iotdb/db/utils/EnvironmentUtils.java
b/server/src/test/java/org/apache/iotdb/db/utils/EnvironmentUtils.java
index 302ddaa..6e1ff67 100644
--- a/server/src/test/java/org/apache/iotdb/db/utils/EnvironmentUtils.java
+++ b/server/src/test/java/org/apache/iotdb/db/utils/EnvironmentUtils.java
@@ -29,7 +29,7 @@ import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import org.apache.commons.io.FileUtils;
import org.apache.iotdb.db.auth.AuthException;
-import org.apache.iotdb.db.auth.authorizer.LocalFileAuthorizer;
+import org.apache.iotdb.db.auth.authorizer.BasicAuthorizer;
import org.apache.iotdb.db.conf.IoTDBConfig;
import org.apache.iotdb.db.conf.IoTDBDescriptor;
import org.apache.iotdb.db.conf.adapter.IoTDBConfigDynamicAdapter;
@@ -255,7 +255,7 @@ public class EnvironmentUtils {
}
//create user and roles folder
try {
- LocalFileAuthorizer.getInstance().reset();
+ BasicAuthorizer.getInstance().reset();
} catch (AuthException e) {
logger.error("create user and role folders failed", e);
fail(e.getMessage());
diff --git
a/spark-iotdb-connector/src/test/scala/org/apache/iotdb/spark/db/EnvironmentUtils.java
b/spark-iotdb-connector/src/test/scala/org/apache/iotdb/spark/db/EnvironmentUtils.java
index e05e7d9..0070fe0 100644
---
a/spark-iotdb-connector/src/test/scala/org/apache/iotdb/spark/db/EnvironmentUtils.java
+++
b/spark-iotdb-connector/src/test/scala/org/apache/iotdb/spark/db/EnvironmentUtils.java
@@ -28,7 +28,7 @@ import java.util.Locale;
import org.apache.commons.io.FileUtils;
import org.apache.iotdb.db.auth.AuthException;
import org.apache.iotdb.db.auth.authorizer.IAuthorizer;
-import org.apache.iotdb.db.auth.authorizer.LocalFileAuthorizer;
+import org.apache.iotdb.db.auth.authorizer.BasicAuthorizer;
import org.apache.iotdb.db.conf.IoTDBConfig;
import org.apache.iotdb.db.conf.IoTDBDescriptor;
import org.apache.iotdb.db.conf.adapter.IoTDBConfigDynamicAdapter;
@@ -180,7 +180,7 @@ public class EnvironmentUtils {
config.setEnableStatMonitor(false);
IAuthorizer authorizer;
try {
- authorizer = LocalFileAuthorizer.getInstance();
+ authorizer = BasicAuthorizer.getInstance();
} catch (AuthException e) {
throw new StartupException(e);
}