diff --git a/xtable-api/src/main/java/org/apache/xtable/conversion/ExternalCatalogConfig.java b/xtable-api/src/main/java/org/apache/xtable/conversion/ExternalCatalogConfig.java index b525d8318..6ac9acf0f 100644 --- a/xtable-api/src/main/java/org/apache/xtable/conversion/ExternalCatalogConfig.java +++ b/xtable-api/src/main/java/org/apache/xtable/conversion/ExternalCatalogConfig.java @@ -58,6 +58,13 @@ public class ExternalCatalogConfig { */ String catalogConversionSourceImpl; + /** + * (Optional) A fully qualified class name that implements the interface for {@link + * org.apache.xtable.spi.sync.CatalogAccessControlPolicySyncClient} it can be used if the + * implementation for catalogType doesn't exist in XTable. + */ + String catalogPolicySyncClientImpl; + /** * The properties for this catalog, used for providing any custom behaviour during catalog sync */ diff --git a/xtable-api/src/main/java/org/apache/xtable/model/catalog/policy/InternalAccessControlPolicySnapshot.java b/xtable-api/src/main/java/org/apache/xtable/model/catalog/policy/InternalAccessControlPolicySnapshot.java new file mode 100644 index 000000000..b28bf3038 --- /dev/null +++ b/xtable-api/src/main/java/org/apache/xtable/model/catalog/policy/InternalAccessControlPolicySnapshot.java @@ -0,0 +1,70 @@ +/* + * 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. + */ + +package org.apache.xtable.model.catalog.policy; + +import java.time.Instant; +import java.util.Collections; +import java.util.Map; + +import lombok.Builder; +import lombok.Value; + +/** A snapshot of all access control data at a given point in time. */ +@Value +@Builder +public class InternalAccessControlPolicySnapshot { + /** + * A unique identifier representing this snapshot's version. + * + *

This could be a UUID, timestamp string, or any value that guarantees uniqueness across + * snapshots. + */ + String versionId; + + /** + * The moment in time when this snapshot was created. + * + *

Useful for maintaining an audit trail or comparing how policies have changed over time. + */ + Instant timestamp; + + /** + * A map of user names to {@link InternalUser} objects, capturing individual users' details such + * as assigned roles, auditing metadata, etc. + */ + @Builder.Default Map usersByName = Collections.emptyMap(); + + /** + * A map of group names to {@link InternalUserGroup} objects, representing logical groupings of + * users for easier role management. + */ + @Builder.Default Map groupsByName = Collections.emptyMap(); + + /** + * A map of role names to {@link InternalRole} objects, defining the privileges and security rules + * each role entails. + */ + @Builder.Default Map rolesByName = Collections.emptyMap(); + + /** + * A map of additional properties or metadata related to this snapshot. This map provides + * flexibility for storing information without modifying the main schema of the snapshot. + */ + @Builder.Default Map properties = Collections.emptyMap(); +} diff --git a/xtable-api/src/main/java/org/apache/xtable/model/catalog/policy/InternalChangeLogInfo.java b/xtable-api/src/main/java/org/apache/xtable/model/catalog/policy/InternalChangeLogInfo.java new file mode 100644 index 000000000..505cf7cb1 --- /dev/null +++ b/xtable-api/src/main/java/org/apache/xtable/model/catalog/policy/InternalChangeLogInfo.java @@ -0,0 +1,48 @@ +/* + * 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. + */ + +package org.apache.xtable.model.catalog.policy; + +import java.time.Instant; + +import lombok.Builder; +import lombok.Value; + +/** + * Contains change-log information for roles, users, or user groups, enabling traceability of who + * created or last modified them. + * + *

This class is useful for governance and compliance scenarios, where an audit trail is + * necessary. It can be extended to include additional fields such as reasonForChange or + * changeDescription. + */ +@Value +@Builder +public class InternalChangeLogInfo { + /** The username or identifier of the entity that created this record. */ + String createdBy; + + /** The username or identifier of the entity that last modified this record. */ + String lastModifiedBy; + + /** The timestamp when this record was created. */ + Instant createdAt; + + /** The timestamp when this record was last modified. */ + Instant lastModifiedAt; +} diff --git a/xtable-api/src/main/java/org/apache/xtable/model/catalog/policy/InternalPrivilege.java b/xtable-api/src/main/java/org/apache/xtable/model/catalog/policy/InternalPrivilege.java new file mode 100644 index 000000000..48650b1df --- /dev/null +++ b/xtable-api/src/main/java/org/apache/xtable/model/catalog/policy/InternalPrivilege.java @@ -0,0 +1,45 @@ +/* + * 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. + */ + +package org.apache.xtable.model.catalog.policy; + +import lombok.Builder; +import lombok.Value; + +/** + * Represents a single privilege assignment for a securable object. + * + *

This defines the kind of operation (e.g., SELECT, CREATE, MODIFY) and whether it is allowed or + * denied. Some catalogs may only accept ALLOW rules and treat all other operations as denied by + * default. + */ +@Value +@Builder +public class InternalPrivilege { + /** + * The type of privilege, such as SELECT, CREATE, or MODIFY. Each implementation can define its + * own set of enums. + */ + InternalPrivilegeType privilegeType; + + /** + * The decision, typically ALLOW or DENY. Some catalogs may not support DENY explicitly, + * defaulting to ALLOW. + */ + String privilegeDecision; +} diff --git a/xtable-api/src/main/java/org/apache/xtable/model/catalog/policy/InternalPrivilegeType.java b/xtable-api/src/main/java/org/apache/xtable/model/catalog/policy/InternalPrivilegeType.java new file mode 100644 index 000000000..bcd5debfb --- /dev/null +++ b/xtable-api/src/main/java/org/apache/xtable/model/catalog/policy/InternalPrivilegeType.java @@ -0,0 +1,71 @@ +/* + * 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. + */ + +package org.apache.xtable.model.catalog.policy; + +/** + * Specifies a set of privileges that can be granted or revoked for securable objects. + * + *

This enum is used to indicate the type of actions that a subject (user, role, group) is + * allowed to perform on a given resource, such as a catalog, database, table, or other securable + * entity. + */ +public enum InternalPrivilegeType { + + /** Grants all available privileges on the resource. */ + ALL, + + /** + * Allows modification of the structure or metadata of the resource. For example, modifying + * schemas or properties. + */ + ALTER, + + /** + * Allows describing or viewing the metadata of the resource. Typically applies to viewing schemas + * or properties of the resource. + */ + DESCRIBE, + + /** + * Allows reading or selecting data from the resource. Commonly associated with performing SQL + * SELECT statements. + */ + SELECT, + + /** + * Allows inserting new data into the resource. Typically granted for operations like SQL INSERT + * statements. + */ + INSERT, + + /** + * Allows updating existing data within the resource. Typically granted for operations like SQL + * UPDATE statements. + */ + UPDATE, + + /** Allows creating new resources within the catalog. */ + CREATE, + + /** Allows deleting or dropping a resource, such as a database or a table. */ + DROP, + + /** Allows removing data from the resource, for example using SQL DELETE statements. */ + DELETE +} diff --git a/xtable-api/src/main/java/org/apache/xtable/model/catalog/policy/InternalRole.java b/xtable-api/src/main/java/org/apache/xtable/model/catalog/policy/InternalRole.java new file mode 100644 index 000000000..76f04605c --- /dev/null +++ b/xtable-api/src/main/java/org/apache/xtable/model/catalog/policy/InternalRole.java @@ -0,0 +1,51 @@ +/* + * 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. + */ + +package org.apache.xtable.model.catalog.policy; + +import java.util.List; +import java.util.Map; + +import lombok.Builder; +import lombok.Value; + +/** + * Represents a role within the catalog. + * + *

A role can be granted access to multiple securable objects, each with its own set of + * privileges. Audit info is stored to track the role's creation and modifications, and a properties + * map can hold additional metadata. + */ +@Value +@Builder +public class InternalRole { + /** The unique name or identifier for the role. */ + String name; + + /** The list of securable objects this role can access. */ + List securableObjects; + + /** Contains information about how and when this role was created and last modified. */ + InternalChangeLogInfo changeLogInfo; + + /** + * A map to store additional metadata or properties related to this role. For example, this might + * include a description, usage instructions, or any catalog-specific fields. + */ + Map properties; +} diff --git a/xtable-api/src/main/java/org/apache/xtable/model/catalog/policy/InternalSecurableObject.java b/xtable-api/src/main/java/org/apache/xtable/model/catalog/policy/InternalSecurableObject.java new file mode 100644 index 000000000..0a7c5e913 --- /dev/null +++ b/xtable-api/src/main/java/org/apache/xtable/model/catalog/policy/InternalSecurableObject.java @@ -0,0 +1,45 @@ +/* + * 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. + */ + +package org.apache.xtable.model.catalog.policy; + +import java.util.List; + +import lombok.Builder; +import lombok.Value; + +/** + * Represents a securable object in the catalog, which can be managed by access control. + * + *

Examples of securable objects include catalogs, schemas, tables, views, or any other data + * objects that require fine-grained privilege management. Each securable object can have one or + * more privileges assigned to it. + */ +@Value +@Builder +public class InternalSecurableObject { + /** The identifier of the securable object. */ + InternalSecurableObjectIdentifier securableObjectIdentifier; + /** + * The type of securable object, such as TABLE, VIEW, FUNCTION, etc. Each implementation can + * define its own set of enums. + */ + InternalSecurableObjectType securableObjectType; + /** The set of privileges assigned to this object. */ + List privileges; +} diff --git a/xtable-api/src/main/java/org/apache/xtable/model/catalog/policy/InternalSecurableObjectIdentifier.java b/xtable-api/src/main/java/org/apache/xtable/model/catalog/policy/InternalSecurableObjectIdentifier.java new file mode 100644 index 000000000..d13403ae3 --- /dev/null +++ b/xtable-api/src/main/java/org/apache/xtable/model/catalog/policy/InternalSecurableObjectIdentifier.java @@ -0,0 +1,36 @@ +/* + * 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. + */ + +package org.apache.xtable.model.catalog.policy; + +/** + * Defines a structure for obtaining a unique, canonical identifier for a securable object within + * the catalog. + * + *

Implementations of this interface may represent entities such as catalogs, databases, tables, + * or any other resource that can be protected or controlled via security policies. + */ +public interface InternalSecurableObjectIdentifier { + + /** + * Returns the unique identifier of the securable object in a canonical form. + * + * @return a non-null {@link String} representing the unique identifier of this securable object + */ + String getId(); +} diff --git a/xtable-api/src/main/java/org/apache/xtable/model/catalog/policy/InternalSecurableObjectType.java b/xtable-api/src/main/java/org/apache/xtable/model/catalog/policy/InternalSecurableObjectType.java new file mode 100644 index 000000000..13ba7247a --- /dev/null +++ b/xtable-api/src/main/java/org/apache/xtable/model/catalog/policy/InternalSecurableObjectType.java @@ -0,0 +1,55 @@ +/* + * 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. + */ + +package org.apache.xtable.model.catalog.policy; + +/** + * Identifies the type of securable object within the catalog. + * + *

Each attribute in this enum represents a different kind of resource for which permissions may + * be managed or enforced. + */ +public enum InternalSecurableObjectType { + + /** Represents the root container in which databases and other objects reside. */ + CATALOG, + + /** Represents a logical grouping of tables and other related objects. */ + DATABASE, + + /** Represents a table, typically containing rows and columns of data. */ + TABLE, + + /** Represents a view, which is often a virtual table defined by a query. */ + VIEW, + + /** + * Represents a partition, commonly used to segment table data for performance or organizational + * reasons. + */ + PARTITION, + + /** Represents a column, generally a single field within a table or partition. */ + COLUMN, + + /** Represents a function, such as a user-defined function (UDF) within the database system. */ + FUNCTION, + + /** Represents an unsupported object type for error handling. */ + UNSUPPORTED +} diff --git a/xtable-api/src/main/java/org/apache/xtable/model/catalog/policy/InternalUser.java b/xtable-api/src/main/java/org/apache/xtable/model/catalog/policy/InternalUser.java new file mode 100644 index 000000000..f39f8e322 --- /dev/null +++ b/xtable-api/src/main/java/org/apache/xtable/model/catalog/policy/InternalUser.java @@ -0,0 +1,43 @@ +/* + * 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. + */ + +package org.apache.xtable.model.catalog.policy; + +import java.util.List; + +import lombok.Builder; +import lombok.Value; + +/** + * Represents an individual user within the catalog. + * + *

A user may be assigned multiple roles, and can also belong to a specific user group. Audit + * information is stored to allow tracking of who created or last modified the user. + */ +@Value +@Builder +public class InternalUser { + /** The unique name or identifier for the user. */ + String name; + + /** The list of roles assigned to this user. */ + List roles; + + /** Contains information about how and when this user was created and last modified. */ + InternalChangeLogInfo changeLogInfo; +} diff --git a/xtable-api/src/main/java/org/apache/xtable/model/catalog/policy/InternalUserGroup.java b/xtable-api/src/main/java/org/apache/xtable/model/catalog/policy/InternalUserGroup.java new file mode 100644 index 000000000..179f95490 --- /dev/null +++ b/xtable-api/src/main/java/org/apache/xtable/model/catalog/policy/InternalUserGroup.java @@ -0,0 +1,43 @@ +/* + * 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. + */ + +package org.apache.xtable.model.catalog.policy; + +import java.util.List; + +import lombok.Builder; +import lombok.Value; + +/** + * Represents a user group within the catalog. + * + *

Groups can have multiple roles assigned, and also include audit information to track creation + * and modifications. + */ +@Value +@Builder +public class InternalUserGroup { + /** The unique name or identifier for the user group. */ + String name; + + /** The list of roles assigned to this group. */ + List roles; + + /** Contains information about how and when this group was created and last modified. */ + InternalChangeLogInfo changeLogInfo; +} diff --git a/xtable-api/src/main/java/org/apache/xtable/model/sync/policy/PolicySyncResult.java b/xtable-api/src/main/java/org/apache/xtable/model/sync/policy/PolicySyncResult.java new file mode 100644 index 000000000..1e936f5eb --- /dev/null +++ b/xtable-api/src/main/java/org/apache/xtable/model/sync/policy/PolicySyncResult.java @@ -0,0 +1,156 @@ +/* + * 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. + */ + +package org.apache.xtable.model.sync.policy; + +import java.time.Duration; +import java.time.Instant; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import lombok.Builder; +import lombok.Value; + +import org.apache.xtable.annotations.Evolving; +import org.apache.xtable.model.sync.ErrorDetails; +import org.apache.xtable.model.sync.SyncStatusCode; + +/** + * Represents the result of a policy sync between catalogs, capturing details of roles, users, and + * user groups. + */ +@Value +@Builder +@Evolving +public class PolicySyncResult { + + /** List of role sync results. */ + @Builder.Default List rolesSyncResult = new ArrayList<>(); + + /** List of user sync results. */ + @Builder.Default List usersSyncResult = new ArrayList<>(); + + /** List of user group sync results. */ + @Builder.Default List userGroupsSyncResult = new ArrayList<>(); + + /** The start time of the policy sync. */ + Instant startTime; + + /** The duration of the policy sync. */ + Duration duration; + + /** Represents the sync result for a specific role, including privileges and status. */ + @Value + public static class RoleSyncResult { + /** The name of the role. */ + String roleName; + + /** Mapping of securable objects to their privilege sync info details. */ + Map> privilegeSyncInfos; + + /** The status of the role sync (e.g., SUCCESS or ERROR). */ + SyncStatusCode statusCode; + + /** Details of any errors that occurred during synchronization. */ + ErrorDetails errorDetails; + + /** + * Builds a {@link PolicySyncResult.RoleSyncResult} for a given role. + * + * @param roleName The name of the role. + * @param privilegeSyncInfos A map of privileges associated with the role. + * @param errorDetails exception details if an error occurred, otherwise null. + * @return A RoleSyncResult object containing the synchronization details. + */ + public static PolicySyncResult.RoleSyncResult create( + String roleName, + Map> privilegeSyncInfos, + ErrorDetails errorDetails) { + + SyncStatusCode statusCode = + errorDetails == null ? SyncStatusCode.SUCCESS : SyncStatusCode.ERROR; + return new RoleSyncResult(roleName, privilegeSyncInfos, statusCode, errorDetails); + } + } + + /** Represents the sync result for a specific user. */ + @Value + public static class UserSyncResult { + /** The name of the user. */ + String userName; + + /** List of role grant synchronization details. */ + List roleGrantSyncInfos; + + /** The status of the user synchronization. */ + SyncStatusCode statusCode; + + /** Details of any errors that occurred during synchronization. */ + ErrorDetails errorDetails; + + /** + * Builds a {@link PolicySyncResult.UserSyncResult} for a given user. + * + * @param userName The name of the user. + * @param roleGrantSyncInfos List of role grant synchronization information. + * @param errorDetails exception details if an error occurred, otherwise null. + * @return A UserSyncResult object containing the synchronization details. + */ + public static PolicySyncResult.UserSyncResult create( + String userName, List roleGrantSyncInfos, ErrorDetails errorDetails) { + + SyncStatusCode statusCode = + errorDetails == null ? SyncStatusCode.SUCCESS : SyncStatusCode.ERROR; + return new UserSyncResult(userName, roleGrantSyncInfos, statusCode, errorDetails); + } + } + + /** Represents the synchronization result for a user group. */ + @Value + public static class UserGroupSyncResult { + /** The name of the user group. */ + String userGroupName; + + /** List of role grant sync details. */ + List roleGrantSyncInfos; + + /** The status of the user group synchronization. */ + SyncStatusCode statusCode; + + /** Details of any errors that occurred during synchronization. */ + ErrorDetails errorDetails; + + /** + * Builds a {@link PolicySyncResult.UserGroupSyncResult} for a given user group. + * + * @param groupName The name of the user group. + * @param roleGrantSyncInfos List of role grant synchronization information. + * @param errorDetails exception details if an error occurred, otherwise null. + * @return A UserGroupSyncResult object containing the synchronization details. + */ + public static PolicySyncResult.UserGroupSyncResult create( + String groupName, List roleGrantSyncInfos, ErrorDetails errorDetails) { + + SyncStatusCode statusCode = + errorDetails == null ? SyncStatusCode.SUCCESS : SyncStatusCode.ERROR; + return new UserGroupSyncResult(groupName, roleGrantSyncInfos, statusCode, errorDetails); + } + } +} diff --git a/xtable-api/src/main/java/org/apache/xtable/model/sync/policy/PrivilegeSyncInfo.java b/xtable-api/src/main/java/org/apache/xtable/model/sync/policy/PrivilegeSyncInfo.java new file mode 100644 index 000000000..4a559e4fc --- /dev/null +++ b/xtable-api/src/main/java/org/apache/xtable/model/sync/policy/PrivilegeSyncInfo.java @@ -0,0 +1,52 @@ +/* + * 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. + */ + +package org.apache.xtable.model.sync.policy; + +import lombok.Value; + +import org.apache.xtable.annotations.Evolving; +import org.apache.xtable.model.catalog.policy.InternalPrivilegeType; +import org.apache.xtable.model.sync.ErrorDetails; +import org.apache.xtable.model.sync.SyncStatusCode; + +/** + * Represents the synchronization details of a specific privilege, including its type, status, and + * any associated errors. + */ +@Value +@Evolving +public class PrivilegeSyncInfo { + + /** The type of privilege (e.g., SELECT, INSERT, DELETE). */ + String privilegeType; + + /** The status of the privilege sync (e.g., SUCCESS, ERROR). */ + SyncStatusCode statusCode; + + /** Details of any errors that occurred during synchronization. */ + ErrorDetails errorDetails; + + public static PrivilegeSyncInfo create( + InternalPrivilegeType internalPrivilegeType, ErrorDetails errorDetails) { + + SyncStatusCode statusCode = + errorDetails == null ? SyncStatusCode.SUCCESS : SyncStatusCode.ERROR; + return new PrivilegeSyncInfo(internalPrivilegeType.name(), statusCode, errorDetails); + } +} diff --git a/xtable-api/src/main/java/org/apache/xtable/model/sync/policy/RoleGrantSyncInfo.java b/xtable-api/src/main/java/org/apache/xtable/model/sync/policy/RoleGrantSyncInfo.java new file mode 100644 index 000000000..561964004 --- /dev/null +++ b/xtable-api/src/main/java/org/apache/xtable/model/sync/policy/RoleGrantSyncInfo.java @@ -0,0 +1,53 @@ +/* + * 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. + */ + +package org.apache.xtable.model.sync.policy; + +import lombok.Value; + +import org.apache.xtable.annotations.Evolving; +import org.apache.xtable.model.sync.ErrorDetails; +import org.apache.xtable.model.sync.SyncStatusCode; + +/** Represents the synchronization result of a role grant operation, */ +@Value +@Evolving +public class RoleGrantSyncInfo { + + /** The name of the role being granted. */ + String roleName; + + /** The status of the role grant synchronization (e.g., SUCCESS, ERROR). */ + SyncStatusCode status; + + /** Details of any errors that occurred during the synchronization. */ + ErrorDetails errorDetails; + + /** + * Builds a {@link RoleGrantSyncInfo} object for a given role. + * + * @param roleName The name of the role. + * @param errorDetails exception details if an error occurred, otherwise null. + * @return A RoleGrantSyncInfo object. + */ + public static RoleGrantSyncInfo create(String roleName, ErrorDetails errorDetails) { + SyncStatusCode statusCode = + errorDetails == null ? SyncStatusCode.SUCCESS : SyncStatusCode.ERROR; + return new RoleGrantSyncInfo(roleName, statusCode, errorDetails); + } +} diff --git a/xtable-api/src/main/java/org/apache/xtable/model/sync/policy/SecurableObjectInfo.java b/xtable-api/src/main/java/org/apache/xtable/model/sync/policy/SecurableObjectInfo.java new file mode 100644 index 000000000..d7974cefc --- /dev/null +++ b/xtable-api/src/main/java/org/apache/xtable/model/sync/policy/SecurableObjectInfo.java @@ -0,0 +1,50 @@ +/* + * 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. + */ + +package org.apache.xtable.model.sync.policy; + +import lombok.Value; + +import org.apache.xtable.annotations.Evolving; +import org.apache.xtable.model.catalog.policy.InternalSecurableObject; + +/** + * Represents metadata about a securable object, such as a database, table. This class holds basic + * identification details like the object's name and type. + */ +@Value +@Evolving +public class SecurableObjectInfo { + /** The name of the securable object. */ + String name; + + /** The type of the securable object (e.g., "DATABASE", "TABLE", "VIEW"). */ + String objectType; + + /** + * Builds a {@link SecurableObjectInfo} object from an {@link InternalSecurableObject}. + * + * @param securableObject The internal securable object. + * @return A SecurableObjectInfo object. + */ + public static SecurableObjectInfo create(InternalSecurableObject securableObject) { + return new SecurableObjectInfo( + securableObject.getSecurableObjectIdentifier().getId(), + securableObject.getSecurableObjectType().name()); + } +} diff --git a/xtable-api/src/main/java/org/apache/xtable/spi/sync/CatalogAccessControlPolicySyncClient.java b/xtable-api/src/main/java/org/apache/xtable/spi/sync/CatalogAccessControlPolicySyncClient.java new file mode 100644 index 000000000..1478a0d43 --- /dev/null +++ b/xtable-api/src/main/java/org/apache/xtable/spi/sync/CatalogAccessControlPolicySyncClient.java @@ -0,0 +1,70 @@ +/* + * 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. + */ + +package org.apache.xtable.spi.sync; + +import org.apache.xtable.annotations.Evolving; +import org.apache.xtable.model.catalog.policy.InternalAccessControlPolicySnapshot; +import org.apache.xtable.model.sync.SyncResult; +import org.apache.xtable.model.sync.policy.PolicySyncResult; + +/** + * Defines the contract for synchronizing access control policies between a specific catalog and the + * internal canonical model. + * + *

Implementations of this interface are responsible for: + * + *

+ */ +@Evolving +public interface CatalogAccessControlPolicySyncClient { + /** + * Fetches the current policies from the catalog, converting them into the internal canonical + * model. + * + *

This method allows you to pull in the catalog’s native policy definitions (e.g., roles, + * privileges, user/groups) and map them into a {@link InternalAccessControlPolicySnapshot} so + * that they can be managed or merged with your centralized policy framework. + * + * @return A {@code CatalogAccessControlPolicySnapshot} containing the catalog’s current policies. + */ + InternalAccessControlPolicySnapshot fetchPolicies(); + + /** + * Pushes the canonical policy snapshot into the target catalog, converting it into the catalog’s + * native policy definitions and applying any necessary updates. + * + *

This method typically performs the following steps: + * + *

    + *
  1. Transforms the given {@code InternalAccessControlPolicySnapshot} into the catalog’s + * native format (roles, privileges, etc.). + *
  2. Applies the resulting policy definitions to the catalog, potentially overwriting or + * merging existing policies. + *
  3. Returns a {@link SyncResult} detailing the success or failure of the operation. + *
+ * + * @param snapshot The access control policy snapshot to be synchronized with the catalog. + */ + PolicySyncResult pushPolicies(InternalAccessControlPolicySnapshot snapshot); +} diff --git a/xtable-core/src/main/java/org/apache/xtable/catalog/CatalogConversionFactory.java b/xtable-core/src/main/java/org/apache/xtable/catalog/CatalogConversionFactory.java index 777811bef..371db0325 100644 --- a/xtable-core/src/main/java/org/apache/xtable/catalog/CatalogConversionFactory.java +++ b/xtable-core/src/main/java/org/apache/xtable/catalog/CatalogConversionFactory.java @@ -31,6 +31,7 @@ import org.apache.xtable.exception.NotSupportedException; import org.apache.xtable.reflection.ReflectionUtils; import org.apache.xtable.spi.extractor.CatalogConversionSource; +import org.apache.xtable.spi.sync.CatalogAccessControlPolicySyncClient; import org.apache.xtable.spi.sync.CatalogSyncClient; @NoArgsConstructor(access = AccessLevel.PRIVATE) @@ -88,6 +89,19 @@ public CatalogSyncClient
createCatalogSyncClient( configuration); } + /** + * Returns an implementation class for {@link CatalogAccessControlPolicySyncClient} that'll be + * used for fetching / syncing policies from / to catalog + * + * @param catalogConfig configuration for the catalog + * @param configuration hadoop configuration + */ + public CatalogAccessControlPolicySyncClient createCatalogPolicySyncClient( + ExternalCatalogConfig catalogConfig, Configuration configuration) { + return ReflectionUtils.createInstanceOfClass( + catalogConfig.getCatalogPolicySyncClientImpl(), catalogConfig, configuration); + } + private static T findInstanceByCatalogType( Class serviceClass, String catalogType, Function catalogTypeExtractor) { ServiceLoader loader = ServiceLoader.load(serviceClass); diff --git a/xtable-core/src/test/java/org/apache/xtable/catalog/TestCatalogConversionFactory.java b/xtable-core/src/test/java/org/apache/xtable/catalog/TestCatalogConversionFactory.java index 1d05666b8..9f5801168 100644 --- a/xtable-core/src/test/java/org/apache/xtable/catalog/TestCatalogConversionFactory.java +++ b/xtable-core/src/test/java/org/apache/xtable/catalog/TestCatalogConversionFactory.java @@ -29,8 +29,10 @@ import org.apache.xtable.conversion.TargetCatalogConfig; import org.apache.xtable.model.catalog.ThreePartHierarchicalTableIdentifier; import org.apache.xtable.spi.extractor.CatalogConversionSource; +import org.apache.xtable.spi.sync.CatalogAccessControlPolicySyncClient; import org.apache.xtable.spi.sync.CatalogSyncClient; import org.apache.xtable.testutil.ITTestUtils; +import org.apache.xtable.testutil.ITTestUtils.TestCatalogAccessControlPolicySyncClientImpl; import org.apache.xtable.testutil.ITTestUtils.TestCatalogConversionSourceImpl; import org.apache.xtable.testutil.ITTestUtils.TestCatalogSyncImpl; @@ -105,4 +107,21 @@ void createCatalogSyncClientForCatalogType() { targetCatalogConfig.getCatalogConfig(), "TABLE_FORMAT", new Configuration()); assertEquals(catalogSyncClient.getClass().getName(), TestCatalogSyncImpl.class.getName()); } + + @Test + void createCatalogPolicySyncClient() { + ExternalCatalogConfig externalCatalogConfig = + ExternalCatalogConfig.builder() + .catalogId("catalogId") + .catalogPolicySyncClientImpl( + TestCatalogAccessControlPolicySyncClientImpl.class.getName()) + .catalogProperties(Collections.emptyMap()) + .build(); + CatalogAccessControlPolicySyncClient catalogSyncClient = + CatalogConversionFactory.getInstance() + .createCatalogPolicySyncClient(externalCatalogConfig, new Configuration()); + assertEquals( + catalogSyncClient.getClass().getName(), + TestCatalogAccessControlPolicySyncClientImpl.class.getName()); + } } diff --git a/xtable-core/src/test/java/org/apache/xtable/testutil/ITTestUtils.java b/xtable-core/src/test/java/org/apache/xtable/testutil/ITTestUtils.java index 75c3833ad..3c4f38417 100644 --- a/xtable-core/src/test/java/org/apache/xtable/testutil/ITTestUtils.java +++ b/xtable-core/src/test/java/org/apache/xtable/testutil/ITTestUtils.java @@ -30,10 +30,13 @@ import org.apache.xtable.conversion.SourceTable; import org.apache.xtable.model.InternalTable; import org.apache.xtable.model.catalog.CatalogTableIdentifier; +import org.apache.xtable.model.catalog.policy.InternalAccessControlPolicySnapshot; import org.apache.xtable.model.schema.InternalPartitionField; import org.apache.xtable.model.schema.InternalSchema; import org.apache.xtable.model.storage.DataLayoutStrategy; +import org.apache.xtable.model.sync.policy.PolicySyncResult; import org.apache.xtable.spi.extractor.CatalogConversionSource; +import org.apache.xtable.spi.sync.CatalogAccessControlPolicySyncClient; import org.apache.xtable.spi.sync.CatalogSyncClient; public class ITTestUtils { @@ -161,4 +164,21 @@ public String getCatalogType() { @Override public void init(ExternalCatalogConfig catalogConfig, Configuration configuration) {} } + + public static class TestCatalogAccessControlPolicySyncClientImpl + implements CatalogAccessControlPolicySyncClient { + + public TestCatalogAccessControlPolicySyncClientImpl( + ExternalCatalogConfig catalogConfig, Configuration hadoopConf) {} + + @Override + public InternalAccessControlPolicySnapshot fetchPolicies() { + return InternalAccessControlPolicySnapshot.builder().build(); + } + + @Override + public PolicySyncResult pushPolicies(InternalAccessControlPolicySnapshot snapshot) { + return PolicySyncResult.builder().build(); + } + } }