diff --git a/security-admin/db/mysql/optimized/current/ranger_core_db_mysql.sql b/security-admin/db/mysql/optimized/current/ranger_core_db_mysql.sql index 21bfe0a6c3b..d06d7879775 100644 --- a/security-admin/db/mysql/optimized/current/ranger_core_db_mysql.sql +++ b/security-admin/db/mysql/optimized/current/ranger_core_db_mysql.sql @@ -1903,4 +1903,5 @@ INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('J10061',UTC_TIMESTAMP(),'Ranger 2.5.0',UTC_TIMESTAMP(),'localhost','Y'); INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('J10062',UTC_TIMESTAMP(),'Ranger 2.5.0',UTC_TIMESTAMP(),'localhost','Y'); INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('J10063',UTC_TIMESTAMP(),'Ranger 2.5.0',UTC_TIMESTAMP(),'localhost','Y'); +INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('J10064',UTC_TIMESTAMP(),'Ranger 2.6.0',UTC_TIMESTAMP(),'localhost','Y'); INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('JAVA_PATCHES',UTC_TIMESTAMP(),'Ranger 1.0.0',UTC_TIMESTAMP(),'localhost','Y'); diff --git a/security-admin/db/oracle/optimized/current/ranger_core_db_oracle.sql b/security-admin/db/oracle/optimized/current/ranger_core_db_oracle.sql index 7c655b17ed4..4ec797d5548 100644 --- a/security-admin/db/oracle/optimized/current/ranger_core_db_oracle.sql +++ b/security-admin/db/oracle/optimized/current/ranger_core_db_oracle.sql @@ -2097,5 +2097,6 @@ INSERT INTO x_db_version_h (id,version,inst_at,inst_by,updated_at,updated_by,act INSERT INTO x_db_version_h (id,version,inst_at,inst_by,updated_at,updated_by,active) VALUES (X_DB_VERSION_H_SEQ.nextval,'J10061',sys_extract_utc(systimestamp),'Ranger 2.5.0',sys_extract_utc(systimestamp),'localhost','Y'); INSERT INTO x_db_version_h (id,version,inst_at,inst_by,updated_at,updated_by,active) VALUES (X_DB_VERSION_H_SEQ.nextval,'J10062',sys_extract_utc(systimestamp),'Ranger 2.5.0',sys_extract_utc(systimestamp),'localhost','Y'); INSERT INTO x_db_version_h (id,version,inst_at,inst_by,updated_at,updated_by,active) VALUES (X_DB_VERSION_H_SEQ.nextval,'J10063',sys_extract_utc(systimestamp),'Ranger 2.5.0',sys_extract_utc(systimestamp),'localhost','Y'); +INSERT INTO x_db_version_h (id,version,inst_at,inst_by,updated_at,updated_by,active) VALUES (X_DB_VERSION_H_SEQ.nextval,'J10064',sys_extract_utc(systimestamp),'Ranger 2.6.0',sys_extract_utc(systimestamp),'localhost','Y'); INSERT INTO x_db_version_h (id,version,inst_at,inst_by,updated_at,updated_by,active) VALUES (X_DB_VERSION_H_SEQ.nextval,'JAVA_PATCHES',sys_extract_utc(systimestamp),'Ranger 1.0.0',sys_extract_utc(systimestamp),'localhost','Y'); commit; diff --git a/security-admin/db/postgres/optimized/current/ranger_core_db_postgres.sql b/security-admin/db/postgres/optimized/current/ranger_core_db_postgres.sql index 262f6b13668..ce1ebe53992 100644 --- a/security-admin/db/postgres/optimized/current/ranger_core_db_postgres.sql +++ b/security-admin/db/postgres/optimized/current/ranger_core_db_postgres.sql @@ -2046,4 +2046,5 @@ INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('J10061',current_timestamp,'Ranger 2.5.0',current_timestamp,'localhost','Y'); INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('J10062',current_timestamp,'Ranger 2.5.0',current_timestamp,'localhost','Y'); INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('J10063',current_timestamp,'Ranger 2.5.0',current_timestamp,'localhost','Y'); +INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('J10064',current_timestamp,'Ranger 2.6.0',current_timestamp,'localhost','Y'); INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('JAVA_PATCHES',current_timestamp,'Ranger 1.0.0',current_timestamp,'localhost','Y'); diff --git a/security-admin/db/sqlanywhere/optimized/current/ranger_core_db_sqlanywhere.sql b/security-admin/db/sqlanywhere/optimized/current/ranger_core_db_sqlanywhere.sql index 4ad99b037c1..f06a230eae6 100644 --- a/security-admin/db/sqlanywhere/optimized/current/ranger_core_db_sqlanywhere.sql +++ b/security-admin/db/sqlanywhere/optimized/current/ranger_core_db_sqlanywhere.sql @@ -2472,6 +2472,8 @@ INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active GO INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('J10063',CURRENT_TIMESTAMP,'Ranger 2.5.0',CURRENT_TIMESTAMP,'localhost','Y'); GO +INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('J10064',CURRENT_TIMESTAMP,'Ranger 2.6.0',CURRENT_TIMESTAMP,'localhost','Y'); +GO INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('JAVA_PATCHES',CURRENT_TIMESTAMP,'Ranger 1.0.0',CURRENT_TIMESTAMP,'localhost','Y'); GO exit diff --git a/security-admin/db/sqlserver/optimized/current/ranger_core_db_sqlserver.sql b/security-admin/db/sqlserver/optimized/current/ranger_core_db_sqlserver.sql index 38902610ef8..9a2f0d655c1 100644 --- a/security-admin/db/sqlserver/optimized/current/ranger_core_db_sqlserver.sql +++ b/security-admin/db/sqlserver/optimized/current/ranger_core_db_sqlserver.sql @@ -4265,5 +4265,6 @@ INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('J10061',CURRENT_TIMESTAMP,'Ranger 2.5.0',CURRENT_TIMESTAMP,'localhost','Y'); INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('J10062',CURRENT_TIMESTAMP,'Ranger 2.5.0',CURRENT_TIMESTAMP,'localhost','Y'); INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('J10063',CURRENT_TIMESTAMP,'Ranger 2.5.0',CURRENT_TIMESTAMP,'localhost','Y'); +INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('J10064',CURRENT_TIMESTAMP,'Ranger 2.6.0',CURRENT_TIMESTAMP,'localhost','Y'); INSERT INTO x_db_version_h (version,inst_at,inst_by,updated_at,updated_by,active) VALUES ('JAVA_PATCHES',CURRENT_TIMESTAMP,'Ranger 1.0.0',CURRENT_TIMESTAMP,'localhost','Y'); GO diff --git a/security-admin/pom.xml b/security-admin/pom.xml index bab23ae6dea..009f50712ec 100644 --- a/security-admin/pom.xml +++ b/security-admin/pom.xml @@ -31,6 +31,17 @@ 1.8 false + + + + org.apache.logging.log4j + log4j-bom + ${log4j2.version} + pom + import + + + aopalliance diff --git a/security-admin/src/main/java/org/apache/ranger/patch/PatchForTrinoSvcDefUpdate_J10064.java b/security-admin/src/main/java/org/apache/ranger/patch/PatchForTrinoSvcDefUpdate_J10064.java new file mode 100644 index 00000000000..6285887dc50 --- /dev/null +++ b/security-admin/src/main/java/org/apache/ranger/patch/PatchForTrinoSvcDefUpdate_J10064.java @@ -0,0 +1,202 @@ +/* + * 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.ranger.patch; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.log4j.Logger; +import org.apache.ranger.biz.ServiceDBStore; +import org.apache.ranger.common.RangerValidatorFactory; +import org.apache.ranger.plugin.model.RangerServiceDef; +import org.apache.ranger.plugin.model.validation.RangerServiceDefValidator; +import org.apache.ranger.plugin.model.validation.RangerValidator.Action; +import org.apache.ranger.plugin.store.EmbeddedServiceDefsUtil; +import org.apache.ranger.util.CLIUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Component; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.TransactionDefinition; +import org.springframework.transaction.TransactionStatus; +import org.springframework.transaction.support.TransactionCallback; +import org.springframework.transaction.support.TransactionTemplate; + +import java.util.Set; + +/** + * Adds the "execute" and "grant" access types to the Trino "schemafunction" resource + * by augmenting only its accessTypeRestrictions in the DB-stored service-def, leaving the + * rest of the service-def and any existing policies untouched. Skips when there is nothing to do. + */ +@Component +public class PatchForTrinoSvcDefUpdate_J10064 extends BaseLoader { + public static final String RESOURCE_SCHEMAFUNCTION = "schemafunction"; + public static final String ACCESS_TYPE_GRANT = "grant"; + public static final String ACCESS_TYPE_EXECUTE = "execute"; + private static final Logger logger = Logger.getLogger(PatchForTrinoSvcDefUpdate_J10064.class); + private static final String TRINO_SVC_DEF_NAME = EmbeddedServiceDefsUtil.EMBEDDED_SERVICEDEF_TRINO_NAME; + @Autowired + ServiceDBStore svcDBStore; + @Autowired + @Qualifier(value = "transactionManager") + PlatformTransactionManager txManager; + @Autowired + private RangerValidatorFactory validatorFactory; + + public static void main(String[] args) { + logger.info("main()"); + try { + PatchForTrinoSvcDefUpdate_J10064 loader = (PatchForTrinoSvcDefUpdate_J10064) CLIUtil.getBean(PatchForTrinoSvcDefUpdate_J10064.class); + loader.init(); + while (loader.isMoreToProcess()) { + loader.load(); + } + logger.info("Load complete. Exiting!!!"); + System.exit(0); + } catch (Exception e) { + logger.error("Error loading", e); + System.exit(1); + } + } + + @Override + public void init() throws Exception { + // DO NOTHING + } + + @Override + public void printStats() { + logger.info("PatchForTrinoSvcDefUpdate_J10064 logs "); + } + + @Override + public void execLoad() { + logger.info("==> PatchForTrinoSvcDefUpdate_J10064.execLoad()"); + try { + TransactionTemplate txTemplate = new TransactionTemplate(txManager); + txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); + try { + txTemplate.execute(new TransactionCallback() { + @Override + public Object doInTransaction(TransactionStatus status) { + loadTrinoServiceDef(); + return null; + } + }); + } catch (Throwable ex) { + logger.error("Error while updating " + TRINO_SVC_DEF_NAME + " service-def"); + throw new RuntimeException(ex.getMessage()); + } + } catch (Exception e) { + logger.error("Error while executing PatchForTrinoSvcDefUpdate_J10064, Error - ", e); + throw new RuntimeException(e.getMessage()); + } + logger.info("<== PatchForTrinoSvcDefUpdate_J10064.execLoad()"); + } + + private void loadTrinoServiceDef() { + RangerServiceDef dbRangerServiceDef = null; + try { + dbRangerServiceDef = svcDBStore.getServiceDefByName(TRINO_SVC_DEF_NAME); + } catch (Exception e) { + logger.error("Error while reading the " + TRINO_SVC_DEF_NAME + " service-def from ranger db.", e); + } + if (dbRangerServiceDef == null) { + // Not every cluster has Trino enabled (e.g. via ranger.supportedcomponents), + // so the service-def may legitimately be absent. Skip instead of failing the upgrade. + logger.warn("The " + TRINO_SVC_DEF_NAME + " service-def does not exist in ranger db; nothing to update. Skipping patch."); + return; + } + updateTrinoSvcDef(dbRangerServiceDef); + } + + private void updateTrinoSvcDef(RangerServiceDef dbRangerServiceDef) { + logger.info("==> PatchForTrinoSvcDefUpdate_J10064.updateTrinoSvcDef()"); + try { + RangerServiceDef.RangerResourceDef schemaFunctionResource = findSchemaFunctionResource(dbRangerServiceDef); + if (!validate(schemaFunctionResource)) { + // validate() already logged why there is nothing to do; skip without failing the upgrade. + logger.info("<== PatchForTrinoSvcDefUpdate_J10064.updateTrinoSvcDef()"); + return; + } + + Set accessTypeRestrictions = schemaFunctionResource.getAccessTypeRestrictions(); + accessTypeRestrictions.add(ACCESS_TYPE_EXECUTE); + accessTypeRestrictions.add(ACCESS_TYPE_GRANT); + schemaFunctionResource.setAccessTypeRestrictions(accessTypeRestrictions); + + RangerServiceDefValidator validator = validatorFactory.getServiceDefValidator(this.svcDBStore); + validator.validate(dbRangerServiceDef, Action.UPDATE); + RangerServiceDef updatedSvcDef = this.svcDBStore.updateServiceDef(dbRangerServiceDef); + if (updatedSvcDef == null) { + logger.error("Error while updating " + TRINO_SVC_DEF_NAME + " service-def"); + throw new RuntimeException("Error while updating " + TRINO_SVC_DEF_NAME + " service-def"); + } + logger.info(TRINO_SVC_DEF_NAME + " service-def has been updated: '" + RESOURCE_SCHEMAFUNCTION + "' now allows '" + ACCESS_TYPE_EXECUTE + "' and '" + ACCESS_TYPE_GRANT + "'"); + } catch (Exception e) { + logger.error("Error while updating " + TRINO_SVC_DEF_NAME + " service-def", e); + throw new RuntimeException(e); + } + logger.info("<== PatchForTrinoSvcDefUpdate_J10064.updateTrinoSvcDef()"); + } + + /** + * Decides whether the 'schemafunction' resource needs (and can take) the 'execute'/'grant' update. + * Logs the reason and returns {@code false} when there is nothing to do, so the patch skips + * gracefully instead of failing the upgrade. + */ + private boolean validate(RangerServiceDef.RangerResourceDef schemaFunctionResource) { + if (!isResourcePresent(schemaFunctionResource)) { + logger.warn("The '" + RESOURCE_SCHEMAFUNCTION + "' resource does not exist in the " + TRINO_SVC_DEF_NAME + " service-def; nothing to update. Skipping patch."); + return false; + } + if (!hasAccessTypeRestrictions(schemaFunctionResource)) { + // An empty/absent restriction set means every access type (including 'execute' and 'grant') + // is already allowed on this resource. Adding entries here would instead RESTRICT it, so skip. + logger.info("The '" + RESOURCE_SCHEMAFUNCTION + "' resource has no access-type restrictions; all access types are already allowed; nothing to update"); + return false; + } + if (allowsExecuteAndGrant(schemaFunctionResource)) { + logger.info("The '" + RESOURCE_SCHEMAFUNCTION + "' resource already allows '" + ACCESS_TYPE_EXECUTE + "' and '" + ACCESS_TYPE_GRANT + "'; nothing to update"); + return false; + } + return true; + } + + private RangerServiceDef.RangerResourceDef findSchemaFunctionResource(RangerServiceDef serviceDef) { + for (RangerServiceDef.RangerResourceDef resourceDef : serviceDef.getResources()) { + if (RESOURCE_SCHEMAFUNCTION.equals(resourceDef.getName())) { + return resourceDef; + } + } + return null; + } + + private boolean isResourcePresent(RangerServiceDef.RangerResourceDef resourceDef) { + return resourceDef != null; + } + + private boolean hasAccessTypeRestrictions(RangerServiceDef.RangerResourceDef resourceDef) { + return CollectionUtils.isNotEmpty(resourceDef.getAccessTypeRestrictions()); + } + + private boolean allowsExecuteAndGrant(RangerServiceDef.RangerResourceDef resourceDef) { + Set accessTypeRestrictions = resourceDef.getAccessTypeRestrictions(); + return accessTypeRestrictions.contains(ACCESS_TYPE_EXECUTE) && accessTypeRestrictions.contains(ACCESS_TYPE_GRANT); + } +}