-
Notifications
You must be signed in to change notification settings - Fork 3.7k
[feat](Authorization-plugin)Authorization framework modularization #40750
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
# AccessControllerFactory Interface
## Overview
The `AccessControllerFactory` interface is responsible for creating and managing `CatalogAccessController` instances. The interface includes the following methods:
- **`default String factoryIdentifier()`**: Returns the identifier for the factory, defaulting to the simple name of the implementing class. To maintain compatibility with user-defined plugins from older versions, the `factoryIdentifier` method provides a default implementation that returns the simple name of the current implementation class, ensuring that each factory has a unique identifier.
- **`CatalogAccessController createAccessController(Map<String, String> prop)`**: Creates a new instance of `CatalogAccessController` and initializes it with the provided properties.
## Factory Identifier
Each class implementing `AccessControllerFactory` will automatically use its class name as the factory identifier. This helps in identifying different factory instances during plugin loading and selection.
## Instance Creation
The `createAccessController` method allows you to create and initialize `CatalogAccessController` instances. The `prop` parameter provides the configuration properties needed for initialization.
## Compatibility
- If you are using the previously built-in `range-dorir` authentication plugin, no configuration changes are required; it will continue to function as before.
- For custom plugins, configuration information should be defined in `conf/access.conf`. Then, in `fe.conf`, specify the `access_controller_type` as the identifier for the custom plugin.
## How to Extend
- Add the `fe-core` dependency to your Maven `pom.xml` file.
```xml
<dependency>
<groupId>org.apache.doris</groupId>
<artifactId>fe-core</artifactId>
<version>1.2-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
```
Then, implement the AccessControllerFactory interface to create your own plugin factory class as follows:
```java
public class SimpleAccessControllerFactory implements AccessControllerFactory {
@OverRide
public String factoryIdentifier() {
return "local-simple";
}
@OverRide
public CatalogAccessController createAccessController(Map<String, String> map) {
return new SimpleAccessController(map);
}
}
package org.example.access;
import org.apache.doris.analysis.ResourceTypeEnum;
import org.apache.doris.analysis.UserIdentity;
import org.apache.doris.common.AuthorizationException;
import org.apache.doris.mysql.privilege.CatalogAccessController;
import org.apache.doris.mysql.privilege.DataMaskPolicy;
import org.apache.doris.mysql.privilege.PrivPredicate;
import org.apache.doris.mysql.privilege.RowFilterPolicy;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
public class SimpleAccessController implements CatalogAccessController {
private HashMap<String, Boolean> databasePrivs = new HashMap<>();
// just for test
public SimpleAccessController(Map<String, String> prop) {
prop.forEach((k, v) -> {
databasePrivs.put(k, Boolean.parseBoolean(v));
});
}
@OverRide
public boolean checkGlobalPriv(UserIdentity userIdentity, PrivPredicate privPredicate) {
return false;
}
@OverRide
public boolean checkCtlPriv(UserIdentity userIdentity, String s, PrivPredicate privPredicate) {
return true;
}
...
```
Add a new folder named **META-INF/services** under the resources directory, Create a new file named **org.apache.doris.mysql.privilege.AccessControllerFactory.**
with a file containing **org.apache.doris.mysql.privilege.AccessControllerFactory.**
## How to Use
- In `fe.conf`, specify the **access_controller_type=local-simple**
- Put the jar file containing the custom plugin in the **fe/custom_lib** directory.
|
Thank you for your contribution to Apache Doris. Since 2024-03-18, the Document has been moved to doris-website. |
|
run buildall |
TPC-H: Total hot run time: 42976 ms |
|
run performance |
| private Auth auth; | ||
| private CatalogAccessController defaultAccessController; | ||
| private Map<String, CatalogAccessController> ctlToCtlAccessController = Maps.newConcurrentMap(); | ||
| private ConcurrentHashMap<String, AccessControllerFactory> accessControllerFactoriesCache |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add comment to explain key and value of the map
| prop = PropertiesUtils.loadAccessControllerPropertiesOrNull(); | ||
| } catch (IOException e) { | ||
| LOG.warn("Failed to load access controller properties,Using default access controller plugin", e); | ||
| return new InternalAccessController(auth); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should stop process if user specified access controller is not found
| import java.util.Properties; | ||
|
|
||
| public class PropertiesUtils { | ||
| public static final String ACCESS_PROPERTIES_FILE_DIR = "/conf/access.conf"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better be a FE config
When the configuration plugin name cannot be found, an error is reported.
morningman
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
|
PR approved by at least one committer and no changes requested. |
|
PR approved by anyone and no changes requested. |
| return accessControllerFactoriesCache.get(accessControllerName).createAccessController(prop); | ||
| } | ||
| throw new RuntimeException("No authorization plugin factory found for " + accessControllerName | ||
| + "Please confirm that your plugin is placed in the correct location."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| + "Please confirm that your plugin is placed in the correct location."); | |
| + ". Please confirm that your plugin is placed in the correct location."); |
| .createAccessController(prop); | ||
| if (!isDryRun) { | ||
| ctlToCtlAccessController.put(ctl, accessController); | ||
| LOG.info("create access controller {} for catalog {}", ctl, acFactoryClassName); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| LOG.info("create access controller {} for catalog {}", ctl, acFactoryClassName); | |
| LOG.info("create access controller {} for catalog {}", acFactoryClassName, ctl); |
| prop = PropertiesUtils.loadAccessControllerPropertiesOrNull(); | ||
| } catch (IOException e) { | ||
| throw new RuntimeException("Failed to load authorization properties," | ||
| + "please check the configuration file, authorization name is " + accessControllerName, e); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| + "please check the configuration file, authorization name is " + accessControllerName, e); | |
| + " Please check the configuration file, authorization name is " + accessControllerName, e); |
| try { | ||
| prop = PropertiesUtils.loadAccessControllerPropertiesOrNull(); | ||
| } catch (IOException e) { | ||
| throw new RuntimeException("Failed to load authorization properties," |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| throw new RuntimeException("Failed to load authorization properties," | |
| throw new RuntimeException("Failed to load authorization properties." |
morningman
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
|
run buildall |
|
PR approved by at least one committer and no changes requested. |
|
run buildall |
…pache#40750) # AccessControllerFactory Interface ## Overview The `AccessControllerFactory` interface is responsible for creating and managing `CatalogAccessController` instances. The interface includes the following methods: - **`default String factoryIdentifier()`**: Returns the identifier for the factory, defaulting to the simple name of the implementing class. To maintain compatibility with user-defined plugins from older versions, the `factoryIdentifier` method provides a default implementation that returns the simple name of the current implementation class, ensuring that each factory has a unique identifier. - **`CatalogAccessController createAccessController(Map<String, String> prop)`**: Creates a new instance of `CatalogAccessController` and initializes it with the provided properties. ## Factory Identifier Each class implementing `AccessControllerFactory` will automatically use its class name as the factory identifier. This helps in identifying different factory instances during plugin loading and selection. ## Instance Creation The `createAccessController` method allows you to create and initialize `CatalogAccessController` instances. The `prop` parameter provides the configuration properties needed for initialization. ## Compatibility - If you are using the previously built-in `range-dorir` authentication plugin, no configuration changes are required; it will continue to function as before. - For custom plugins, configuration information should be defined in `conf/access.conf`. Then, in `fe.conf`, specify the `access_controller_type` as the identifier for the custom plugin. ## How to Extend - Add the `fe-core` dependency to your Maven `pom.xml` file. ```xml <dependency> <groupId>org.apache.doris</groupId> <artifactId>fe-core</artifactId> <version>1.2-SNAPSHOT</version> <scope>provided</scope> </dependency> ``` Then, implement the AccessControllerFactory interface to create your own plugin factory class as follows: ```java public class SimpleAccessControllerFactory implements AccessControllerFactory { @OverRide public String factoryIdentifier() { return "local-simple"; } @OverRide public CatalogAccessController createAccessController(Map<String, String> map) { return new SimpleAccessController(map); } } package org.example.access; import org.apache.doris.analysis.ResourceTypeEnum; import org.apache.doris.analysis.UserIdentity; import org.apache.doris.common.AuthorizationException; import org.apache.doris.mysql.privilege.CatalogAccessController; import org.apache.doris.mysql.privilege.DataMaskPolicy; import org.apache.doris.mysql.privilege.PrivPredicate; import org.apache.doris.mysql.privilege.RowFilterPolicy; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; public class SimpleAccessController implements CatalogAccessController { private HashMap<String, Boolean> databasePrivs = new HashMap<>(); // just for test public SimpleAccessController(Map<String, String> prop) { prop.forEach((k, v) -> { databasePrivs.put(k, Boolean.parseBoolean(v)); }); } @OverRide public boolean checkGlobalPriv(UserIdentity userIdentity, PrivPredicate privPredicate) { return false; } @OverRide public boolean checkCtlPriv(UserIdentity userIdentity, String s, PrivPredicate privPredicate) { return true; } ... ``` Add a new folder named **META-INF/services** under the resources directory, Create a new file named **org.apache.doris.mysql.privilege.AccessControllerFactory.** with a file containing **org.apache.doris.mysql.privilege.AccessControllerFactory.** ## How to Use - In `fe.conf`, specify the **access_controller_type=local-simple** - Put the jar file containing the custom plugin in the **fe/custom_lib** directory. (cherry picked from commit dd5605e)
…pache#40750) The `AccessControllerFactory` interface is responsible for creating and managing `CatalogAccessController` instances. The interface includes the following methods: - **`default String factoryIdentifier()`**: Returns the identifier for the factory, defaulting to the simple name of the implementing class. To maintain compatibility with user-defined plugins from older versions, the `factoryIdentifier` method provides a default implementation that returns the simple name of the current implementation class, ensuring that each factory has a unique identifier. - **`CatalogAccessController createAccessController(Map<String, String> prop)`**: Creates a new instance of `CatalogAccessController` and initializes it with the provided properties. Each class implementing `AccessControllerFactory` will automatically use its class name as the factory identifier. This helps in identifying different factory instances during plugin loading and selection. The `createAccessController` method allows you to create and initialize `CatalogAccessController` instances. The `prop` parameter provides the configuration properties needed for initialization. - If you are using the previously built-in `range-dorir` authentication plugin, no configuration changes are required; it will continue to function as before. - For custom plugins, configuration information should be defined in `conf/access.conf`. Then, in `fe.conf`, specify the `access_controller_type` as the identifier for the custom plugin. - Add the `fe-core` dependency to your Maven `pom.xml` file. ```xml <dependency> <groupId>org.apache.doris</groupId> <artifactId>fe-core</artifactId> <version>1.2-SNAPSHOT</version> <scope>provided</scope> </dependency> ``` Then, implement the AccessControllerFactory interface to create your own plugin factory class as follows: ```java public class SimpleAccessControllerFactory implements AccessControllerFactory { @OverRide public String factoryIdentifier() { return "local-simple"; } @OverRide public CatalogAccessController createAccessController(Map<String, String> map) { return new SimpleAccessController(map); } } package org.example.access; import org.apache.doris.analysis.ResourceTypeEnum; import org.apache.doris.analysis.UserIdentity; import org.apache.doris.common.AuthorizationException; import org.apache.doris.mysql.privilege.CatalogAccessController; import org.apache.doris.mysql.privilege.DataMaskPolicy; import org.apache.doris.mysql.privilege.PrivPredicate; import org.apache.doris.mysql.privilege.RowFilterPolicy; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; public class SimpleAccessController implements CatalogAccessController { private HashMap<String, Boolean> databasePrivs = new HashMap<>(); // just for test public SimpleAccessController(Map<String, String> prop) { prop.forEach((k, v) -> { databasePrivs.put(k, Boolean.parseBoolean(v)); }); } @OverRide public boolean checkGlobalPriv(UserIdentity userIdentity, PrivPredicate privPredicate) { return false; } @OverRide public boolean checkCtlPriv(UserIdentity userIdentity, String s, PrivPredicate privPredicate) { return true; } ... ``` Add a new folder named **META-INF/services** under the resources directory, Create a new file named **org.apache.doris.mysql.privilege.AccessControllerFactory.** with a file containing **org.apache.doris.mysql.privilege.AccessControllerFactory.** - In `fe.conf`, specify the **access_controller_type=local-simple** - Put the jar file containing the custom plugin in the **fe/custom_lib** directory.
…arization (apache#40750) apache#40750 (cherry picked from commit dd5605e)
AccessControllerFactory Interface
Overview
The
AccessControllerFactoryinterface is responsible for creating and managingCatalogAccessControllerinstances. The interface includes the following methods:default String factoryIdentifier(): Returns the identifier for the factory, defaulting to the simple name of the implementing class. To maintain compatibility with user-defined plugins from older versions, thefactoryIdentifiermethod provides a default implementation that returns the simple name of the current implementation class, ensuring that each factory has a unique identifier.CatalogAccessController createAccessController(Map<String, String> prop): Creates a new instance ofCatalogAccessControllerand initializes it with the provided properties.Factory Identifier
Each class implementing
AccessControllerFactorywill automatically use its class name as the factory identifier. This helps in identifying different factory instances during plugin loading and selection.Instance Creation
The
createAccessControllermethod allows you to create and initializeCatalogAccessControllerinstances. Thepropparameter provides the configuration properties needed for initialization.Compatibility
range-dorirauthentication plugin, no configuration changes are required; it will continue to function as before.conf/access.conf. Then, infe.conf, specify theaccess_controller_typeas the identifier for the custom plugin.How to Extend
fe-coredependency to your Mavenpom.xmlfile.Then, implement the AccessControllerFactory interface to create your own plugin factory class as follows:
Add a new folder named META-INF/services under the resources directory, Create a new file named org.apache.doris.mysql.privilege.AccessControllerFactory. with a file containing org.apache.doris.mysql.privilege.AccessControllerFactory.
How to Use
fe.conf, specify the access_controller_type=local-simple