Note that this KIP proposal is derived from a proposal by Grant Henke that was part of KIP-4 - Command line and centralized administrative operations.
Status
Current state: Under Discussion
Discussion thread: TBD
JIRA:
Please keep the discussion on the mailing list rather than commenting on the wiki (wiki discussions get unwieldy fast).
Motivation
KIP-4 - Command line and centralized administrative operations outlines the motivation for exposing admin operations via the protocol:
- Allows clients in any language to administrate Kafka
- Wire protocol is supported by any language
- Provides public client for performing admin operations
- Ensures integration test code in other projects and clients maintains compatibility
- Prevents users from needing to use the Command classes and work around standard output and system exits
- Removing the need for admin scripts (kafka-configs.sh, kafka-topics.sh, etc) to talk directly to Zookeeper.
- Allows ZNodes to be completely locked down via ACLs
- Further hides the Zookeeper details of Kafka
A couple of specific use cases are worth pointing out:
- The Metadata request exposes topic metadata, but it does not expose topic configs. ListConfigs will make that information available to any client of the Kafka protocol and the AdminClient will expose it to normal users.
- AlterConfigs would make it possible to update topic configs, but also client and replication quotas via the protocol and the AdminClient.
Public Interfaces
ACLs
A new ACL resource type `Configs` will be introduced with Describe, Alter and All operations. Initially, this resource type will work at a global level like the Cluster resource type. That is, the only valid resource name will be "kafka-cluster". This leaves the door open for evolving this to be more fine-grained in the future.
Protocol APIs
Wire Format types
Entity types will be encoded to INT8 in the following way:
- 0: Unknown
- 1: Any (for filtering, but currently unused)
- 2: Broker
- 3: Topic
- 4: Client
List Configs
ListConfigs Request (Version: 0) => [entities] entities => entity_type entity_name entity_type => INT8 entity_name => STRING
Request semantics:
- Can be sent to any broker
- If there are multiple instructions for the same entity in one request the extra request will be ignored
- This is because the list of entities is modeled server side as a set
- Multiple entities results in the same end goal, so handling this error for the user should be okay
- This is similar to how delete topics handles requests
- Entity types are "Topic", "Client", and "Broker".
- If entity_type is "Broker" and entity_name matches the broker that has received the request, read-only configs for this broker are also returned.
- The principal must be authorized to "Describe" the "Configs" resource type or "Describe" the "Cluster" resource type. Unauthorized requests will receive a ConfigsAuthorization error code.
ListConfigs Response (Version: 0) => error_code [entities] error_code => INT16 entities => entity_type entity_name [configs] entity_type => INT8 entity_name => STRING configs => config_name => STRING config_value => STRING read_only => BOOLEAN is_default => BOOLEAN is_sensitive => BOOLEAN
Alter Configs
AlterConfigs Request (Version: 0) => [entities] validate_only validate_only => BOOLEAN entities => entity_type entity_name [configs] entity_type => INT8 entity_name => STRING configs => config_name => STRING config_value => STRING
Request Semantics
- Can be sent to any broker
- If there are multiple instructions for the same entity in one request, an InvalidRequestException will be logged on the broker and a single error code for that topic will be returned to the client
- This is because the list of entities is modeled server side as a map with entity as the key
- Entity types are "Topic", "Client", and "Broker".
- The principal must be authorized to "Alter" the "Configs" resource type or "Alter" the "Cluster" resource type. Unauthorized requests will receive a ConfigsAuthorization for all entities.
- If an
Alter
operation is attempted on a read-only config, anUnsupportedOperation
error will be returned for the relevant entity. - The request is not transactional.
- If an error occurs for an entity, others could still be updated.
- Errors are reported independently per entity.
- For tools that allow users to alter configs, a validation/dry-run mode where validation errors are reported but no creation is attempted is available via the validate_only parameter.
AlterConfigs Response (Version: 0) => [responses] responses => entity_type entity_name error_code error_message entity_type => INT8 entity_name => STRING error_code => INT16 error_message => STRING
Policy
In a similar fashion to KIP-108: Create Topic Policy, we allow users to define a policy class to validate alter configs requests. The config name will be alter.configs.policy.class.name
and the interface follows:
package org.apache.kafka.server.policy; public interface AlterConfigsPolicy extends Configurable, AutoCloseable { /** * Class containing the create request parameters. */ class RequestMetadata { /** * Create an instance of this class with the provided parameters. * * This constructor is public to make testing of <code>AlterConfigPolicy</code> implementations easier. */ public RequestMetadata(ConfigEntity entity, Map<String, String> configs) { ... } /** * Return configs in the request. */ public Map<String, String> configs() { ... } } /** * Validate the request parameters and throw a <code>PolicyViolationException</code> with a suitable error * message if the alter configs request parameters for the provided entity do not satisfy this policy. * * Clients will receive the POLICY_VIOLATION error code along with the exception's message. Note that validation * failure only affects the relevant entity, other entities in the request will still be processed. * * @param requestMetadata the alter configs request parameters for the provided entity. * @throws PolicyViolationException if the request parameters do not satisfy this policy. */ void validate(RequestMetadata requestMetadata) throws PolicyViolationException; }
Users will have to ensure that the policy implementation code is in the broker's classpath. Implementations should throw the existing PolicyViolationException
with an appropriate error message if the request does not fulfill the policy requirements. We chose a generic name for the only parameter of the validate
method in case we decide to add parameters that are not strictly related to the topic (e.g. session information) in the future. The constructor of RequestMetadata
is public to make testing convenient for users. Under normal circumstances, it should only be instantiated by Kafka. We chose to create separate API classes instead of reusing request classes to make it easier to evolve the latter.
AdminClient APIs
They follow a similar pattern as existing AdminClient APIs:
public class AdminClient { public ListConfigsResult listConfigs(List<ConfigEntity> entities, ListConfigsOptions options); public AlterConfigsResult alterConfigs(Map<ConfigEntity, List<Config>> configs, AlterConfigsOptions options); } public class ListConfigsOptions { public ListConfigsOptions timeoutMs(Integer timeout); } public class ListConfigsResult { public KafkaFuture<Map<ConfigEntity, Config>> all(); } public class AlterConfigsOptions { public AlterConfigsOptions timeoutMs(Integer timeout); public AlterConfigsOptions validateOnly(boolean timeout); } public class AlterConfigsResult { public KafkaFuture<Void> all(); public Map<ConfigEntity, KafkaFuture<Void>> results(); } public class ConfigEntity { enum Type { CLIENT, BROKER, TOPIC, UNKNOWN; } public ConfigEntity(Type type, String name) { ... } public Type type() { ... } public String name() { ... } } public class Config { public Config(String name, String value) { this(name, value, false, false, false); } public Config(String name, String value, boolean isDefault, boolean isSensitive, boolean isReadOnly) { ... } public String name() { ... } public String value() { ... } public boolean isDefault { ... } public boolean isSensitive { ... } public boolean isReadOnly { ... } }
Proposed Changes
The "Public Interfaces" section covers all the proposed changes.
Compatibility, Deprecation, and Migration Plan
We are adding a new ACL resource type, so third-party Authorizer implementations will potentially have to be updated in order to support it. Since this only affects newly introduced protocol and AdminClient APIs, it's not a compatibility issue. It simply means that the new functionality won't be available.
With regards to forwards compatibility, ConfigEntity.Type has an UNKNOWN element in case it receives data from a newer broker that cannot be mapped to one of the existing enum types.
Rejected Alternatives
- Allowing sensitive data to be returned: it's good security practice to never expose sensitive data. If necessary, the user can reset the relevant sensitive data (e.g. a password).
- Using a string for the wire representation of entity_type: it would be inconsistent with the approach used by KIP-140: Add administrative RPCs for adding, deleting, and listing ACLs.
Future work
- Forward requests to the relevant brokers in order to return `read-only` broker configs.
- Finer grained ACLs for configs.