modules/core/domain/src/main/java/org/rhq/core/domain/bundle/Bundle.java | 25 modules/core/domain/src/main/java/org/rhq/core/domain/criteria/BundleCriteria.java | 11 modules/core/domain/src/main/java/org/rhq/core/domain/criteria/BundleResourceDeploymentCriteria.java | 9 modules/core/domain/src/main/java/org/rhq/core/domain/criteria/BundleVersionCriteria.java | 10 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deployment/BundleDeploymentDataSource.java | 3 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundleView.java | 4 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/version/BundleVersionView.java | 4 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/BundleGWTService.java | 9 modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/BundleGWTServiceImpl.java | 44 modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java | 14 modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest.java | 2 modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/tagging/TagManagerBeanTest.java | 2 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java | 445 ++++++---- modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerLocal.java | 149 ++- modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerRemote.java | 159 ++- modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleServerServiceImpl.java | 2 modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java | 50 - 17 files changed, 583 insertions(+), 359 deletions(-)
New commits: commit c0adb33418b870b168d72d682225744664bea1b7 Author: Jay Shaughnessy jshaughn@redhat.com Date: Wed Jul 31 14:19:18 2013 -0400
Fine-grained bundle perms : checkpoint check-in - finished initial work-through of remote/local API methods and the associated coding to support the updated permission scheme - Global.MANAGE_BUNDLE is no longer used as an explicit permission but now only as a convenience for setting all of the new permissions. - merged the "FindXxxByCriteriaWithDestinationFilter" local methods into their respective "FindXxxByCriteria" methods. The base methods should be handling this filtering, otherwise they basically have a security hole.
diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/bundle/Bundle.java b/modules/core/domain/src/main/java/org/rhq/core/domain/bundle/Bundle.java index 3a8569f..5af51af 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/bundle/Bundle.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/bundle/Bundle.java @@ -57,7 +57,7 @@ import org.rhq.core.domain.tagging.Tag; * @author John Mazzitelli */ @Entity -@NamedQueries( { +@NamedQueries({ // Below queries primarily used for domain test code. @NamedQuery(name = Bundle.QUERY_FIND_ALL, query = "SELECT b FROM Bundle b"), // @NamedQuery(name = Bundle.QUERY_FIND_BY_NAME, query = "SELECT b FROM Bundle b WHERE :name = b.name"), @@ -182,6 +182,29 @@ public class Bundle implements Serializable { this.bundleVersions = bundleVersions; }
+ public Set<BundleGroup> getBundleGroups() { + return bundleGroups; + } + + public void setBundleGroups(Set<BundleGroup> bundleGroups) { + this.bundleGroups = bundleGroups; + } + + public void addBundleGroup(BundleGroup bundleGroup) { + if (this.bundleGroups == null) { + this.bundleGroups = new HashSet<BundleGroup>(); + } + this.bundleGroups.add(bundleGroup); + } + + public boolean removeBundleGroup(BundleGroup bundleGroup) { + if (this.bundleGroups != null) { + return this.bundleGroups.remove(bundleGroup); + } else { + return false; + } + } + public List<BundleDestination> getDestinations() { return destinations; } diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/BundleCriteria.java b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/BundleCriteria.java index 5e6f8c1..32f2f9d 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/BundleCriteria.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/BundleCriteria.java @@ -145,6 +145,12 @@ public class BundleCriteria extends TaggedCriteria { this.fetchBundleVersions = fetchBundleVersions; }
+ /** + * Unless called by an InventoryManager the destinations will be filtered to those the caller can view, based + * on the resource groups associated with his roles and the group associated wuth the destination. + * + * @param fetchDestinations + */ public void fetchDestinations(boolean fetchDestinations) { this.fetchDestinations = fetchDestinations; } @@ -166,4 +172,9 @@ public class BundleCriteria extends TaggedCriteria { addSortField("description"); this.sortDescription = sortDescription; } + + public boolean isInventoryManagerRequired() { + return fetchDestinations; + } + } diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/BundleResourceDeploymentCriteria.java b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/BundleResourceDeploymentCriteria.java index 7ec26d7..4924d6f 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/BundleResourceDeploymentCriteria.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/BundleResourceDeploymentCriteria.java @@ -18,15 +18,12 @@ */ package org.rhq.core.domain.criteria;
-import java.util.List; - import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlRootElement;
import org.rhq.core.domain.bundle.BundleDeploymentStatus; import org.rhq.core.domain.bundle.BundleResourceDeployment; -import org.rhq.core.domain.util.CriteriaUtils;
/** * @author Jay Shaughnessy @@ -85,11 +82,7 @@ public class BundleResourceDeploymentCriteria extends Criteria {
/** * By setting this fetch to true, it will cause {@link #isInventoryManagerRequired()} to return true as well. - * - * In practice, however, MANAGE_INVENTORY is too restrictive; a bundle manager who has MANAGE_BUNDLE but not - * MANAGE_INVENTORY would not be able to see any resource deployments. So, until it is possible to handle granular - * authorization checks on optionally fetched criteria data, a bundle manager will be allowed to see resource - * deployments to any platform. + * Without Inventory Manager permission results will be limited to only the resources viewable to the caller. * * @see org.rhq.enterprise.server.bundle.BundleManagerBean#findBundleResourceDeploymentsByCriteria(org.rhq.core.domain.auth.Subject, BundleResourceDeploymentCriteria) */ diff --git a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/BundleVersionCriteria.java b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/BundleVersionCriteria.java index 0bc999f..b5dd0e4 100644 --- a/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/BundleVersionCriteria.java +++ b/modules/core/domain/src/main/java/org/rhq/core/domain/criteria/BundleVersionCriteria.java @@ -79,6 +79,12 @@ public class BundleVersionCriteria extends TaggedCriteria { this.fetchBundle = fetchBundle; }
+ /** + * Unless called by an InventoryManager the deployments will be filtered to those the caller can view, based + * on the resource groups associated with his roles and the destination associated with the deployments. + * + * @param fetchDestinations + */ public void fetchBundleDeployments(boolean fetchBundleDeployments) { this.fetchBundleDeployments = fetchBundleDeployments; } @@ -91,4 +97,8 @@ public class BundleVersionCriteria extends TaggedCriteria { this.fetchConfigurationDefinition = fetchConfigurationDefinition; }
+ public boolean isInventoryManagerRequired() { + return fetchBundleDeployments; + } + } diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deployment/BundleDeploymentDataSource.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deployment/BundleDeploymentDataSource.java index 3f71fb1..576f8a8 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deployment/BundleDeploymentDataSource.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/deployment/BundleDeploymentDataSource.java @@ -99,7 +99,7 @@ public class BundleDeploymentDataSource extends RPCDataSource<BundleDeployment, @Override protected void executeFetch(final DSRequest request, final DSResponse response, final BundleDeploymentCriteria criteria) { - bundleService.findBundleDeploymentsByCriteriaWithDestinationFilter(criteria, new AsyncCallback<PageList<BundleDeployment>>() { + bundleService.findBundleDeploymentsByCriteria(criteria, new AsyncCallback<PageList<BundleDeployment>>() { public void onFailure(Throwable caught) { CoreGUI.getErrorHandler().handleError(MSG.view_bundle_deploy_loadDeployFailure(), caught); } @@ -109,7 +109,6 @@ public class BundleDeploymentDataSource extends RPCDataSource<BundleDeployment, processResponse(request.getRequestId(), response); } }); - }
@Override diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundleView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundleView.java index bd54a07..a3bc0d8 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundleView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/list/BundleView.java @@ -62,9 +62,9 @@ import org.rhq.enterprise.gui.coregui.client.components.tagging.TagsChangedCallb import org.rhq.enterprise.gui.coregui.client.gwt.BundleGWTServiceAsync; import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup; import org.rhq.enterprise.gui.coregui.client.util.StringUtility; -import org.rhq.enterprise.gui.coregui.client.util.message.Message; import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedIButton; import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout; +import org.rhq.enterprise.gui.coregui.client.util.message.Message;
public class BundleView extends EnhancedVLayout implements BookmarkableView { private DynamicForm form; @@ -277,7 +277,7 @@ public class BundleView extends EnhancedVLayout implements BookmarkableView { criteria.fetchDestinations(true); criteria.fetchTags(true);
- GWTServiceLookup.getBundleService().findBundlesByCriteriaWithDestinationFilter(criteria, + GWTServiceLookup.getBundleService().findBundlesByCriteria(criteria, new AsyncCallback<PageList<Bundle>>() { public void onFailure(Throwable caught) { CoreGUI.getErrorHandler().handleError(MSG.view_bundle_list_error3(), caught); diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/version/BundleVersionView.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/version/BundleVersionView.java index 52f73f3..3ac67dd 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/version/BundleVersionView.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/bundle/version/BundleVersionView.java @@ -58,9 +58,9 @@ import org.rhq.enterprise.gui.coregui.client.components.tagging.TagEditorView; import org.rhq.enterprise.gui.coregui.client.components.tagging.TagsChangedCallback; import org.rhq.enterprise.gui.coregui.client.gwt.BundleGWTServiceAsync; import org.rhq.enterprise.gui.coregui.client.gwt.GWTServiceLookup; -import org.rhq.enterprise.gui.coregui.client.util.message.Message; import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedIButton; import org.rhq.enterprise.gui.coregui.client.util.enhanced.EnhancedVLayout; +import org.rhq.enterprise.gui.coregui.client.util.message.Message;
/** * @author Greg Hinkle @@ -268,7 +268,7 @@ public class BundleVersionView extends EnhancedVLayout implements BookmarkableVi criteria.fetchConfigurationDefinition(true); criteria.fetchTags(true);
- bundleManager.findBundleVersionsByCriteriaWithDestinationFilter(criteria, + bundleManager.findBundleVersionsByCriteria(criteria, new AsyncCallback<PageList<BundleVersion>>() { public void onFailure(Throwable caught) { CoreGUI.getErrorHandler().handleError(MSG.view_bundle_version_loadFailure(), caught); diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/BundleGWTService.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/BundleGWTService.java index cd108b7..2a45f65 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/BundleGWTService.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/client/gwt/BundleGWTService.java @@ -47,8 +47,6 @@ public interface BundleGWTService extends RemoteService {
ResourceTypeBundleConfiguration getResourceTypeBundleConfiguration(int compatGroupId) throws RuntimeException;
- BundleVersion createBundleVersion(int bundleId, String name, String version, String recipe) throws RuntimeException; - BundleVersion createBundleVersionViaURL(String url, String username, String password) throws RuntimeException;
BundleVersion createBundleVersionViaRecipe(String recipe) throws RuntimeException; @@ -74,14 +72,9 @@ public interface BundleGWTService extends RemoteService {
PageList<BundleGroup> findBundleGroupsByCriteria(BundleGroupCriteria criteria) throws RuntimeException;
- PageList<Bundle> findBundlesByCriteriaWithDestinationFilter(BundleCriteria criteria) throws RuntimeException; - PageList<BundleDeployment> findBundleDeploymentsByCriteria(BundleDeploymentCriteria criteria) throws RuntimeException;
- PageList<BundleDeployment> findBundleDeploymentsByCriteriaWithDestinationFilter(BundleDeploymentCriteria criteria) - throws RuntimeException; - PageList<BundleDestination> findBundleDestinationsByCriteria(BundleDestinationCriteria criteria) throws RuntimeException;
@@ -92,8 +85,6 @@ public interface BundleGWTService extends RemoteService {
PageList<BundleVersion> findBundleVersionsByCriteria(BundleVersionCriteria criteria) throws RuntimeException;
- PageList<BundleVersion> findBundleVersionsByCriteriaWithDestinationFilter(BundleVersionCriteria criteria) throws RuntimeException; - PageList<BundleWithLatestVersionComposite> findBundlesWithLatestVersionCompositesByCriteria(BundleCriteria criteria) throws RuntimeException;
diff --git a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/BundleGWTServiceImpl.java b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/BundleGWTServiceImpl.java index 88458b8..01b17a1 100644 --- a/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/BundleGWTServiceImpl.java +++ b/modules/enterprise/gui/coregui/src/main/java/org/rhq/enterprise/gui/coregui/server/gwt/BundleGWTServiceImpl.java @@ -110,18 +110,6 @@ public class BundleGWTServiceImpl extends AbstractGWTServiceImpl implements Bund }
@Override - public BundleVersion createBundleVersion(int bundleId, String name, String version, String recipe) - throws RuntimeException { - try { - BundleVersion results = bundleManager.createBundleVersion(getSessionSubject(), bundleId, name, null, - version, recipe); - return SerialUtility.prepare(results, "createBundleVersion"); - } catch (Throwable t) { - throw getExceptionToThrowToClient(t); - } - } - - @Override public void deleteBundles(int[] bundleIds) throws RuntimeException { try { bundleManager.deleteBundles(getSessionSubject(), bundleIds); @@ -246,16 +234,6 @@ public class BundleGWTServiceImpl extends AbstractGWTServiceImpl implements Bund }
@Override - public PageList<Bundle> findBundlesByCriteriaWithDestinationFilter(BundleCriteria criteria) throws RuntimeException { - try { - PageList<Bundle> results = bundleManager.findBundlesByCriteriaWithDestinationFilter(getSessionSubject(), criteria); - return SerialUtility.prepare(results, "findBundlesByCriteriaWithDestinationFilter"); - } catch (Throwable t) { - throw getExceptionToThrowToClient(t); - } - } - - @Override public PageList<BundleDeployment> findBundleDeploymentsByCriteria(BundleDeploymentCriteria criteria) throws RuntimeException { try { @@ -268,18 +246,6 @@ public class BundleGWTServiceImpl extends AbstractGWTServiceImpl implements Bund }
@Override - public PageList<BundleDeployment> findBundleDeploymentsByCriteriaWithDestinationFilter(BundleDeploymentCriteria criteria) - throws RuntimeException { - try { - PageList<BundleDeployment> result = bundleManager.findBundleDeploymentsByCriteriaWithDestinationFilter(getSessionSubject(), - criteria); - return SerialUtility.prepare(result, "BundleService.findBundleDeploymentsByCriteriaWithDestinationFilter"); - } catch (Throwable t) { - throw getExceptionToThrowToClient(t); - } - } - - @Override public PageList<BundleDestination> findBundleDestinationsByCriteria(BundleDestinationCriteria criteria) throws RuntimeException { try { @@ -324,16 +290,6 @@ public class BundleGWTServiceImpl extends AbstractGWTServiceImpl implements Bund }
@Override - public PageList<BundleVersion> findBundleVersionsByCriteriaWithDestinationFilter(BundleVersionCriteria criteria) throws RuntimeException { - try { - PageList<BundleVersion> results = bundleManager.findBundleVersionsByCriteriaWithDestinationFilter(getSessionSubject(), criteria); - return SerialUtility.prepare(results, "findBundleVersionsByCriteriaWithDestinationFilter"); - } catch (Throwable t) { - throw getExceptionToThrowToClient(t); - } - } - - @Override public PageList<BundleWithLatestVersionComposite> findBundlesWithLatestVersionCompositesByCriteria( BundleCriteria criteria) throws RuntimeException { try { diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java index f60d426..c4d9a79 100644 --- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java +++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/bundle/BundleManagerBeanTest.java @@ -860,7 +860,7 @@ public class BundleManagerBeanTest extends AbstractEJB3Test { int size = brd.getBundleResourceDeploymentHistories().size(); assertTrue(size > 0); String auditMessage = "BundleTest-Message"; - bundleManager.addBundleResourceDeploymentHistory(overlord, brd.getId(), new BundleResourceDeploymentHistory( + bundleManager.addBundleResourceDeploymentHistoryInNewTrans(overlord, brd.getId(), new BundleResourceDeploymentHistory( overlord.getName(), auditMessage, auditMessage, BundleResourceDeploymentHistory.Category.DEPLOY_STEP, BundleResourceDeploymentHistory.Status.SUCCESS, auditMessage, auditMessage));
@@ -1242,7 +1242,7 @@ public class BundleManagerBeanTest extends AbstractEJB3Test { final BundleType type = createBundleType(name); final String recipe = "deploy -f " + TEST_PREFIX + ".zip -d @@ test.path @@"; final BundleVersion bundleVerison = bundleManager.createBundleAndBundleVersion(overlord, fullName, - "description", type.getId(), fullName, fullName + "-desc", "3.0", recipe); + "description", type.getId(), 0, fullName, fullName + "-desc", "3.0", recipe); assertNotNull(bundleVerison);
// find the previously created bundle @@ -1272,7 +1272,7 @@ public class BundleManagerBeanTest extends AbstractEJB3Test { final String fullName = TEST_PREFIX + "-bundle-" + name; final String recipe = "deploy -f " + TEST_PREFIX + ".zip -d @@ test.path @@"; final BundleVersion bundleVerison = bundleManager.createBundleAndBundleVersion(overlord, fullName, - "description", bundle.getBundleType().getId(), fullName, fullName + "-desc", "3.0", recipe); + "description", bundle.getBundleType().getId(), 0, fullName, fullName + "-desc", "3.0", recipe);
// find the newly created bundle BundleCriteria c = new BundleCriteria(); @@ -1284,6 +1284,12 @@ public class BundleManagerBeanTest extends AbstractEJB3Test { assertEquals(1, bundles.size()); }
+ @Test(enabled = false) + public void testNoAuthz() throws Exception { + // create + + } + // helper methods private BundleType createBundleType(String name) throws Exception { final String fullName = TEST_PREFIX + "-type-" + name; @@ -1302,7 +1308,7 @@ public class BundleManagerBeanTest extends AbstractEJB3Test {
private Bundle createBundle(String name, BundleType bt) throws Exception { final String fullName = TEST_PREFIX + "-bundle-" + name; - Bundle b = bundleManager.createBundle(overlord, fullName, fullName + "-desc", bt.getId()); + Bundle b = bundleManager.createBundle(overlord, fullName, fullName + "-desc", bt.getId(), 0);
assert b.getId() > 0; assert b.getName().endsWith(fullName); diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest.java index 48649d2..46f2bef 100644 --- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest.java +++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/resource/metadata/ResourceMetadataManagerBeanTest.java @@ -684,7 +684,7 @@ public class ResourceMetadataManagerBeanTest extends MetadataBeanTest { BundleType bundleType = bundleMgr.getBundleType(subjectMgr.getOverlord(), bundleTypeName); assertNotNull("Cannot create bundle. Unable to find bundle type for [name: " + bundleTypeName + "]", bundleType); Bundle bundle = bundleMgr.createBundle(subjectMgr.getOverlord(), bundleName, "test bundle: " + bundleName, - bundleType.getId()); + bundleType.getId(), 0);
assertNotNull("Failed create bundle for [name: " + bundleName + "]", bundle); } diff --git a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/tagging/TagManagerBeanTest.java b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/tagging/TagManagerBeanTest.java index 83a5dfe..bef8921 100644 --- a/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/tagging/TagManagerBeanTest.java +++ b/modules/enterprise/server/itests-2/src/test/java/org/rhq/enterprise/server/tagging/TagManagerBeanTest.java @@ -259,7 +259,7 @@ public class TagManagerBeanTest extends AbstractEJB3Test { private Bundle createBundle() throws Exception { ResourceType resourceType = SessionTestHelper.createNewResourceType(em); BundleType bundleType = bundleManager.createBundleType(overlord, getRandomString(), resourceType.getId()); - return bundleManager.createBundle(overlord, getRandomString(), getRandomString(), bundleType.getId()); + return bundleManager.createBundle(overlord, getRandomString(), getRandomString(), bundleType.getId(), 0); }
private BundleVersion createBundleVersion() throws Exception { diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java index 51e59ff..a9882c4 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerBean.java @@ -30,6 +30,7 @@ import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -197,9 +198,8 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
@Override @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) - @RequiredPermission(Permission.MANAGE_BUNDLE) - public BundleResourceDeploymentHistory addBundleResourceDeploymentHistory(Subject subject, int bundleDeploymentId, - BundleResourceDeploymentHistory history) throws Exception { + public BundleResourceDeploymentHistory addBundleResourceDeploymentHistoryInNewTrans(Subject subject, + int bundleDeploymentId, BundleResourceDeploymentHistory history) throws Exception {
BundleResourceDeployment resourceDeployment = entityManager.find(BundleResourceDeployment.class, bundleDeploymentId); @@ -214,8 +214,8 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot }
@Override - @RequiredPermission(Permission.MANAGE_BUNDLE) - public Bundle createBundle(Subject subject, String name, String description, int bundleTypeId) throws Exception { + public Bundle createBundle(Subject subject, String name, String description, int bundleTypeId, int bundleGroupId) + throws Exception { if (null == name || "".equals(name.trim())) { throw new IllegalArgumentException("Invalid bundleName: " + name); } @@ -225,8 +225,15 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot throw new IllegalArgumentException("Invalid bundleTypeId: " + bundleTypeId); }
- // create and add the required Repo. the Repo is a detached object which helps in its eventual - // removal. + BundleGroup bundleGroup = null; + if (bundleGroupId > 0) { + bundleGroup = entityManager.find(BundleGroup.class, bundleGroupId); + if (null == bundleGroup) { + throw new IllegalArgumentException("Invalid bundleGroupId: " + bundleGroupId); + } + } + + // create and add the required Repo. the Repo is a detached object which helps in its eventual removal. Repo repo = new Repo(name); repo.setCandidate(false); repo.setSyncSchedule(null); @@ -249,6 +256,9 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot Bundle bundle = new Bundle(name, bundleType, repo, packageType); bundle.setDescription(description); bundle.setPackageType(packageType); + if (null != bundleGroup) { + bundle.addBundleGroup(bundleGroup); + }
log.info("Creating bundle: " + bundle); entityManager.persist(bundle); @@ -258,7 +268,6 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
@Override @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) - @RequiredPermission(Permission.MANAGE_BUNDLE) public BundleDeployment createBundleDeploymentInNewTrans(Subject subject, int bundleVersionId, int bundleDestinationId, String name, String description, Configuration configuration) throws Exception {
@@ -287,7 +296,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot throw new IllegalArgumentException("Invalid bundleDestinationId: " + bundleDestinationId); }
- checkBundleDeploymentAuthz(subject, bundleVersion.getBundle().getId(), bundleDestination.getGroup().getId()); + checkDeployBundleAuthz(subject, bundleVersion.getBundle().getId(), bundleDestination.getGroup().getId());
String name = getBundleDeploymentNameImpl(subject, bundleDestination, bundleVersion, null); return this.createBundleDeploymentImpl(subject, bundleVersion, bundleDestination, name, description, @@ -348,7 +357,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot } ResourceGroup group = entityManager.find(ResourceGroup.class, groups.get(0).getId());
- checkBundleDeploymentAuthz(subject, bundle.getId(), groupId); + checkDeployBundleAuthz(subject, bundle.getId(), groupId);
BundleDestination dest = new BundleDestination(bundle, name, group, destBaseDirName, deployDir); dest.setDescription(description); @@ -383,6 +392,8 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot + "] or prevDeploymentId [" + prevDeploymentId + "]"); }
+ checkDeployBundleAuthz(subject, bundleVersion.getBundle().getId(), bundleDestination.getGroup().getId()); + return getBundleDeploymentNameImpl(subject, bundleDestination, bundleVersion, prevDeployment); }
@@ -442,7 +453,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot }
@Override - @RequiredPermission(Permission.MANAGE_BUNDLE) + @RequiredPermission(Permission.CREATE_BUNDLES) public BundleType createBundleType(Subject subject, String name, int resourceTypeId) throws Exception { if (null == name || "".equals(name.trim())) { throw new IllegalArgumentException("Invalid bundleTypeName: " + name); @@ -459,22 +470,21 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot }
@Override - @RequiredPermission(Permission.MANAGE_BUNDLE) public BundleVersion createBundleAndBundleVersion(Subject subject, String bundleName, String bundleDescription, - int bundleTypeId, String bundleVersionName, String bundleVersionDescription, String version, String recipe) - throws Exception { + int bundleTypeId, int bundleGroupId, String bundleVersionName, String bundleVersionDescription, String version, + String recipe) throws Exception {
// first see if the bundle exists or not; if not, create one BundleCriteria criteria = new BundleCriteria(); criteria.setStrict(true); criteria.addFilterBundleTypeId(Integer.valueOf(bundleTypeId)); criteria.addFilterName(bundleName); - criteria.clearPaging();//disable paging as the code assumes all the results will be returned. + criteria.clearPaging(); //disable paging as the code assumes all the results will be returned.
PageList<Bundle> bundles = findBundlesByCriteria(subject, criteria); Bundle bundle; if (bundles.getTotalSize() == 0) { - bundle = createBundle(subject, bundleName, bundleDescription, bundleTypeId); + bundle = createBundle(subject, bundleName, bundleDescription, bundleTypeId, bundleGroupId); } else { bundle = bundles.get(0); } @@ -487,7 +497,6 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
@Override @SuppressWarnings("unchecked") - @RequiredPermission(Permission.MANAGE_BUNDLE) public BundleVersion createBundleVersion(Subject subject, int bundleId, String name, String description, String version, String recipe) throws Exception { if (null == name || "".equals(name.trim())) { @@ -533,7 +542,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot versionOrder = ((Number) bv[1]).intValue(); needToUpdateOrder = true; } else { - break; // comparision > 0, means our new version is higher than what's in the DB, because we DESC ordered, we can stop + break; // Comparison > 0, means our new version is higher than what's in the DB, because we DESC ordered, we can stop } }
@@ -753,7 +762,8 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
if (isInitialVersion) { checkCreateInitialBundleVersionAuthz(subject, initialBundleGroupId); - bundle = bundleManager.createBundle(subject, bundleName, bundleDescription, bundleType.getId()); + bundle = bundleManager.createBundle(subject, bundleName, bundleDescription, bundleType.getId(), + initialBundleGroupId); createdBundle = true; } else { bundle = bundles.get(0); @@ -762,8 +772,8 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot }
// now create the bundle version with the bundle we either found or created - BundleVersion bundleVersion = bundleManager.createBundleVersion(subject, bundle.getId(), name, description, - version, recipe); + BundleVersion bundleVersion = bundleManager.createBundleVersion(subjectManager.getOverlord(), bundle.getId(), + name, description, version, recipe);
// now that we have the bundle version we can actually create the bundle files that were provided in // the bundle distribution @@ -979,7 +989,6 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot }
@Override - @RequiredPermission(Permission.MANAGE_BUNDLE) public BundleFile addBundleFileViaPackageVersion(Subject subject, int bundleVersionId, String name, int packageVersionId) throws Exception {
@@ -1010,7 +1019,6 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot }
@Override - @RequiredPermission(Permission.MANAGE_BUNDLE) @TransactionAttribute(TransactionAttributeType.NEVER) public void purgeBundleDestination(final Subject subject, int bundleDestinationId) throws Exception { // find the live bundle deployment for this destination, and get all the resource deployments for that live deployment @@ -1031,6 +1039,13 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot return; // nothing to do }
+ // Although they likely will, the actual resource deployments may no longer match the members of the destination's + // resource group (if group membership has changed). We still use the group for authz because that is the more + // intuitive, manageable way to do this. Otherwise the subject would need view perms on each of the previously + // deployed-to resources, and that may be tricky to provide. + checkDeployBundleAuthz(subject, liveDeployment.getBundleVersion().getBundle().getId(), liveDeployment + .getDestination().getGroup().getId()); + // we need to obtain the bundle type (the remote plugin container needs it). our first criteria can't fetch this deep, we have to do another query. BundleVersionCriteria bvc = new BundleVersionCriteria(); bvc.addFilterId(liveDeployment.getBundleVersion().getId()); @@ -1082,7 +1097,8 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot BundleResourceDeploymentHistory history = new BundleResourceDeploymentHistory(subject.getName(), "Purge Requested", "User [" + subject.getName() + "] requested to purge this deployment", null, BundleResourceDeploymentHistory.Status.SUCCESS, null, null); - bundleManager.addBundleResourceDeploymentHistory(subject, resourceDeploy.getId(), history); + bundleManager.addBundleResourceDeploymentHistoryInNewTrans(subjectManager.getOverlord(), + resourceDeploy.getId(), history);
// get a connection to the agent and tell it to purge the bundle from the file system Subject overlord = subjectManager.getOverlord(); @@ -1116,8 +1132,6 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot }
@Override - @RequiredPermission(Permission.MANAGE_SECURITY) - // no one should be calling us except overlord public void _finalizePurge(Subject subject, BundleDeployment bundleDeployment, Map<BundleResourceDeployment, String> failedToPurge) throws Exception {
@@ -1154,14 +1168,12 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot }
@Override - @RequiredPermission(Permission.MANAGE_BUNDLE) public BundleDeployment scheduleBundleDeployment(Subject subject, int bundleDeploymentId, boolean isCleanDeployment) throws Exception { return scheduleBundleDeploymentImpl(subject, bundleDeploymentId, isCleanDeployment, false, null); }
@Override - @RequiredPermission(Permission.MANAGE_BUNDLE) public BundleDeployment scheduleRevertBundleDeployment(Subject subject, int bundleDestinationId, String deploymentDescription, boolean isCleanDeployment) throws Exception {
@@ -1189,6 +1201,9 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot + "] can not be reverted. There is no prior deployment for destinationId [" + bundleDestinationId + "]"); }
+ checkDeployBundleAuthz(subject, liveDeployment.getBundleVersion().getBundle().getId(), liveDeployment + .getDestination().getGroup().getId()); + // A revert is done by deploying a new deployment that mirrors "prevDeployment". It uses the same // bundleVersion, destination and config as prevDeployment. It can have a new name and new desc, and // may opt to clean the deploy dir. It must be a new deployment so that all status/auditing/history starts @@ -1225,6 +1240,8 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot + "] group has no members. Invalid deployment destination"); }
+ checkDeployBundleAuthz(subject, newDeployment.getBundleVersion().getBundle().getId(), group.getId()); + for (Resource groupMember : groupMembers) { try { scheduleBundleResourceDeployment(subject, newDeployment, groupMember, isCleanDeployment, isRevert); @@ -1277,8 +1294,8 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
// The BundleResourceDeployment record must exist in the db before the agent request because the agent may try // to add History to it during immediate deployments. So, create and persist it (requires a new trans). - BundleResourceDeployment resourceDeployment = bundleManager.createBundleResourceDeployment(subject, - deployment.getId(), bundleTargetResourceId); + BundleResourceDeployment resourceDeployment = bundleManager.createBundleResourceDeploymentInNewTrans( + subjectManager.getOverlord(), deployment.getId(), bundleTargetResourceId);
if (null != bundleTarget.getResourceType().getResourceTypeBundleConfiguration()) {
@@ -1292,7 +1309,8 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot AUDIT_ACTION_DEPLOYMENT_REQUESTED, deployment.getName(), null, BundleResourceDeploymentHistory.Status.SUCCESS, "Requested deployment time: " + request.getRequestedDeployTimeAsString(), null); - bundleManager.addBundleResourceDeploymentHistory(subject, resourceDeployment.getId(), history); + bundleManager.addBundleResourceDeploymentHistoryInNewTrans(subjectManager.getOverlord(), + resourceDeployment.getId(), history);
BundleScheduleResponse response = bundleAgentService.schedule(request);
@@ -1303,7 +1321,8 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot history = new BundleResourceDeploymentHistory(subject.getName(), AUDIT_ACTION_DEPLOYMENT, deployment.getName(), null, BundleResourceDeploymentHistory.Status.FAILURE, response.getErrorMessage(), null); - bundleManager.addBundleResourceDeploymentHistory(subject, resourceDeployment.getId(), history); + bundleManager.addBundleResourceDeploymentHistoryInNewTrans(subject, resourceDeployment.getId(), + history); } } catch (Throwable t) { // fail the unlaunched resource deployment @@ -1311,7 +1330,8 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot this.AUDIT_ACTION_DEPLOYMENT, deployment.getName(), null, BundleResourceDeploymentHistory.Status.FAILURE, "Failed to schedule, agent on [" + bundleTarget + "] may be down: " + t, null); - bundleManager.addBundleResourceDeploymentHistory(subject, resourceDeployment.getId(), failureHistory); + bundleManager.addBundleResourceDeploymentHistoryInNewTrans(subject, resourceDeployment.getId(), + failureHistory); bundleManager.setBundleResourceDeploymentStatus(subject, resourceDeployment.getId(), BundleDeploymentStatus.FAILURE); } @@ -1324,7 +1344,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot "Target resource is not of a type that can have bundles deployed to it [resource=" + bundleTarget.getName() + "; id=" + bundleTarget.getId() + "]. Fix target group for destination [" + deployment.getDestination().getName() + "]", null); - bundleManager.addBundleResourceDeploymentHistory(subject, resourceDeployment.getId(), history); + bundleManager.addBundleResourceDeploymentHistoryInNewTrans(subject, resourceDeployment.getId(), history); }
return resourceDeployment; @@ -1332,7 +1352,6 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
@Override @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED) - @RequiredPermission(Permission.MANAGE_BUNDLE) public BundleScheduleRequest getScheduleRequest(Subject subject, int resourceDeploymentId, boolean isCleanDeployment, boolean isRevert) throws Exception {
@@ -1391,8 +1410,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
@Override @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) - @RequiredPermission(Permission.MANAGE_BUNDLE) - public BundleResourceDeployment createBundleResourceDeployment(Subject subject, int bundleDeploymentId, + public BundleResourceDeployment createBundleResourceDeploymentInNewTrans(Subject subject, int bundleDeploymentId, int resourceId) throws Exception {
BundleDeployment deployment = entityManager.find(BundleDeployment.class, bundleDeploymentId); @@ -1411,7 +1429,6 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot }
@Override - @RequiredPermission(Permission.MANAGE_BUNDLE) public BundleResourceDeployment setBundleResourceDeploymentStatus(Subject subject, int resourceDeploymentId, BundleDeploymentStatus status) throws Exception {
@@ -1456,14 +1473,7 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot return resourceDeployment; }
- // @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) - // public BundleGroupDeployment createBundleGroupDeployment(BundleGroupDeployment groupDeployment) throws Exception { - // entityManager.persist(groupDeployment); - // return groupDeployment; - //} - @Override - @RequiredPermission(Permission.MANAGE_BUNDLE) public Set<String> getBundleVersionFilenames(Subject subject, int bundleVersionId, boolean withoutBundleFileOnly) throws Exception {
@@ -1472,6 +1482,8 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot throw new IllegalArgumentException("Invalid bundleVersionId: " + bundleVersionId); }
+ checkCreateBundleVersionAuthz(subject, bundleVersion.getBundle().getId()); + // parse the recipe (validation occurs here) and get the config def and list of files BundleType bundleType = bundleVersion.getBundle().getBundleType(); RecipeParseResults parseResults = BundleManagerHelper.getPluginContainer().getBundleServerPluginManager() @@ -1499,11 +1511,9 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot }
return result; - }
@Override - @RequiredPermission(Permission.MANAGE_BUNDLE) public HashMap<String, Boolean> getAllBundleVersionFilenames(Subject subject, int bundleVersionId) throws Exception {
BundleVersion bundleVersion = entityManager.find(BundleVersion.class, bundleVersionId); @@ -1511,6 +1521,8 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot throw new IllegalArgumentException("Invalid bundleVersionId: " + bundleVersionId); }
+ checkCreateBundleVersionAuthz(subject, bundleVersion.getBundle().getId()); + // parse the recipe (validation occurs here) and get the config def and list of files BundleType bundleType = bundleVersion.getBundle().getBundleType(); RecipeParseResults parseResults = BundleManagerHelper.getPluginContainer().getBundleServerPluginManager() @@ -1533,7 +1545,6 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot }
return result; - }
@Override @@ -1557,44 +1568,40 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot @Override public PageList<BundleDeployment> findBundleDeploymentsByCriteria(Subject subject, BundleDeploymentCriteria criteria) { CriteriaQueryGenerator generator = new CriteriaQueryGenerator(subject, criteria); - CriteriaQueryRunner<BundleDeployment> queryRunner = new CriteriaQueryRunner<BundleDeployment>(criteria, - generator, entityManager); - return queryRunner.execute(); - } - - /** - * Fetch bundle deployments by criteria and then filter on destinations on the result objects to limit what the user can see - * @param subject Caller - * @param criteria criteria to fetch the deployments - * @return List of deployments with destinations filtered. - */ - @Override - public PageList<BundleDeployment> findBundleDeploymentsByCriteriaWithDestinationFilter(Subject subject, - BundleDeploymentCriteria criteria) { - - PageList<BundleDeployment> deployments = findBundleDeploymentsByCriteria(subject, criteria); - if (authorizationManager.isInventoryManager(subject)) - return deployments;
- PageList<BundleDeployment> resultingDeployments = new PageList<BundleDeployment>(deployments.getPageControl()); - // We now have visible destinations - go over the resultingDeployments and only include the ones with vis. destinations - for (BundleDeployment deployment : deployments) { + // filter by bundles that are viewable + if (!authorizationManager.hasGlobalPermission(subject, Permission.VIEW_BUNDLES)) { + generator.setAuthorizationResourceFragment(CriteriaQueryGenerator.AuthorizationTokenType.BUNDLE, null, + subject.getId()); + }
- int bundleId = deployment.getBundleVersion().getBundle().getId(); - BundleDestinationCriteria destinationCriteria = new BundleDestinationCriteria(); - destinationCriteria.addFilterBundleId(bundleId); - List<BundleDestination> destinations = findBundleDestinationsByCriteria(subject, destinationCriteria); - if (destinationsContains(destinations, deployment.getDestination())) - resultingDeployments.add(deployment); + CriteriaQueryRunner<BundleDeployment> queryRunner = new CriteriaQueryRunner<BundleDeployment>(criteria, + generator, entityManager); + PageList<BundleDeployment> result = queryRunner.execute(); + + // The result currently holds bundle deployments for bundles viewable by the caller, but we must remove + // those bundle deployments for destinations not viewable by the user. In essence we wanted two authz tokens, + // one for bundle and one for resource group, but we can only supply one. + if (!(result.isEmpty() || authorizationManager.isInventoryManager(subject))) { + + for (Iterator<BundleDeployment> i = result.iterator(); i.hasNext();) { + BundleDeployment bd = i.next(); + int groupId = bd.getDestination().getGroup().getId(); + if (!authorizationManager.canViewGroup(subject, groupId)) { + i.remove(); + } + } } - return resultingDeployments; + + return result; }
@Override public PageList<BundleDestination> findBundleDestinationsByCriteria(Subject subject, BundleDestinationCriteria criteria) { CriteriaQueryGenerator generator = new CriteriaQueryGenerator(subject, criteria); - // Filter by destinations that are viewable + + // Filter by destinations (resource groups) that are viewable if (!authorizationManager.isInventoryManager(subject)) { generator.setAuthorizationResourceFragment(CriteriaQueryGenerator.AuthorizationTokenType.GROUP, subject.getId()); @@ -1610,74 +1617,95 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
CriteriaQueryGenerator generator = new CriteriaQueryGenerator(subject, criteria);
- if (!authorizationManager.isInventoryManager(subject)) { - if (criteria.isInventoryManagerRequired()) { - // TODO: MANAGE_INVENTORY was too restrictive as a bundle manager could not then - // see his resource deployments. Until we can handle granular authorization checks on - // optionally fetched resource member data, allow a bundle manager to see - // resource deployments to any resource. - if (!authorizationManager.hasGlobalPermission(subject, Permission.MANAGE_BUNDLE)) { - throw new PermissionException("Subject [" + subject.getName() - + "] requires InventoryManager or BundleManager permission for requested query criteria."); - } - } - // TODO limit target groups according to visibility + // filter by bundles that are viewable + if (!authorizationManager.hasGlobalPermission(subject, Permission.VIEW_BUNDLES)) { + generator.setAuthorizationResourceFragment(CriteriaQueryGenerator.AuthorizationTokenType.BUNDLE, null, + subject.getId()); }
CriteriaQueryRunner<BundleResourceDeployment> queryRunner = new CriteriaQueryRunner<BundleResourceDeployment>( criteria, generator, entityManager); + PageList<BundleResourceDeployment> result = queryRunner.execute();
- return queryRunner.execute(); + // if necessary, filter results to resources that are viewable + if (!result.isEmpty() && criteria.isInventoryManagerRequired() + && !authorizationManager.isInventoryManager(subject)) { + + // try to authorize in one call, if that fails then go (slow) fine-grained + List<Integer> resourceIds = new ArrayList<Integer>(result.size()); + for (BundleResourceDeployment brd : result) { + int resourceId = brd.getResource().getId(); + resourceIds.add(resourceId); + } + + if (!authorizationManager.canViewResources(subject, resourceIds)) { + for (Integer resourceId : resourceIds) { + if (!authorizationManager.canViewResource(subject, resourceId)) { + for (Iterator<BundleResourceDeployment> i = result.iterator(); i.hasNext();) { + BundleResourceDeployment brd = i.next(); + if (brd.getResource().getId() == resourceId.intValue()) { + i.remove(); + } + } + } + } + } + } + + return result; }
@Override public PageList<BundleVersion> findBundleVersionsByCriteria(Subject subject, BundleVersionCriteria criteria) { CriteriaQueryGenerator generator = new CriteriaQueryGenerator(subject, criteria); - CriteriaQueryRunner<BundleVersion> queryRunner = new CriteriaQueryRunner<BundleVersion>(criteria, generator, - entityManager); - return queryRunner.execute(); - } - - /** - * Fetch bundle versions by criteria and then filter destination on the result objects to limit what the user can see - * @param subject Caller - * @param criteria criteria to fetch the bundles - * @return List of versions with destinations filtered. - */ - @Override - public PageList<BundleVersion> findBundleVersionsByCriteriaWithDestinationFilter(Subject subject, - BundleVersionCriteria criteria) {
- PageList<BundleVersion> versions = findBundleVersionsByCriteria(subject, criteria); - if (authorizationManager.isInventoryManager(subject)) { - return versions; + if (!authorizationManager.hasGlobalPermission(subject, Permission.VIEW_BUNDLES)) { + generator.setAuthorizationResourceFragment(CriteriaQueryGenerator.AuthorizationTokenType.BUNDLE, null, + subject.getId()); } - // Not inv manager -> restrict visible deployments by visible destinations
- for (BundleVersion version : versions) { + CriteriaQueryRunner<BundleVersion> queryRunner = new CriteriaQueryRunner<BundleVersion>(criteria, generator, + entityManager); + PageList<BundleVersion> result = queryRunner.execute(); + + // If asking for optional data that the subject may not be able to see then ensure that the optional + // data is filtered appropriately. In this case only deployments to destinations viewable by the subject + // can be returned. The result currently holds bundle versions viewable by the caller, but the bundle version + // may have been deployed to destinations for which the user does not have access to the destination's + // resource group. (BZ 694741) + if (!result.isEmpty() && criteria.isInventoryManagerRequired() + && !authorizationManager.isInventoryManager(subject)) { + + // this works because findBundleDestinationsByCriteria() authorizes against resource group associations + + for (BundleVersion bundleVersion : result) { + int numDeployments = bundleVersion.getBundleDeployments().size(); + if (0 == numDeployments) { + continue; + }
- Bundle bundle = version.getBundle(); - BundleDestinationCriteria destinationCriteria = new BundleDestinationCriteria(); - destinationCriteria.addFilterBundleId(bundle.getId()); - destinationCriteria.clearPaging();//disable paging as the code assumes all the results will be returned. + Bundle bundle = bundleVersion.getBundle(); + BundleDestinationCriteria destinationCriteria = new BundleDestinationCriteria(); + destinationCriteria.clearPaging(); //disable paging as the code assumes all the results will be returned. + destinationCriteria.addFilterBundleId(bundle.getId()); + + // get the viewable destinations and use to filter the deployments + List<BundleDestination> destinations = findBundleDestinationsByCriteria(subject, destinationCriteria); + List<BundleDeployment> filteredDeployments = new ArrayList<BundleDeployment>(numDeployments); + entityManager.detach(bundleVersion); // make sure we don't persist the filtered data + for (BundleDeployment deployment : bundleVersion.getBundleDeployments()) { + if (containsDestination(destinations, deployment.getDestination())) + filteredDeployments.add(deployment); + }
- List<BundleDestination> destinations = findBundleDestinationsByCriteria(subject, destinationCriteria); - List<BundleDeployment> resultingDeployments = new ArrayList<BundleDeployment>(version - .getBundleDeployments().size()); - // We now have visible destinations - go over the resultingDeployments and only include the ones with vis. destinations - for (BundleDeployment deployment : version.getBundleDeployments()) { - if (destinationsContains(destinations, deployment.getDestination())) - resultingDeployments.add(deployment); + bundleVersion.setBundleDeployments(filteredDeployments); } - - version.setBundleDeployments(resultingDeployments); }
- return versions; - + return result; }
- private boolean destinationsContains(List<BundleDestination> list, BundleDestination dest) { + private boolean containsDestination(List<BundleDestination> list, BundleDestination dest) { int id = dest.getId(); for (BundleDestination destination : list) { if (destination.getId() == id) @@ -1689,6 +1717,13 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot @Override public PageList<BundleFile> findBundleFilesByCriteria(Subject subject, BundleFileCriteria criteria) { CriteriaQueryGenerator generator = new CriteriaQueryGenerator(subject, criteria); + + // filter by bundles that are viewable + if (!authorizationManager.hasGlobalPermission(subject, Permission.VIEW_BUNDLES)) { + generator.setAuthorizationResourceFragment(CriteriaQueryGenerator.AuthorizationTokenType.BUNDLE, null, + subject.getId()); + } + CriteriaQueryRunner<BundleFile> queryRunner = new CriteriaQueryRunner<BundleFile>(criteria, generator, entityManager); return queryRunner.execute(); @@ -1700,40 +1735,35 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot CriteriaQueryGenerator generator = new CriteriaQueryGenerator(subject, criteria);
if (!authorizationManager.hasGlobalPermission(subject, Permission.VIEW_BUNDLES)) { - generator.setAuthorizationResourceFragment(CriteriaQueryGenerator.AuthorizationTokenType.BUNDLE, null, subject.getId()); }
CriteriaQueryRunner<Bundle> queryRunner = new CriteriaQueryRunner<Bundle>(criteria, generator, entityManager); - return queryRunner.execute(); - } - - /** - * Fetch bundles by criteria and then filter destination on the result objects to limit what the user can see - * @param subject Caller - * @param criteria criteria to fetch the bundles - * @return List of bundles with destinations filtered. - */ - @Override - public PageList<Bundle> findBundlesByCriteriaWithDestinationFilter(Subject subject, BundleCriteria criteria) { - // First get the bundles - PageList<Bundle> bundles = findBundlesByCriteria(subject, criteria); - if (authorizationManager.isInventoryManager(subject)) { - return bundles; - } - // Not inv manager -> restrict visible destinations - PageList<Bundle> result = new PageList<Bundle>(bundles.size(), bundles.getPageControl()); - for (Bundle bundle : bundles.getValues()) { // TODO clone the bundle and return the modified clones - BundleDestinationCriteria destinationCriteria = new BundleDestinationCriteria(); - destinationCriteria.addFilterBundleId(bundle.getId()); - destinationCriteria.clearPaging();//disable paging as the code assumes all the results will be returned. - - List<BundleDestination> destinations = findBundleDestinationsByCriteria(subject, destinationCriteria); - bundle.setDestinations(destinations); + PageList<Bundle> result = queryRunner.execute(); + + // If asking for optional data that the subject may not be able to see then ensure that the optional + // data is filtered appropriately. In this case only destinations viewable by the subject can be returned. + // The result currently holds bundles viewable by the caller, but the bundle may have been deployed to + // destinations for which the user does not have access to the destination's resource group. (BZ 694741) + if (!result.isEmpty() && criteria.isInventoryManagerRequired() + && !authorizationManager.isInventoryManager(subject)) { + + // this works because findBundleDestinationsByCriteria() authorizes against resource group associations + for (Bundle bundle : result) { + if (bundle.getDestinations().isEmpty()) { + continue; + } + BundleDestinationCriteria destinationCriteria = new BundleDestinationCriteria(); + destinationCriteria.clearPaging(); //disable paging as the code assumes all the results will be returned. + destinationCriteria.addFilterBundleId(bundle.getId()); + List<BundleDestination> destinations = findBundleDestinationsByCriteria(subject, destinationCriteria); + entityManager.detach(bundle); // make sure the narrowed set of destinations does not get persisted + bundle.setDestinations(destinations); + } }
- return bundles; + return result; }
@Override @@ -1750,6 +1780,11 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot + " ( SELECT COUNT(bv3) FROM bundle.bundleVersions bv3 WHERE bv3.bundle.id = bundle.id) AS deploymentCount ) "; generator.alterProjection(replacementSelectList);
+ if (!authorizationManager.hasGlobalPermission(subject, Permission.VIEW_BUNDLES)) { + generator.setAuthorizationResourceFragment(CriteriaQueryGenerator.AuthorizationTokenType.BUNDLE, null, + subject.getId()); + } + CriteriaQueryRunner<BundleWithLatestVersionComposite> queryRunner = new CriteriaQueryRunner<BundleWithLatestVersionComposite>( criteria, generator, entityManager); PageList<BundleWithLatestVersionComposite> results = queryRunner.execute(); @@ -1771,13 +1806,14 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
@Override @SuppressWarnings("unchecked") - @RequiredPermission(Permission.MANAGE_BUNDLE) public void deleteBundle(Subject subject, int bundleId) throws Exception { Bundle bundle = this.entityManager.find(Bundle.class, bundleId); if (null == bundle) { return; }
+ checkDeleteBundleAuthz(subject, bundleId); + Query q = entityManager.createNamedQuery(BundleVersion.QUERY_FIND_BY_BUNDLE_ID); q.setParameter("bundleId", bundleId); List<BundleVersion> bvs = q.getResultList(); @@ -1797,12 +1833,15 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot }
@Override - @RequiredPermission(Permission.MANAGE_BUNDLE) public void deleteBundleDeployment(Subject subject, int bundleDeploymentId) throws Exception { BundleDeployment doomed = this.entityManager.find(BundleDeployment.class, bundleDeploymentId); if (null == doomed) { return; } + + checkDeployBundleAuthz(subject, doomed.getBundleVersion().getBundle().getId(), doomed.getDestination() + .getGroup().getId()); + // only allow deployments to be deleted if they are finished if (BundleDeploymentStatus.SUCCESS == doomed.getStatus() || BundleDeploymentStatus.FAILURE == doomed.getStatus() @@ -1814,13 +1853,14 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot }
@Override - @RequiredPermission(Permission.MANAGE_BUNDLE) public void deleteBundleDestination(Subject subject, int destinationId) throws Exception { BundleDestination doomed = this.entityManager.find(BundleDestination.class, destinationId); if (null == doomed) { return; }
+ checkDeployBundleAuthz(subject, doomed.getBundle().getId(), doomed.getGroup().getId()); + // deployments replace other deployments and have a self-referring FK. The deployments // need to be removed in a way that will ensure that a replaced deployment is not removed // prior to the replacer. To do this we'll just blanket update all the doomed deployments @@ -1834,26 +1874,26 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot }
@Override - @RequiredPermission(Permission.MANAGE_BUNDLE) public void deleteBundleVersion(Subject subject, int bundleVersionId, boolean deleteBundleIfEmpty) throws Exception { BundleVersion bundleVersion = this.entityManager.find(BundleVersion.class, bundleVersionId); if (null == bundleVersion) { return; }
+ int bundleId = bundleVersion.getBundle().getId(); + + checkDeleteBundleAuthz(subject, bundleId); + // After we delete this bundle version, this is the version order value that is being removed. // Later we need to re-order the other bundles that are newer than this so their version orders are readjusted. int doomedBundleVersionOrder = bundleVersion.getVersionOrder();
- int bundleId = bundleVersion.getBundle().getId(); - // deployments replace other deployments and have a self-referring FK. The deployments // need to be removed in a way that will ensure that a replaced deployment is not removed // prior to the replacer. To do this we'll just blanket update all the doomed deployments // to break the FK dependency with nulls. Query q = entityManager.createNamedQuery(BundleDeployment.QUERY_UPDATE_FOR_VERSION_REMOVE); q.setParameter("bundleVersionId", bundleVersionId); - @SuppressWarnings("unused") int rowsUpdated = q.executeUpdate(); entityManager.flush();
@@ -1970,10 +2010,10 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot public PageList<BundleGroup> findBundleGroupsByCriteria(Subject subject, BundleGroupCriteria criteria) { CriteriaQueryGenerator generator = new CriteriaQueryGenerator(subject, criteria);
- if (!authorizationManager.hasGlobalPermission(subject, Permission.VIEW_BUNDLES)) { - - generator.setAuthorizationResourceFragment(CriteriaQueryGenerator.AuthorizationTokenType.BUNDLE, null, - subject.getId()); + // filter by bundle groups that are viewable + if (!authorizationManager.hasGlobalPermission(subject, Permission.MANAGE_BUNDLE_GROUPS)) { + generator.setAuthorizationResourceFragment(CriteriaQueryGenerator.AuthorizationTokenType.BUNDLE_GROUP, + null, subject.getId()); }
CriteriaQueryRunner<BundleGroup> queryRunner = new CriteriaQueryRunner<BundleGroup>(criteria, generator, @@ -1983,11 +2023,29 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
@Override public void unassignBundlesFromBundleGroup(Subject subject, int bundleGroupId, int[] bundleIds) { - // TODO Auto-generated method stub + BundleGroup bundleGroup = entityManager.find(BundleGroup.class, bundleGroupId); + if (null == bundleGroup) { + throw new IllegalArgumentException("BundleGroup does not exist for bundleGroupId [" + bundleGroupId + "]"); + } + + checkAssignBundleGroupAuthz(subject, bundleGroupId, bundleIds);
+ for (int bundleId : bundleIds) { + Bundle bundle = entityManager.find(Bundle.class, bundleId); + if (null == bundle) { + throw new IllegalArgumentException("Bundle does not exist for bundleId [" + bundleId + "]"); + } + + bundleGroup.removeBundle(bundle); + } }
/** + * Required Permissions: Either: + * - Global.CREATE_BUNDLES and Global.VIEW_BUNDLES + * - Global.CREATE_BUNDLES and BundleGroup.VIEW_BUNDLES_IN_GROUP for bundle group BG + * - BundleGroup.CREATE_BUNDLES_IN_GROUP for bundle group BG + * * @param subject * @param bundleGroupId null or 0 for unassigned initial bundle version creation * @throws PermissionException @@ -2026,6 +2084,11 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot }
/** + * Required Permissions: Either: + * - Global.CREATE_BUNDLES and Global.VIEW_BUNDLES + * - Global.CREATE_BUNDLES and BundleGroup.VIEW_BUNDLES_IN_GROUP for bundle group BG and the relevant bundle is assigned to BG + * - BundleGroup.CREATE_BUNDLES_IN_GROUP for bundle group BG and the relevant bundle is assigned to BG + * * @param subject * @param bundleId required, bundleId of bundle in which bundle version is being created/updated * @throws PermissionException @@ -2062,6 +2125,10 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot }
/** + * Requires VIEW permission for the relevant bundle and either: + * - Global.CREATE_BUNDLE + * - BundleGroup.CREATE_BUNDLES_IN_GROUP or BundleGroup.ASSIGN_BUNDLES_TO_GROUP for the relevant bundle group + * * @param subject * @param bundleGroupId an existing bundle group * @param bundleIds existing bundles @@ -2109,8 +2176,12 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot return; }
- private void checkBundleDeploymentAuthz(Subject subject, int bundleId, int resourceGroupId) - throws PermissionException { + /** + * Required Permissions: Either: + * - Global.DEPLOY_BUNDLES and a view of the relevant bundle and a view of the relevant resource group (may involve multiple roles) + * - Resource.DEPLOY_BUNDLES_TO_GROUP and a view of the relevant bundle and a view of the relevant resource group (may involve multiple roles) + */ + private void checkDeployBundleAuthz(Subject subject, int bundleId, int resourceGroupId) throws PermissionException {
boolean hasResourceGroupView = authorizationManager.hasGroupPermission(subject, Permission.VIEW_RESOURCE, resourceGroupId); @@ -2143,4 +2214,46 @@ public class BundleManagerBean implements BundleManagerLocal, BundleManagerRemot
return; } + + /** + * Required Permissions: Either: + * - Global.DELETE_BUNDLES and Global.VIEW_BUNDLES + * - Global.DELETE_BUNDLES and BundleGroup.VIEW_BUNDLES_IN_GROUP for bundle group BG and the relevant bundle is assigned to BG + * - BundleGroup.DELETE_BUNDLES_FROM_GROUP for bundle group BG and the relevant bundle is assigned to BG + * + * @param subject + * @param bundleId required, bundleId of bundle, or the bundle version, being deleted + * @throws PermissionException + */ + private void checkDeleteBundleAuthz(Subject subject, int bundleId) throws PermissionException { + + if (bundleId <= 0) { + throw new IllegalArgumentException( + "Must supply valid bundleId for bundle version being deleted. BundleId specified [" + bundleId + "]"); + } + + Set<Permission> globalPerms = authorizationManager.getExplicitGlobalPermissions(subject); + boolean hasGlobalDeleteBundles = globalPerms.contains(Permission.DELETE_BUNDLES); + + if (hasGlobalDeleteBundles && globalPerms.contains(Permission.VIEW_BUNDLES)) { + return; + } + + if (hasGlobalDeleteBundles) { + if (authorizationManager.hasBundlePermission(subject, Permission.VIEW_BUNDLES_IN_GROUP, bundleId)) { + return; + } + } else { + if (authorizationManager.hasBundlePermission(subject, Permission.DELETE_BUNDLES_FROM_GROUP, bundleId)) { + return; + } + } + + String msg = "Subject [" + + subject.getName() + + "] requires either Global.DELETE_BUNDLES + BundleGroup.VIEW_BUNDLES_IN_GROUP, or BundleGroup.DELETE_BUNDLES_FROM_GROUP, to delete bundle [" + + bundleId + "]."; + throw new PermissionException(msg); + } + } diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerLocal.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerLocal.java index b4d7d1b..01ca620 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerLocal.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerLocal.java @@ -33,10 +33,6 @@ import org.rhq.core.domain.bundle.BundleResourceDeploymentHistory; import org.rhq.core.domain.bundle.BundleType; import org.rhq.core.domain.bundle.BundleVersion; import org.rhq.core.domain.configuration.Configuration; -import org.rhq.core.domain.criteria.BundleCriteria; -import org.rhq.core.domain.criteria.BundleDeploymentCriteria; -import org.rhq.core.domain.criteria.BundleVersionCriteria; -import org.rhq.core.domain.util.PageList;
/** * Local interface to the manager responsible for creating and managing bundles. @@ -55,51 +51,64 @@ public interface BundleManagerLocal extends BundleManagerRemote { // - legacy reasons
/** + * Internal use only + * </p> * Called internally to add history when action is taken against a deployment. This executes * in a New Transaction and supports deployBundle and Agent requests. - * + * </p> + * This method performs NO AUTHZ! + * </p> * @param subject * @param resourceDeploymentId id of the deployment appending the history record * @param history * @return the persisted history */ - BundleResourceDeploymentHistory addBundleResourceDeploymentHistory(Subject subject, int resourceDeploymentId, - BundleResourceDeploymentHistory history) throws Exception; + BundleResourceDeploymentHistory addBundleResourceDeploymentHistoryInNewTrans(Subject subject, + int resourceDeploymentId, BundleResourceDeploymentHistory history) throws Exception;
/** - * Mainly Used For Testing - * + * Internal use only, and test entry point. + * </p> + * This method performs NO AUTHZ! + * </p> * @param subject user that must have proper permissions * @param name not null or empty * @param description optional long description of the bundle * @param bundleTypeId valid bundleType + * @param bundleGroupId bundle group, existing bundle group for bundle assignment, or 0 for unassigned * @return the persisted Bundle (id is assigned) */ - Bundle createBundle(Subject subject, String name, String description, int bundleTypeId) throws Exception; + Bundle createBundle(Subject subject, String name, String description, int bundleTypeId, int bundleGroupId) + throws Exception;
/** - * Mainly Used For Testing + * Internal use only and test entry point. * - * Convienence method that combines {@link #createBundle(Subject, String, int)} and {@link #createBundleVersion(Subject, int, String, String, String)}. + * Convenience method that combines {@link #createBundle(Subject, String, int)} and {@link #createBundleVersion(Subject, int, String, String, String)}. * This will first check to see if a bundle with the given type/name exists - if it doesn't, it will be created. If it does, it will be reused. * This will then create the bundle version that will be associated with the bundle that was created or found. - * + * </p> + * This method performs NO AUTHZ! + * </p> * @param subject user that must have proper permissions * @param bundleName name of the bundle to use (if not found, it will be created) * @param bundleDescription optional long description of the bundle * @param bundleTypeId the bundle type for the new bundle (if it is created) for which this will be the first version + * @param bundleGroupId the bundle group for the new bundle (if it is created) for which this will be the first version. 0 to leave unassigned. * @param bundleVersionName name of the bundle version * @param bundleVersionDescription optional long description of the bundle version * @param version optional. If not supplied set to 1.0 for first version, or incremented (as best as possible) for subsequent version * @return the persisted BundleVersion (id is assigned) */ BundleVersion createBundleAndBundleVersion(Subject subject, String bundleName, String bundleDescription, - int bundleTypeId, String bundleVersionName, String bundleVersionDescription, String version, String recipe) - throws Exception; + int bundleTypeId, int bundleGroupId, String bundleVersionName, String bundleVersionDescription, String version, + String recipe) throws Exception;
/** - * Mainly Used For Testing - * + * Internal use only, test entry point + * </p> + * This method performs NO AUTHZ! + * </p> * @param subject user that must have proper permissions * @param bundleId the bundle for which this will be the next version * @param name not null or empty @@ -112,8 +121,11 @@ public interface BundleManagerLocal extends BundleManagerRemote {
/** * Not generally called. For use by Server Side Plugins when registering a Bundle Plugin. - * - * @param subject must be InventoryManager + * </p> + * Required Permissions: + * - Global.CREATE_BUNDLES + * </p> + * @param subject * @param name not null or empty * @param resourceTypeId id of the ResourceType that handles this BundleType * @return the persisted BundleType (id is assigned) @@ -121,26 +133,50 @@ public interface BundleManagerLocal extends BundleManagerRemote { BundleType createBundleType(Subject subject, String name, int resourceTypeId) throws Exception;
/** - * This is typically not called directly, typically scheduleBundleResourceDeployment() is called externally. This executes - * in a New Transaction and supports scheduleBundleResourceDeployment. + * This is typically not called directly, typically scheduleBundleResourceDeployment() is called externally. + * This executes in a New Transaction and supports scheduleBundleResourceDeployment. + * </p> + * This method performs NO AUTHZ! + * </p> */ - BundleResourceDeployment createBundleResourceDeployment(Subject subject, int bundleDeploymentId, int resourceId) - throws Exception; + BundleResourceDeployment createBundleResourceDeploymentInNewTrans(Subject subject, int bundleDeploymentId, + int resourceId) throws Exception;
/** * Similar to {@link BundleManagerRemote#createBundleDeployment(Subject, int, int, String, Configuration)} but * supplies the internally generated deploymentName and has different transaction semantics. Useful when an * slsb method needs to both create a deployment and schedules it prior to returning to an external caller. + * </p> + * This method performs NO AUTHZ! + * </p> */ public BundleDeployment createBundleDeploymentInNewTrans(Subject subject, int bundleVersionId, int bundleDestinationId, String name, String description, Configuration configuration) throws Exception;
- // added here because the same method in @Remote was commented out to bypass a WSProvide issue + /** + * Used by GUI + * </p> + * Required Permissions: Either: + * - Global.CREATE_BUNDLES and Global.VIEW_BUNDLES + * - Global.CREATE_BUNDLES and BundleGroup.VIEW_BUNDLES_IN_GROUP for bundle group BG and the relevant bundle is assigned to BG + * - BundleGroup.CREATE_BUNDLES_IN_GROUP for bundle group BG and the relevant bundle is assigned to BG + * </p> + * + * @param subject + * @param bundleVersionId + * @return Map, filename to foundInBundleVersion + * @throws Exception + */ HashMap<String, Boolean> getAllBundleVersionFilenames(Subject subject, int bundleVersionId) throws Exception;
/** - * Needed by the Bundle Deploy and Revert wizards GUI to generate a deployment name for display. - * + * Used by GUI. Needed by the Bundle Deploy and Revert wizards GUI to generate a deployment name for display. + * <pre> + * Required Permissions: Either: + * - Global.DEPLOY_BUNDLES and a view of the relevant bundle and a view of the relevant resource group (may involve multiple roles) + * - Resource.DEPLOY_BUNDLES_TO_GROUP and a view of the relevant bundle and a view of the relevant resource group (may involve multiple roles) + * </pre> + * * @param subject * @param bundleDestinationId required * @param bundleVersionId required for progressive deployment, -1 for revert @@ -151,18 +187,26 @@ public interface BundleManagerLocal extends BundleManagerRemote { int prevDeploymentId);
/** - * Not for general consumption. A special case method to build the pojo that can be sent to the agent to + * Internal use only. A special case method to build the pojo that can be sent to the agent to * schedule the deployment request. Uses NOT_SUPPORTED transaction attribute to avoid having the cleaned pojo * affect the persistence context. + * </p> + * This method performs NO AUTHZ! + * </p> + * * @throws Exception */ public BundleScheduleRequest getScheduleRequest(Subject subject, int resourceDeploymentId, boolean isCleanDeployment, boolean isRevert) throws Exception;
/** - * This is a simple attempt at delete, typically used for removing a poorly defined deployment before it is - * actually scheduled for deployment. The status must be PENDING. It will - * fail if anything actually refers to it. + * Used by GUI. This is a simple attempt at delete, typically used for removing a poorly defined deployment before it is + * actually scheduled for deployment. The status must be PENDING. It will fail if anything actually refers to it. + * <pre> + * Required Permissions: Either: + * - Global.DEPLOY_BUNDLES and a view of the relevant bundle and a view of the relevant resource group (may involve multiple roles) + * - Resource.DEPLOY_BUNDLES_TO_GROUP and a view of the relevant bundle and a view of the relevant resource group (may involve multiple roles) + * </pre> * * @param subject * @param bundleDeploymentId @@ -171,8 +215,13 @@ public interface BundleManagerLocal extends BundleManagerRemote { void deleteBundleDeployment(Subject subject, int bundleDeploymentId) throws Exception;
/** - * This is a simple attempt at delete, typically used for removing a poorly defined destination. It will + * Used by GUI. This is a simple attempt at delete, typically used for removing a poorly defined destination. It will * fail if any actual deployments are referring to the destination. + * <pre> + * Required Permissions: Either: + * - Global.DEPLOY_BUNDLES and a view of the relevant bundle and a view of the relevant resource group (may involve multiple roles) + * - Resource.DEPLOY_BUNDLES_TO_GROUP and a view of the relevant bundle and a view of the relevant resource group (may involve multiple roles) + * </pre> * * @param subject * @param bundleDestinationId @@ -181,7 +230,11 @@ public interface BundleManagerLocal extends BundleManagerRemote { void deleteBundleDestination(Subject subject, int bundleDestinationId) throws Exception;
/** - * Called internally to set deployment status. Typically to a completion status when deployment ends. + * Internal use only. Called internally to set deployment status. Typically to a completion status when deployment + * ends. + * </p> + * This method performs NO AUTHZ! + * </p> * * @param subject * @param resourceDeploymentId id of the resource deployment appending the history record @@ -192,9 +245,14 @@ public interface BundleManagerLocal extends BundleManagerRemote { BundleDeploymentStatus status) throws Exception;
/** - * This is for internal use only - when {@link #purgeBundleDestination(Subject, int)} is done, it + * Internal use only + * </p> + * When {@link #purgeBundleDestination(Subject, int)} is done, it * calls this so the purge can be finalized. This is required because this method is called with * a transactional context, as opposed to the main purge method. + * </p> + * This method performs NO AUTHZ! + * </p> * * @param subject * @param bundleDeployment @@ -204,29 +262,4 @@ public interface BundleManagerLocal extends BundleManagerRemote { void _finalizePurge(Subject subject, BundleDeployment bundleDeployment, Map<BundleResourceDeployment, String> failedToPurge) throws Exception;
- /** - * Fetch bundles by criteria and then on the result objects - * @param subject Caller - * @param criteria criteria to fetch the bundles - * @return List of bundles with destinations filtered. - */ - PageList<Bundle> findBundlesByCriteriaWithDestinationFilter(Subject subject, BundleCriteria criteria); - - /** - * Fetch bundle versions by criteria and then filter destination on the result objects to limit what the user can see - * @param subject Caller - * @param criteria criteria to fetch the bundles - * @return List of bundles with destinations filtered. - */ - PageList<BundleVersion> findBundleVersionsByCriteriaWithDestinationFilter(Subject subject, - BundleVersionCriteria criteria); - - /** - * Fetch bundle deployments by criteria and then filter on destinations on the result objects to limit what the user can see - * @param subject Caller - * @param criteria criteria to fetch the deployments - * @return List of deployments with destinations filtered. - */ - PageList<BundleDeployment> findBundleDeploymentsByCriteriaWithDestinationFilter(Subject subject, - BundleDeploymentCriteria criteria); } diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerRemote.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerRemote.java index 5ff63d0..c1b9eef 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerRemote.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleManagerRemote.java @@ -72,12 +72,13 @@ public interface BundleManagerRemote { /** * Adds a BundleFile to the BundleVersion and implicitly creates the backing PackageVersion. If the PackageVersion * already exists use {@link #addBundleFileViaPackageVersion(Subject, int, String, int)} - * </p> + * <pre> * Required Permissions: Either: * - Global.CREATE_BUNDLES and Global.VIEW_BUNDLES * - Global.CREATE_BUNDLES and BundleGroup.VIEW_BUNDLES_IN_GROUP for bundle group BG and the relevant bundle is assigned to BG * - BundleGroup.CREATE_BUNDLES_IN_GROUP for bundle group BG and the relevant bundle is assigned to BG - * + * </pre> + * * @param subject user that must have proper permissions * @param bundleVersionId id of the BundleVersion incorporating this BundleFile * @param name name of the BundleFile (and the resulting Package) @@ -94,12 +95,13 @@ public interface BundleManagerRemote { * A convenience method taking a byte array as opposed to a stream for the file bits. * WARNING: obviously, this requires the entire bundle file to have been loaded fully in memory. * For very large files, this could cause OutOfMemoryErrors. - * </p> + * <pre> * Required Permissions: Either: * - Global.CREATE_BUNDLES and Global.VIEW_BUNDLES * - Global.CREATE_BUNDLES and BundleGroup.VIEW_BUNDLES_IN_GROUP for bundle group BG and the relevant bundle is assigned to BG * - BundleGroup.CREATE_BUNDLES_IN_GROUP for bundle group BG and the relevant bundle is assigned to BG - * + * </pre> + * * @see {@link #addBundleFile(Subject, int, String, String, Architecture, InputStream)} */ BundleFile addBundleFileViaByteArray(Subject subject, int bundleVersionId, String name, String version, @@ -107,12 +109,13 @@ public interface BundleManagerRemote {
/** * A convenience method taking a URL String whose content will be streamed to the server and used for the file bits. - * </p> + * <pre> * Required Permissions: Either: * - Global.CREATE_BUNDLES and Global.VIEW_BUNDLES * - Global.CREATE_BUNDLES and BundleGroup.VIEW_BUNDLES_IN_GROUP for bundle group BG and the relevant bundle is assigned to BG * - BundleGroup.CREATE_BUNDLES_IN_GROUP for bundle group BG and the relevant bundle is assigned to BG - * + * </pre> + * * @see #addBundleFile(Subject, int, String, String, Architecture, InputStream) */ BundleFile addBundleFileViaURL(Subject subject, int bundleVersionId, String name, String version, @@ -121,12 +124,13 @@ public interface BundleManagerRemote { /** * A variant of {@link #addBundleFileViaURL(Subject, int, String, String, Architecture, String)} supporting the * HTTP basic authentication. - * </p> + * <pre> * Required Permissions: Either: * - Global.CREATE_BUNDLES and Global.VIEW_BUNDLES * - Global.CREATE_BUNDLES and BundleGroup.VIEW_BUNDLES_IN_GROUP for bundle group BG and the relevant bundle is assigned to BG * - BundleGroup.CREATE_BUNDLES_IN_GROUP for bundle group BG and the relevant bundle is assigned to BG - * + * </pre> + * * @see #addBundleFileViaURL(Subject, int, String, String, Architecture, String) */ BundleFile addBundleFileViaURL(Subject subject, int bundleVersionId, String name, String version, @@ -134,12 +138,13 @@ public interface BundleManagerRemote {
/** * A convenience method taking an existing PackageVersion as opposed to a stream for the file bits. - * </p> + * <pre> * Required Permissions: Either: * - Global.CREATE_BUNDLES and Global.VIEW_BUNDLES * - Global.CREATE_BUNDLES and BundleGroup.VIEW_BUNDLES_IN_GROUP for bundle group BG and the relevant bundle is assigned to BG * - BundleGroup.CREATE_BUNDLES_IN_GROUP for bundle group BG and the relevant bundle is assigned to BG - * + * </pre> + * * @see {@link #addBundleFile(Subject, int, String, String, Architecture, InputStream)} */ BundleFile addBundleFileViaPackageVersion(Subject subject, int bundleVersionId, String name, int packageVersionId) @@ -147,11 +152,12 @@ public interface BundleManagerRemote {
/** * Assign the specified bundles to the specified bundle group. - * </p> + * <pre> * Requires VIEW permission for the relevant bundle and either: * - Global.CREATE_BUNDLE * - BundleGroup.CREATE_BUNDLES_IN_GROUP or BundleGroup.ASSIGN_BUNDLES_TO_GROUP for the relevant bundle group - * + * </pre> + * * @param subject * @param bundleGroupId * @param bundleIds @@ -163,11 +169,12 @@ public interface BundleManagerRemote { * call. This provides useful, uniform naming for display. An optional, custom description * can be added. This call defines a deployment. The defined deployment can then be * scheduled in a separate call. - * </p> + * <pre> * Required Permissions: Either: * - Global.DEPLOY_BUNDLES and a view of the relevant bundle and a view of the relevant resource group (may involve multiple roles) * - Resource.DEPLOY_BUNDLES_TO_GROUP and a view of the relevant bundle and a view of the relevant resource group (may involve multiple roles) - * + * </pre> + * * @param subject user that must have proper permissions * @param bundleVersionId the BundleVersion being deployed by this deployment * @param bundleDestinationId the BundleDestination for the deployment @@ -182,11 +189,12 @@ public interface BundleManagerRemote {
/** * Creates a bundle destination that describes a target for the bundle deployments. - * </p> + * <pre> * Required Permissions: Either: * - Global.DEPLOY_BUNDLES and a view of the relevant bundle and a view of the relevant resource group (may involve multiple roles) * - Resource.DEPLOY_BUNDLES_TO_GROUP and a view of the relevant bundle and a view of the relevant resource group (may involve multiple roles) - * + * </pre> + * * @param subject user must have MANAGE_INVENTORY permission * @param bundleId the Bundle to be deployed to this Destination * @param name a name for this destination. not null or empty @@ -225,12 +233,13 @@ public interface BundleManagerRemote { * </p> * If this bundle version is the initial version of a new bundle that needs to be created, the subject must * have Global.VIEW_BUNDLES because the new bundle will not be associated with any bundle group. - * </p> + * <pre> * Required Permissions: Either: * - Global.CREATE_BUNDLES and Global.VIEW_BUNDLES * - Global.CREATE_BUNDLES and BundleGroup.VIEW_BUNDLES_IN_GROUP for bundle group BG and the relevant bundle is assigned to BG * - BundleGroup.CREATE_BUNDLES_IN_GROUP for bundle group BG and the relevant bundle is assigned to BG - * + * </pre> + * * @param subject user that must have proper permissions * @param recipe the recipe that defines the bundle version to be created * @return the persisted BundleVersion with alot of the internal relationships filled in to help the caller @@ -244,19 +253,21 @@ public interface BundleManagerRemote { * should be assigned to. * If bundleGroupId is 0, then the new bundle will not be associated with any bundle group - this is only * allowed if the caller has the permission Global.VIEW_BUNDLES. - * </p> + * <pre> * Required Permissions: Either: * - Global.CREATE_BUNDLES and Global.VIEW_BUNDLES * - Global.CREATE_BUNDLES and BundleGroup.VIEW_BUNDLES_IN_GROUP for bundle group BG * - BundleGroup.CREATE_BUNDLES_IN_GROUP for bundle group BG - * + * </pre> + * * @param subject user that must have proper permissions * @param bundleGroupId identifies the bundle group that the new bundle will be associated with; 0 if no group * @param recipe the recipe that defines the bundle version to be created * @return the persisted BundleVersion with alot of the internal relationships filled in to help the caller * understand all that this method did. */ - BundleVersion createInitialBundleVersionViaRecipe(Subject subject, int bundleGroupId, String recipe) throws Exception; + BundleVersion createInitialBundleVersionViaRecipe(Subject subject, int bundleGroupId, String recipe) + throws Exception;
/** * Creates a bundle version based on a Bundle Distribution file. Typically a zip file, the bundle distribution @@ -267,12 +278,13 @@ public interface BundleManagerRemote { * </p> * If this bundle version is the initial version of a new bundle that needs to be created, the subject must * have Global.VIEW_BUNDLES because the new bundle will not be associated with any bundle group. - * </p> + * <pre> * Required Permissions: Either: * - Global.CREATE_BUNDLES and Global.VIEW_BUNDLES * - Global.CREATE_BUNDLES and BundleGroup.VIEW_BUNDLES_IN_GROUP for bundle group BG and the relevant bundle is assigned to BG * - BundleGroup.CREATE_BUNDLES_IN_GROUP for bundle group BG and the relevant bundle is assigned to BG - * + * </pre> + * * @param subject user that must have proper permissions * @param distributionFile a local Bundle Distribution file. It must be read accessible by the RHQ server process. * @return the persisted BundleVersion with alot of the internal relationships filled in to help the caller @@ -286,12 +298,13 @@ public interface BundleManagerRemote { * should be assigned to. * If bundleGroupId is 0, then the new bundle will not be associated with any bundle group - this is only * allowed if the caller has the permission Global.VIEW_BUNDLES. - * </p> + * <pre> * Required Permissions: Either: * - Global.CREATE_BUNDLES and Global.VIEW_BUNDLES * - Global.CREATE_BUNDLES and BundleGroup.VIEW_BUNDLES_IN_GROUP for bundle group BG * - BundleGroup.CREATE_BUNDLES_IN_GROUP for bundle group BG - * + * </pre> + * * @param subject user that must have proper permissions * @param bundleGroupId identifies the bundle group that the new bundle will be associated with; 0 if no group * @param distributionFile a local Bundle Distribution file. It must be read accessible by the RHQ server process. @@ -299,7 +312,8 @@ public interface BundleManagerRemote { * understand all that this method did. Bundle files specifically are returned. * @throws Exception */ - BundleVersion createInitialBundleVersionViaFile(Subject subject, int bundleGroupId, File distributionFile) throws Exception; + BundleVersion createInitialBundleVersionViaFile(Subject subject, int bundleGroupId, File distributionFile) + throws Exception;
/** * Creates a bundle version based on the actual bytes of a Bundle Distribution file. This is essentially @@ -310,12 +324,13 @@ public interface BundleManagerRemote { * </p> * If this bundle version is the initial version of a new bundle that needs to be created, the subject must * have Global.VIEW_BUNDLES because the new bundle will not be associated with any bundle group. - * </p> + * <pre> * Required Permissions: Either: * - Global.CREATE_BUNDLES and Global.VIEW_BUNDLES * - Global.CREATE_BUNDLES and BundleGroup.VIEW_BUNDLES_IN_GROUP for bundle group BG and the relevant bundle is assigned to BG * - BundleGroup.CREATE_BUNDLES_IN_GROUP for bundle group BG and the relevant bundle is assigned to BG - * + * </pre> + * * @param subject user that must have proper permissions * @param fileBytes the file bits that make up the entire bundle distribution file * @return the persisted BundleVersion with a lot of the internal relationships filled in to help the caller @@ -329,12 +344,13 @@ public interface BundleManagerRemote { * should be assigned to. * If bundleGroupId is 0, then the new bundle will not be associated with any bundle group - this is only * allowed if the caller has the permission Global.VIEW_BUNDLES. - * </p> + * <pre> * Required Permissions: Either: * - Global.CREATE_BUNDLES and Global.VIEW_BUNDLES * - Global.CREATE_BUNDLES and BundleGroup.VIEW_BUNDLES_IN_GROUP for bundle group BG * - BundleGroup.CREATE_BUNDLES_IN_GROUP for bundle group BG - * + * </pre> + * * @param subject user that must have proper permissions * @param bundleGroupId identifies the bundle group that the new bundle will be associated with; 0 if no group * @param fileBytes the file bits that make up the entire bundle distribution file @@ -342,7 +358,8 @@ public interface BundleManagerRemote { * understand all that this method did. Bundle files specifically are returned. * @throws Exception */ - BundleVersion createInitialBundleVersionViaByteArray(Subject subject, int bundleGroupId, byte[] fileBytes) throws Exception; + BundleVersion createInitialBundleVersionViaByteArray(Subject subject, int bundleGroupId, byte[] fileBytes) + throws Exception;
/** * Creates a bundle version based on a Bundle Distribution file. Typically a zip file, the bundle distribution @@ -355,12 +372,13 @@ public interface BundleManagerRemote { * </p> * If this bundle version is the initial version of a new bundle that needs to be created, the subject must * have Global.VIEW_BUNDLES because the new bundle will not be associated with any bundle group. - * </p> + * <pre> * Required Permissions: Either: * - Global.CREATE_BUNDLES and Global.VIEW_BUNDLES * - Global.CREATE_BUNDLES and BundleGroup.VIEW_BUNDLES_IN_GROUP for bundle group BG and the relevant bundle is assigned to BG * - BundleGroup.CREATE_BUNDLES_IN_GROUP for bundle group BG and the relevant bundle is assigned to BG - * + * </pre> + * * @param subject user that must have proper permissions * @param distributionFileUrl a URL String to the Bundle Distribution file. It must be live, resolvable and read accessible * by the RHQ server process. @@ -376,12 +394,13 @@ public interface BundleManagerRemote { * should be assigned to. * If bundleGroupId is 0, then the new bundle will not be associated with any bundle group - this is only * allowed if the caller has the permission Global.VIEW_BUNDLES. - * </p> + * <pre> * Required Permissions: Either: * - Global.CREATE_BUNDLES and Global.VIEW_BUNDLES * - Global.CREATE_BUNDLES and BundleGroup.VIEW_BUNDLES_IN_GROUP for bundle group BG * - BundleGroup.CREATE_BUNDLES_IN_GROUP for bundle group BG - * + * </pre> + * * @param subject user that must have proper permissions * @param bundleGroupId identifies the bundle group that the new bundle will be associated with; 0 if no group * @param distributionFileUrl a URL String to the Bundle Distribution file. It must be live, resolvable and read accessible @@ -390,7 +409,8 @@ public interface BundleManagerRemote { * understand all that this method did. Bundle files specifically are returned. * @throws Exception */ - BundleVersion createInitialBundleVersionViaURL(Subject subject, int bundleGroupId, String distributionFileUrl) throws Exception; + BundleVersion createInitialBundleVersionViaURL(Subject subject, int bundleGroupId, String distributionFileUrl) + throws Exception;
/** * A version of the {@link #createBundleVersionViaURL(org.rhq.core.domain.auth.Subject, String)} that accepts a @@ -398,12 +418,13 @@ public interface BundleManagerRemote { * </p> * If this bundle version is the initial version of a new bundle that needs to be created, the subject must * have Global.VIEW_BUNDLES because the new bundle will not be associated with any bundle group. - * </p> + * <pre> * Required Permissions: Either: * - Global.CREATE_BUNDLES and Global.VIEW_BUNDLES * - Global.CREATE_BUNDLES and BundleGroup.VIEW_BUNDLES_IN_GROUP for bundle group BG and the relevant bundle is assigned to BG * - BundleGroup.CREATE_BUNDLES_IN_GROUP for bundle group BG and the relevant bundle is assigned to BG - * + * </pre> + * * @see #createBundleVersionViaURL(org.rhq.core.domain.auth.Subject, String) */ BundleVersion createBundleVersionViaURL(Subject subject, String distributionFileUrl, String username, @@ -415,27 +436,30 @@ public interface BundleManagerRemote { * should be assigned to. * If bundleGroupId is 0, then the new bundle will not be associated with any bundle group - this is only * allowed if the caller has the permission Global.VIEW_BUNDLES. - * </p> + * <pre> * Required Permissions: Either: * - Global.CREATE_BUNDLES and Global.VIEW_BUNDLES * - Global.CREATE_BUNDLES and BundleGroup.VIEW_BUNDLES_IN_GROUP for bundle group BG * - BundleGroup.CREATE_BUNDLES_IN_GROUP for bundle group BG - * + * </pre> + * * @see #createBundleVersionViaURL(org.rhq.core.domain.auth.Subject, String) */ - BundleVersion createInitialBundleVersionViaURL(Subject subject, int bundleGroupId, String distributionFileUrl, String username, String password) throws Exception; + BundleVersion createInitialBundleVersionViaURL(Subject subject, int bundleGroupId, String distributionFileUrl, + String username, String password) throws Exception;
/** * Remove everything associated with the Bundles with the exception of files laid down by related deployments. * Deployed files are left as is on the deployment platforms but the bundle mechanism will no longer track * the deployment of all bundles that have been deleted. * The bundles that are deleted will be removed from all bundle groups that it was a member of. - * </p> + * <pre> * Required Permissions: Either: * - Global.DELETE_BUNDLES and Global.VIEW_BUNDLES * - Global.DELETE_BUNDLES and BundleGroup.VIEW_BUNDLES_IN_GROUP for bundle group BG and the relevant bundle is assigned to BG * - BundleGroup.DELETE_BUNDLES_FROM_GROUP for bundle group BG and the relevant bundle is assigned to BG - * + * </pre> + * * @param subject user that must have proper permissions * @param bundleIds IDs of all bundles to be deleted * @throws Exception if any part of the removal fails. @@ -447,12 +471,13 @@ public interface BundleManagerRemote { * Deployed files are left as is on the deployment platforms but the bundle mechanism will no longer track * the deployment. * The bundles that are deleted will be removed from all bundle groups that it was a member of. - * </p> + * <pre> * Required Permissions: Either: * - Global.DELETE_BUNDLES and Global.VIEW_BUNDLES * - Global.DELETE_BUNDLES and BundleGroup.VIEW_BUNDLES_IN_GROUP for bundle group BG and the relevant bundle is assigned to BG * - BundleGroup.DELETE_BUNDLES_FROM_GROUP for bundle group BG and the relevant bundle is assigned to BG - * + * </pre> + * * @param subject user that must have proper permissions * @param bundleId the id of the bundle to remove * @throws Exception if any part of the removal fails. @@ -476,12 +501,13 @@ public interface BundleManagerRemote { * Deployed files are left as is on the deployment platforms but the bundle mechanism will no longer track * the deployment. * The deleted bundle version will no longer exist in any bundle group. - * </p> + * <pre> * Required Permissions: Either: * - Global.DELETE_BUNDLES and Global.VIEW_BUNDLES * - Global.DELETE_BUNDLES and BundleGroup.VIEW_BUNDLES_IN_GROUP for bundle group BG and the relevant bundle is assigned to BG * - BundleGroup.DELETE_BUNDLES_FROM_GROUP for bundle group BG and the relevant bundle is assigned to BG - * + * </pre> + * * @param subject user that must have proper permissions * @param bundleVersionId the id of the bundle version to remove * @param deleteBundleIfEmpty if <code>true</code> and if this method deletes the last bundle version for its @@ -490,14 +516,40 @@ public interface BundleManagerRemote { */ void deleteBundleVersion(Subject subject, int bundleVersionId, boolean deleteBundleIfEmpty) throws Exception;
+ /** + * Return the <code>Bundles</code> narrowed by the supplied Criteria. The results are implicitly + * narrowed to those bundles viewable by the <code>subject</code>. + */ PageList<Bundle> findBundlesByCriteria(Subject subject, BundleCriteria criteria);
+ /** + * Return the <code>BundleGroups</code> narrowed by the supplied Criteria. The results are implicitly + * narrowed to those bundle groups viewable by the <code>subject</code>. + */ PageList<BundleGroup> findBundleGroupsByCriteria(Subject subject, BundleGroupCriteria criteria);
+ /** + * Return the <code>BundleDeployments</code> narrowed by the supplied Criteria. The results are implicitly + * narrowed to those for bundles and destination groups viewable by the <code>subject</code>. + */ PageList<BundleDeployment> findBundleDeploymentsByCriteria(Subject subject, BundleDeploymentCriteria criteria);
+ /** + * Return the <code>BundleDestinations</code> narrowed by the supplied Criteria. The results are implicitly + * narrowed to those with destination resource groups viewable by the <code>subject</code>. + */ PageList<BundleDestination> findBundleDestinationsByCriteria(Subject subject, BundleDestinationCriteria criteria);
+ /** + * Note that this can involves permissions on bundles and resources. Results will always be narrowed to the bundles + * viewable by <code>subject</code>. If optionally requesting the relevant Resources + * via <code>BundleResourceDeploymentCriteria.fetchResources(true)</code> the results will be further narrowed to + * the viewable resources. + * + * @param subject + * @param criteria + * @return + */ PageList<BundleResourceDeployment> findBundleResourceDeploymentsByCriteria(Subject subject, BundleResourceDeploymentCriteria criteria);
@@ -516,12 +568,13 @@ public interface BundleManagerRemote { * Determine the files required for a BundleVersion and return all of the filenames or optionally, just those * that lack BundleFiles for the BundleVersion. The recipe may be parsed as part of this call. * This is needed as part of the bundle creation workflow, hence why creation permissions are needed. - * </p> + * <pre> * Required Permissions: Either: * - Global.CREATE_BUNDLES and Global.VIEW_BUNDLES * - Global.CREATE_BUNDLES and BundleGroup.VIEW_BUNDLES_IN_GROUP for bundle group BG and the relevant bundle is assigned to BG * - BundleGroup.CREATE_BUNDLES_IN_GROUP for bundle group BG and the relevant bundle is assigned to BG - * + * </pre> + * * @param subject user that must have proper permissions * @param bundleVersionId the BundleVersion being queried * @param withoutBundleFileOnly if true omit any filenames that already have a corresponding BundleFile for @@ -534,7 +587,7 @@ public interface BundleManagerRemote {
/** * Purges the destination's live deployment content from the remote platforms. - * </p> + * </pre> * Required Permissions: Either: * - Global.DEPLOY_BUNDLES and a view of the relevant bundle and a view of the relevant resource group (may involve multiple roles) * - Resource.DEPLOY_BUNDLES_TO_GROUP and a view of the relevant bundle and a view of the relevant resource group (may involve multiple roles) @@ -550,7 +603,7 @@ public interface BundleManagerRemote { * complete. The returned BundleDeployment can be used to track the history of the individual deployments. * <br/><br/> * TODO: Add the scheduling capability, currently it's Immediate. - * </p> + * </pre> * Required Permissions: Either: * - Global.DEPLOY_BUNDLES and a view of the relevant bundle and a view of the relevant resource group (may involve multiple roles) * - Resource.DEPLOY_BUNDLES_TO_GROUP and a view of the relevant bundle and a view of the relevant resource group (may involve multiple roles) @@ -574,7 +627,7 @@ public interface BundleManagerRemote { * call. This provides useful, uniform naming for display. An optional, custom description can be added. * <br/><br/> * TODO: Add the scheduling capability, currently it's Immediate. - * </p> + * </pre> * Required Permissions: Either: * - Global.DEPLOY_BUNDLES and a view of the relevant bundle and a view of the relevant resource group (may involve multiple roles) * - Resource.DEPLOY_BUNDLES_TO_GROUP and a view of the relevant bundle and a view of the relevant resource group (may involve multiple roles) @@ -592,7 +645,7 @@ public interface BundleManagerRemote {
/** * Unassign the specified bundles from the specified bundle group. - * </p> + * </pre> * Requires VIEW permission for the relevant bundles and either: * - Global.DELETE_BUNDLE * - BundleGroup.DELETE_BUNDLES_FROM_GROUP or BundleGroup.UNASSIGN_BUNDLES_FROM_GROUP for the relevant bundle group diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleServerServiceImpl.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleServerServiceImpl.java index a78d7e9..4e73171 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleServerServiceImpl.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/bundle/BundleServerServiceImpl.java @@ -56,7 +56,7 @@ public class BundleServerServiceImpl implements BundleServerService { public void addDeploymentHistory(int bundleDeploymentId, BundleResourceDeploymentHistory history) { try { BundleManagerLocal bm = LookupUtil.getBundleManager(); - bm.addBundleResourceDeploymentHistory(LookupUtil.getSubjectManager().getOverlord(), bundleDeploymentId, + bm.addBundleResourceDeploymentHistoryInNewTrans(LookupUtil.getSubjectManager().getOverlord(), bundleDeploymentId, history); } catch (Exception e) { log.error("Failed to add history to deployment id: " + bundleDeploymentId, e); diff --git a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java index e65d9f3..0a1060d 100644 --- a/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java +++ b/modules/enterprise/server/jar/src/main/java/org/rhq/enterprise/server/util/CriteriaQueryGenerator.java @@ -69,7 +69,8 @@ public final class CriteriaQueryGenerator { public enum AuthorizationTokenType { RESOURCE, // specifies the resource alias to join on for standard res-group-role-subject authorization checking GROUP, // specifies the group alias to join on for standard group-role-subject authorization checking - BUNDLE; // specifies the bundle alias to join on for standard bundle-bundleGroup-role-subject authorization checking + BUNDLE, // specifies the bundle alias to join on for standard bundle-bundleGroup-role-subject authorization checking + BUNDLE_GROUP; // specifies the bundle group alias to join on for standard bundleGroup-role-subject authorization checking }
private Criteria criteria; @@ -125,6 +126,8 @@ public final class CriteriaQueryGenerator { setAuthorizationResourceFragment(type, defaultFragment, subjectId); } else if (type == AuthorizationTokenType.BUNDLE) { setAuthorizationBundleFragment(subjectId); + } else if (type == AuthorizationTokenType.BUNDLE_GROUP) { + setAuthorizationBundleGroupFragment(subjectId); } }
@@ -249,6 +252,39 @@ public final class CriteriaQueryGenerator { customAuthzFragment = customAuthzFragment.replace("%aliasWithFragment%", aliasReplacement); customAuthzFragment = customAuthzFragment.replace("%innerAlias%", innerAliasReplacement); customAuthzFragment = customAuthzFragment.replace("%subjectId%", String.valueOf(subjectId)); + this.authorizationCustomConditionFragment = customAuthzFragment; + + // If the query results are narrowed by requiredPerms generate the fragment now. It's done + // here for two reasons. First, it seems to make sense to apply this only when an authFragment is + // being used. Second, because one day the query may be less brute force and may modify or + // leverage the joinFragment above. But, after extensive trying a more elegant + // query could not be constructed due to Hibernate limitations. So, for now, here it is... + List<Permission> requiredPerms = this.criteria.getRequiredPermissions(); + if (!(null == requiredPerms || requiredPerms.isEmpty())) { + this.authorizationPermsFragment = "" // + + "( SELECT COUNT(DISTINCT p)" + NL // + + " FROM Subject innerSubject" + NL // + + " JOIN innerSubject.roles r" + NL // + + " JOIN r.permissions p" + NL // + + " WHERE innerSubject.id = " + this.authorizationSubjectId + NL // + + " AND p IN ( :requiredPerms ) ) = :requiredPermsSize" + NL; + } + } + + public void setAuthorizationBundleGroupFragment(int subjectId) { + String fragment = "bundleGroup"; + String customAuthzFragment = "" // + + "( %aliasWithFragment%.id IN ( SELECT %innerAlias%.id " + NL // + + " FROM %alias% innerAlias " + NL // + + " JOIN %innerAlias%.roles r JOIN r.subjects s " + NL // + + " WHERE s.id = %subjectId% ) ) " + NL; + String aliasReplacement = criteria.getAlias() + (fragment != null ? "." + fragment : ""); + String innerAliasReplacement = "innerAlias" + (fragment != null ? "." + fragment : ""); + customAuthzFragment = customAuthzFragment.replace("%alias%", criteria.getAlias()); + customAuthzFragment = customAuthzFragment.replace("%aliasWithFragment%", aliasReplacement); + customAuthzFragment = customAuthzFragment.replace("%innerAlias%", innerAliasReplacement); + customAuthzFragment = customAuthzFragment.replace("%subjectId%", String.valueOf(subjectId)); + this.authorizationCustomConditionFragment = customAuthzFragment;
// If the query results are narrowed by requiredPerms generate the fragment now. It's done // here for two reasons. First, it seems to make sense to apply this only when an authFragment is @@ -724,9 +760,9 @@ public final class CriteriaQueryGenerator { private void addPersistentBag(String fieldName) { Field f = findField(fieldName); if (f == null) { - LOG.warn( - "Failed to add persistent bag collection [" + fieldName + "] on class [" + criteria.getPersistentClass().getName() + - "]. There doesn't seem to be a field of that name on the class or any of its superclasses."); + LOG.warn("Failed to add persistent bag collection [" + fieldName + "] on class [" + + criteria.getPersistentClass().getName() + + "]. There doesn't seem to be a field of that name on the class or any of its superclasses."); } else { persistentBagFields.add(f); } @@ -735,9 +771,9 @@ public final class CriteriaQueryGenerator { private void addJoinFetch(String fieldName) { Field f = findField(fieldName); if (f == null) { - LOG.warn( - "Failed to add join fetch field [" + fieldName + "] on class [" + criteria.getPersistentClass().getName() + - "]. There doesn't seem to be a field of that name on the class or any of its superclasses."); + LOG.warn("Failed to add join fetch field [" + fieldName + "] on class [" + + criteria.getPersistentClass().getName() + + "]. There doesn't seem to be a field of that name on the class or any of its superclasses."); } else { joinFetchFields.add(f); }