This is an automated email from the ASF dual-hosted git repository. dineshkumar pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/ranger.git
The following commit(s) were added to refs/heads/master by this push: new f400998bd RANGER-4399 : Need to fix zone drop-down option in policy listing for user not having 'Security Zone' module permission f400998bd is described below commit f400998bdac38b5f9cfd5401345155017e9d05f9 Author: Dineshkumar Yadav <dineshkumar.ya...@outlook.com> AuthorDate: Tue Sep 26 18:52:59 2023 +0530 RANGER-4399 : Need to fix zone drop-down option in policy listing for user not having 'Security Zone' module permission Signed-off-by: Dineshkumar Yadav <dineshkumar.ya...@outlook.com> --- .../plugin/model/RangerSecurityZoneHeaderInfo.java | 7 + .../org/apache/ranger/biz/SecurityZoneDBStore.java | 7 + .../org/apache/ranger/db/XXSecurityZoneDao.java | 23 +++ .../java/org/apache/ranger/rest/PublicAPIsv2.java | 16 ++ .../org/apache/ranger/rest/SecurityZoneREST.java | 27 ++++ .../main/resources/META-INF/jpa_named_queries.xml | 12 ++ .../main/webapp/react-webapp/src/views/Home.jsx | 13 +- .../views/PolicyListing/PolicyListingTabView.jsx | 169 ++++++--------------- .../src/views/ServiceManager/ImportPolicy.jsx | 27 +++- .../views/ServiceManager/ServiceDefinitions.jsx | 14 +- .../react-webapp/src/views/SideBar/TopNavBar.jsx | 6 - 11 files changed, 175 insertions(+), 146 deletions(-) diff --git a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerSecurityZoneHeaderInfo.java b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerSecurityZoneHeaderInfo.java index 02927b07b..c42b0bedd 100644 --- a/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerSecurityZoneHeaderInfo.java +++ b/agents-common/src/main/java/org/apache/ranger/plugin/model/RangerSecurityZoneHeaderInfo.java @@ -46,4 +46,11 @@ public class RangerSecurityZoneHeaderInfo extends RangerBaseModelObject implemen public void setName(String name) { this.name = name; } + + public StringBuilder toString(StringBuilder sb) { + sb.append("id={").append(getId()).append("} "); + sb.append("name={").append(name).append("} "); + sb.append("isEnabled={").append(getIsEnabled()).append("} "); + return sb; + } } diff --git a/security-admin/src/main/java/org/apache/ranger/biz/SecurityZoneDBStore.java b/security-admin/src/main/java/org/apache/ranger/biz/SecurityZoneDBStore.java index a2c4e30ca..3cecfbc2f 100644 --- a/security-admin/src/main/java/org/apache/ranger/biz/SecurityZoneDBStore.java +++ b/security-admin/src/main/java/org/apache/ranger/biz/SecurityZoneDBStore.java @@ -245,4 +245,11 @@ public class SecurityZoneDBStore implements SecurityZoneStore { return services; } + + public List<RangerSecurityZoneHeaderInfo> getSecurityZoneHeaderInfoListByServiceId(Long serviceId, Boolean isTagService ) { + if(serviceId == null){ + throw restErrorUtil.createRESTException("Invalid value for serviceId", MessageEnums.INVALID_INPUT_DATA); + } + return daoMgr.getXXSecurityZoneDao().findAllZoneHeaderInfosByServiceId(serviceId,isTagService); + } } diff --git a/security-admin/src/main/java/org/apache/ranger/db/XXSecurityZoneDao.java b/security-admin/src/main/java/org/apache/ranger/db/XXSecurityZoneDao.java index 5f73b64ea..5fe0e856d 100644 --- a/security-admin/src/main/java/org/apache/ranger/db/XXSecurityZoneDao.java +++ b/security-admin/src/main/java/org/apache/ranger/db/XXSecurityZoneDao.java @@ -122,4 +122,27 @@ public class XXSecurityZoneDao extends BaseDao<XXSecurityZone> { return securityZoneList; } + + public List<RangerSecurityZoneHeaderInfo> findAllZoneHeaderInfosByServiceId(Long serviceId, Boolean isTagService) { + if(serviceId == null){ + return Collections.emptyList(); + } + List<Object[]> results = null; + if(isTagService){ + results = getEntityManager().createNamedQuery("XXSecurityZone.findAllZoneHeaderInfosByTagServiceId") + .setParameter("tagServiceId", serviceId) + .getResultList(); + }else{ + results = getEntityManager().createNamedQuery("XXSecurityZone.findAllZoneHeaderInfosByServiceId") + .setParameter("serviceId", serviceId) + .getResultList(); + } + + List<RangerSecurityZoneHeaderInfo> securityZoneList = new ArrayList<RangerSecurityZoneHeaderInfo>(results.size()); + for (Object[] result : results) { + securityZoneList.add(new RangerSecurityZoneHeaderInfo((Long) result[0], (String) result[1])); + } + + return securityZoneList; + } } diff --git a/security-admin/src/main/java/org/apache/ranger/rest/PublicAPIsv2.java b/security-admin/src/main/java/org/apache/ranger/rest/PublicAPIsv2.java index 92ade823b..eebab8108 100644 --- a/security-admin/src/main/java/org/apache/ranger/rest/PublicAPIsv2.java +++ b/security-admin/src/main/java/org/apache/ranger/rest/PublicAPIsv2.java @@ -182,6 +182,22 @@ public class PublicAPIsv2 { return ret; } + /** + * Get {@link List} of security zone header info. + * This API is authorized to every authenticated user. + * @param serviceId + * @param isTagService + * @return {@link List} of {@link RangerSecurityZoneHeaderInfo} if present. + */ + @GET + @Path("/api/zones/zone-headers/for-service/{serviceId}") + @Produces({ "application/json" }) + public List<RangerSecurityZoneHeaderInfo> getSecurityZoneHeaderInfoListByServiceId( @PathParam("serviceId") Long serviceId + , @DefaultValue("false") @QueryParam("isTagService") Boolean isTagService + ) { + return securityZoneRest.getSecurityZoneHeaderInfoListByServiceId(serviceId,isTagService); + } + /** * Get service header info {@link List} for given zone. * This API is authorized to every authenticated user. diff --git a/security-admin/src/main/java/org/apache/ranger/rest/SecurityZoneREST.java b/security-admin/src/main/java/org/apache/ranger/rest/SecurityZoneREST.java index 7c1e01053..5c1438c5b 100644 --- a/security-admin/src/main/java/org/apache/ranger/rest/SecurityZoneREST.java +++ b/security-admin/src/main/java/org/apache/ranger/rest/SecurityZoneREST.java @@ -43,6 +43,8 @@ import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Context; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.QueryParam; import org.apache.ranger.biz.RangerPolicyAdmin; import org.apache.ranger.biz.RangerBizUtil; @@ -58,6 +60,7 @@ import org.apache.ranger.db.RangerDaoManager; import org.apache.ranger.entity.XXService; import org.apache.ranger.entity.XXServiceDef; import org.apache.ranger.plugin.model.RangerSecurityZone; +import org.apache.ranger.plugin.model.RangerSecurityZoneHeaderInfo; import org.apache.ranger.plugin.model.RangerSecurityZoneV2; import org.apache.ranger.plugin.model.validation.RangerSecurityZoneValidator; import org.apache.ranger.plugin.model.validation.RangerValidator; @@ -393,6 +396,30 @@ public class SecurityZoneREST { return ret; } + @GET + @Path("/zones/zone-headers/for-service/{serviceId}") + @Produces({ "application/json" }) + public List<RangerSecurityZoneHeaderInfo> getSecurityZoneHeaderInfoListByServiceId( @PathParam("serviceId") Long serviceId + , @DefaultValue("false") @QueryParam ("isTagService") Boolean isTagService + ) { + if (LOG.isDebugEnabled()) { + LOG.debug("==> SecurityZoneREST.getSecurityZoneHeaderInfoListByServiceId() serviceId:{}, isTagService:{}",serviceId,isTagService); + } + List<RangerSecurityZoneHeaderInfo> ret; + try { + ret = securityZoneStore.getSecurityZoneHeaderInfoListByServiceId(serviceId, isTagService); + } catch (WebApplicationException excp) { + throw excp; + } catch (Throwable excp) { + LOG.error("SecurityZoneREST.getSecurityZoneHeaderInfoListByServiceId() failed", excp); + throw restErrorUtil.createRESTException(excp.getMessage()); + } + if (LOG.isDebugEnabled()) { + LOG.debug("<== SecurityZoneREST.getSecurityZoneHeaderInfoListByServiceId():" + ret); + } + return ret; + } + public RangerSecurityZoneV2 createSecurityZone(RangerSecurityZoneV2 securityZone) { LOG.debug("==> createSecurityZone({})", securityZone); diff --git a/security-admin/src/main/resources/META-INF/jpa_named_queries.xml b/security-admin/src/main/resources/META-INF/jpa_named_queries.xml index 23085a273..d3246c60c 100755 --- a/security-admin/src/main/resources/META-INF/jpa_named_queries.xml +++ b/security-admin/src/main/resources/META-INF/jpa_named_queries.xml @@ -1786,6 +1786,18 @@ </query> </named-query> + <named-query name="XXSecurityZone.findAllZoneHeaderInfosByServiceId"> + <query> + select obj.id, obj.name from XXSecurityZone obj where obj.id in (select ref.zoneId from XXSecurityZoneRefService ref where ref.serviceId = :serviceId) + </query> + </named-query> + + <named-query name="XXSecurityZone.findAllZoneHeaderInfosByTagServiceId"> + <query> + select obj.id, obj.name from XXSecurityZone obj where obj.id in (select ref.zoneId from XXSecurityZoneRefTagService ref where ref.tagServiceId = :tagServiceId) + </query> + </named-query> + <named-query name="XXGlobalState.findByStateId"> <query> select obj from XXGlobalState obj where obj.id = :stateId diff --git a/security-admin/src/main/webapp/react-webapp/src/views/Home.jsx b/security-admin/src/main/webapp/react-webapp/src/views/Home.jsx index ffbc990fa..3dee1d086 100644 --- a/security-admin/src/main/webapp/react-webapp/src/views/Home.jsx +++ b/security-admin/src/main/webapp/react-webapp/src/views/Home.jsx @@ -23,7 +23,6 @@ import { Tab, Tabs } from "react-bootstrap"; import withRouter from "Hooks/withRouter"; import { hasAccessToTab } from "../utils/XAUtils"; import CustomBreadcrumb from "./CustomBreadcrumb"; -import { isEmpty } from "lodash"; class Home extends Component { constructor(props) { @@ -34,9 +33,11 @@ class Home extends Component { loader: false }; } + tabChange = (tabName) => { this.props.navigate(`/policymanager/${tabName}`, { replace: true }); }; + componentDidUpdate(nextProps, prevState) { let activeTabVal = this.activeTab(); @@ -44,6 +45,7 @@ class Home extends Component { this.setState({ activeKey: this.activeTab() }); } } + activeTab = () => { let activeTabVal; if (this.props.location.pathname) { @@ -91,6 +93,7 @@ class Home extends Component { .getElementById("tagSelectedZone") ?.classList?.remove("disabledEvents"); }; + render() { return ( <> @@ -114,10 +117,6 @@ class Home extends Component { <ServiceDefinitions isTagView={this.state.isTagView} disableTabs={this.disableTabs} - key={ - !isEmpty(localStorage.getItem("zoneDetails")) && - JSON.parse(localStorage.getItem("zoneDetails"))?.value - } ></ServiceDefinitions> )} </Tab> @@ -132,10 +131,6 @@ class Home extends Component { <ServiceDefinitions isTagView={this.state.isTagView} disableTabs={this.disableTabs} - key={ - !isEmpty(localStorage.getItem("zoneDetails")) && - JSON.parse(localStorage.getItem("zoneDetails"))?.value - } ></ServiceDefinitions> )} </Tab> diff --git a/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/PolicyListingTabView.jsx b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/PolicyListingTabView.jsx index 633290f75..44d9f1da9 100644 --- a/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/PolicyListingTabView.jsx +++ b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/PolicyListingTabView.jsx @@ -31,7 +31,7 @@ import { } from "Utils/XAUtils"; import { Loader } from "Components/CommonComponents"; import TopNavBar from "../SideBar/TopNavBar"; -import { compact, has, map, sortBy, includes, filter } from "lodash"; +import { map, sortBy } from "lodash"; import { RangerPolicyType } from "../../utils/XAEnums"; import { getServiceDef } from "../../utils/appState"; @@ -66,7 +66,6 @@ export const PolicyListingTabView = () => { allServicesData: [] }); const { loader, serviceDefData, serviceData, allServicesData } = policyState; - //const [zoneServicesData, setZoneServicesData] = useState([]); const [zones, setZones] = useState([]); let localStorageZoneDetails = localStorage.getItem("zoneDetails"); @@ -105,87 +104,58 @@ export const PolicyListingTabView = () => { return serviceDef.name == getServiceData?.data?.type; }); - isTagView = - getServiceDefData?.name !== undefined && - getServiceDefData?.name === "tag" - ? true - : false; - - updateTagActive(isTagView); - if (!isKMSRole) { getZones = await fetchApi({ - url: `zones/zones` + url: `public/v2/api/zones/zone-headers/for-service/${params.serviceId}`, + params: { + isTagService: getServiceData.data?.type == "tag" ? true : false + } }); } - - setZones(getZones?.data?.securityZones || []); - - dispatch({ - type: "SERVICES_DATA", - allServicesData: getAllServicesData?.data?.services, - serviceData: getServiceData?.data, - serviceDefData: getServiceDefData - }); - - /* zoneServices( - getServiceData.data, - getAllServicesData.data.services, - getZones?.data?.securityZones || [] - ); */ - - dispatch({ - type: "SET_LOADER", - loader: false - }); - - document - .getElementById("resourceSelectedZone") - ?.classList?.remove("disabledEvents"); - document - .getElementById("tagSelectedZone") - ?.classList?.remove("disabledEvents"); } catch (error) { console.error(`Error occurred while fetching service details ! ${error}`); } - }; - /* const zoneServices = (serviceData, servicesData, zonesData) => { - let filterZoneService = []; - if ( - localStorageZoneDetails !== undefined && - localStorageZoneDetails !== null - ) { - let filterZones = find(zonesData, { - name: JSON.parse(localStorageZoneDetails)?.label - }); + isTagView = + getServiceDefData?.name !== undefined && getServiceDefData?.name === "tag" + ? true + : false; - if (serviceData.type !== "tag") { - filterZoneService = - filterZones !== undefined ? Object.keys(filterZones.services) : []; - } else { - filterZoneService = - filterZones !== undefined ? filterZones?.tagServices : []; - } + updateTagActive(isTagView); - let zoneServices = filterZoneService?.map((zoneService) => { - return servicesData?.filter((service) => { - return service.name === zoneService; - }); - }); + setZones(getZones?.data || []); - setZoneServicesData(zoneServices?.flat()); - } - }; */ + dispatch({ + type: "SERVICES_DATA", + allServicesData: getAllServicesData?.data?.services, + serviceData: getServiceData?.data, + serviceDefData: getServiceDefData + }); + + dispatch({ + type: "SET_LOADER", + loader: false + }); + + document + .getElementById("resourceSelectedZone") + ?.classList?.remove("disabledEvents"); + document + .getElementById("tagSelectedZone") + ?.classList?.remove("disabledEvents"); + }; const getServices = (services) => { - return sortBy( - services?.map(({ displayName }) => ({ - label: displayName, - value: displayName - })), + let filterService = []; + + filterService = sortBy( + map(services, function ({ displayName }) { + return { label: displayName, value: displayName }; + }), "label" ); + + return filterService; }; const handleServiceChange = async (e) => { @@ -208,35 +178,14 @@ export const PolicyListingTabView = () => { const getZones = (zones) => { let filterZones = []; - if (serviceData.type !== "tag") { - filterZones = compact( - zones?.map((zone) => { - if (has(zone?.services, serviceData?.name)) { - return { label: zone.name, value: zone.id }; - } - }) - ); - } else { - filterZones = zones - ?.map((zone) => { - return compact( - zone?.tagServices?.map((tagService) => { - if (tagService === serviceData?.name) { - return { label: zone.name, value: zone.id }; - } - }) - ); - }) - ?.flat(); - } - - return sortBy( - filterZones?.map((zone) => ({ - label: zone.label, - value: zone.value - })), + filterZones = sortBy( + map(zones, function (zone) { + return { label: zone.name, value: zone.id }; + }), "label" ); + + return filterZones; }; const handleZoneChange = async (e) => { @@ -263,32 +212,13 @@ export const PolicyListingTabView = () => { localStorageZoneDetails !== undefined && localStorageZoneDetails !== null ) { - if (serviceData.type !== "tag") { - zoneName = compact( - map(zones, function (zone) { - if ( - zone.name === JSON.parse(localStorageZoneDetails)?.label && - has(zone?.services, serviceData?.name) - ) { - return { label: zone.name, value: zone.id }; - } - }) - ); - - zoneName = zoneName.length == 1 ? zoneName[0] : null; - } else { - zoneName = filter(zones, { - name: JSON.parse(localStorageZoneDetails)?.label - }); - - zoneName = - zoneName.length == 1 && - includes(zoneName[0]?.tagServices, serviceData?.name) - ? { label: zoneName[0].name, value: zoneName[0].id } - : null; + for (const zone of zones) { + if (zone.name === JSON.parse(localStorageZoneDetails)?.label) { + zoneName = { label: zone.name, value: zone.id }; + break; + } } } - return zoneName; }; @@ -311,7 +241,6 @@ export const PolicyListingTabView = () => { handleZoneChange={handleZoneChange} getZones={getZones} allZonesData={zones} - //zoneServicesData={zoneServicesData} /> {loader ? ( <Loader /> diff --git a/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ImportPolicy.jsx b/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ImportPolicy.jsx index 44346bb4b..21b9f6ee1 100644 --- a/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ImportPolicy.jsx +++ b/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ImportPolicy.jsx @@ -65,7 +65,7 @@ class ImportPolicy extends Component { }); }; - handleFileUpload = (e) => { + handleFileUpload = (e, values) => { e.preventDefault(); const fileReader = new FileReader(); fileReader.readAsText(e.target.files[0]); @@ -132,6 +132,7 @@ class ImportPolicy extends Component { const formFields = {}; formFields["serviceFields"] = serviceFieldsFromJson; formFields["sourceZoneName"] = zoneNameJsonParseFile; + formFields["isOverride"] = values.isOverride; this.setState({ fileJsonData: jsonParseFileData, @@ -204,7 +205,8 @@ class ImportPolicy extends Component { } }; - handleSelectedZone = async (e) => { + handleSelectedZone = async (e, values) => { + const formFields = {}; let zonesResp = []; try { @@ -238,10 +240,10 @@ class ImportPolicy extends Component { }; }); - const formFields = {}; formFields["serviceFields"] = serviceFieldsFromJson; formFields["sourceZoneName"] = this.state.initialFormFields["sourceZoneName"]; + formFields["isOverride"] = values.isOverride; this.setState({ destZoneName: e && e.label, @@ -249,18 +251,24 @@ class ImportPolicy extends Component { filterFormFields: formFields }); } else { + formFields["serviceFields"] = + this.state.initialFormFields["serviceFields"]; + formFields["sourceZoneName"] = + this.state.initialFormFields["sourceZoneName"]; + formFields["isOverride"] = values.isOverride; + this.setState({ destZoneName: "", destServices: this.props.isParentImport ? this.props.allServices : this.props.services, - filterFormFields: this.state.initialFormFields + filterFormFields: formFields }); } } catch (error) { serverError(error); console.error( - `Error occurred while fetching Service Definitions or CSRF headers! ${error}` + `Error occurred while fetching Services from selected Zone! ${error}` ); } }; @@ -323,6 +331,7 @@ class ImportPolicy extends Component { initialValues={this.state.filterFormFields} render={({ handleSubmit, + values, form: { mutators: { push: addItem, pop: removeItem } } @@ -359,7 +368,9 @@ class ImportPolicy extends Component { type="file" className="form-control-file" accept=" .json " - onChange={this.handleFileUpload} + onChange={(e) => + this.handleFileUpload(e, values) + } /> </label> </div> @@ -452,7 +463,9 @@ class ImportPolicy extends Component { <Col sm={1}>To</Col> <Col sm={4}> <Select - onChange={this.handleSelectedZone} + onChange={(e) => + this.handleSelectedZone(e, values) + } isClearable components={{ IndicatorSeparator: () => null diff --git a/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ServiceDefinitions.jsx b/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ServiceDefinitions.jsx index aeb88161b..715038f67 100644 --- a/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ServiceDefinitions.jsx +++ b/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ServiceDefinitions.jsx @@ -121,8 +121,7 @@ class ServiceDefinitions extends Component { loader: false }); this.props.disableTabs(false); - this.state.selectedZone != "" && - this.getSelectedZone(this.state.selectedZone); + this.getSelectedZone(this.state.selectedZone); }; fetchServices = async () => { @@ -250,8 +249,10 @@ class ServiceDefinitions extends Component { deleteService = async (sid) => { let localStorageZoneDetails = localStorage.getItem("zoneDetails"); let zonesResp = []; + try { this.setState({ blockUI: true }); + await fetchApi({ url: `plugins/services/${sid}`, method: "delete" @@ -268,17 +269,20 @@ class ServiceDefinitions extends Component { }); if (isEmpty(zonesResp?.data)) { - localStorage.removeItem("zoneDetails"); this.setState({ - selectedZone: "" + zones: this.state.zones.filter( + (z) => z.id !== JSON.parse(localStorageZoneDetails)?.value + ) }); } } + this.setState({ services: this.state.services.filter((s) => s.id !== sid), filterServices: this.state.filterServices.filter((s) => s.id !== sid), blockUI: false }); + toast.success("Successfully deleted the service"); this.props.navigate(this.props.location.pathname); } catch (error) { @@ -299,11 +303,13 @@ class ServiceDefinitions extends Component { } }; }; + formatOptionLabel = ({ label }) => ( <div title={label} className="text-truncate"> {label} </div> ); + render() { const { filterServiceDefs, diff --git a/security-admin/src/main/webapp/react-webapp/src/views/SideBar/TopNavBar.jsx b/security-admin/src/main/webapp/react-webapp/src/views/SideBar/TopNavBar.jsx index 4f3dedde1..d4dbc57d1 100644 --- a/security-admin/src/main/webapp/react-webapp/src/views/SideBar/TopNavBar.jsx +++ b/security-admin/src/main/webapp/react-webapp/src/views/SideBar/TopNavBar.jsx @@ -73,11 +73,8 @@ export const TopNavBar = (props) => { handleZoneChange, getZones, allZonesData - //zoneServicesData } = props; - //let localStorageZoneDetails = localStorage.getItem("zoneDetails"); - const serviceSelectCustomStyles = { option: (provided, state) => ({ ...provided, @@ -216,9 +213,6 @@ export const TopNavBar = (props) => { styles={serviceSelectCustomStyles} className={`${policyLoader ? "not-allowed" : ""}`} isDisabled={policyLoader ? true : false} - /* options={getServices( - localStorageZoneDetails != null ? zoneServicesData : allServicesData - )} */ options={getServices(allServicesData)} formatOptionLabel={formatOptionLabel} onChange={(e) => handleServiceChange(e)}