BusinessObjects Board

Running Statistics on an SAP BI 4.2 SP7 Environment

Does anyone know how to run statistics on an 4.2 SP7 installation? Ideally mainly for CMC/security but also for the entire installation would be good to know as well. I know 365 can do this, but do not have a 3rd party software tool.

What kind of statistics?

User Groups, users, folders, security. Ideally also server settings, servers used, etc. Anything and everything would be awesom!

The BI Support Tool may provide some of the info you are looking for. You can also use the CMS universe to write custom reports.

3 Likes

dtolly, thank you so much! That was extremely helpful. The new goal is to try and obtain just the user groups and the corresponding access to reports/universes/etc. Is there a way to show the security at a user level?

You can query users and groups. You may be able to get to the security at the user or group level, but it would probably be pretty ugly to get at.

May be easier to use the Create Security Query in the CMC. You can create queries at the user or group level and find specific permissions or all. Right click on the object to query, Tools, Create Security Query.

Hi Dtolley,

Thank you for that response, but I think that will only allow you to do that per user or group. Is there a way to do that in bulk?

You’ll have to write your own custom queries or code. You’ll have to account for users, groups, access levels, inherited permissions, etc.

You could also try the Security Analyzer in the BI Platform Support Tool. Even it isn’t going to give you everything at one time, but you can export the results.

It’s also not difficult to get this information using the BI Platform Java SDK. I have a program that does this and spits the information out to .csv files. I might be able to share some sample code if you’re interested.

-Dell

You’re pulling folder and object level security using the SDK? Wow! The way permissions are applied and inherited at so many levels – folder, object, access levels, groups, users, etc, plus the inheritance rules of explicit, not specified, and denied permissions… you are a much braver soul than me! Can’t imagine dealing with all those twists and turns and loops!!!

Hi hilfy,

Yes I am interested :slight_smile:

Sorry it has taken me so long to respond!

Part of the trick to configuring security so that it’s easier to extract is to follow the best practice of assigning user groups (not users!) access to objects.

Here’s the baseInfo class that I use for loading IInfoObjects in my code. This includes the code for loading security. I subclass this for the various types of objects (reports, universes, users, etc.) that I load in this program.

package com.boetools.CMSInfo;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;

import com.crystaldecisions.sdk.exception.SDKException;
import com.crystaldecisions.sdk.occa.infostore.IEffectivePrincipal;
import com.crystaldecisions.sdk.occa.infostore.IEffectivePrincipals;
import com.crystaldecisions.sdk.occa.infostore.IExplicitPrincipal;
import com.crystaldecisions.sdk.occa.infostore.IExplicitPrincipals;
import com.crystaldecisions.sdk.occa.infostore.IInfoObject;
import com.crystaldecisions.sdk.occa.infostore.ISecurityInfo2;

public class baseInfo {
	protected Integer id = -1;
	protected Integer parentId = -1;
	protected String title = "";
	protected String kind = "";
	protected String cuid = "";
	protected ArrayList<SecurityInfo> security = new ArrayList<SecurityInfo>();
	protected boolean hasAdvancedSec = false;
	protected String folder = "";
	protected String parentCuid = "";
	protected Integer ownerId = -1;
	protected String owner = "";

	public baseInfo() {
		id = -1;
		parentId = -1;
		title = "";
		kind = "";
		cuid = "";
	}

	public baseInfo(final IInfoObject iobj) throws SDKException {
		id = iobj.getID();
		parentId = iobj.getParentID();
		title = iobj.getTitle();
		kind = iobj.getKind();
		cuid = iobj.getCUID();
		parentCuid = iobj.getParentCUID();
		ownerId = iobj.getOwnerID();
		owner = iobj.getOwner();
	}

	public String getCUID() {
		return cuid;
	}

	public String getFolder() {
		return folder;
	}

	public Integer getId() {
		return id;
	}

	public String getKind() {
		return kind;
	}
	
	public String getOwner() {
	  return owner;
	}
	
	public Integer getOwnerId() {
	  return ownerId;
	}

	public String getParentCuid() {
		return parentCuid;
	}

	public Integer getParentId() {
		return parentId;
	}

	public ArrayList<SecurityInfo> getSecurity() {
		return security;
	}

	public String getTitle() {
		return title;
	}

	public boolean hasAdvancedRights() {
		return hasAdvancedSec;
	}

	@SuppressWarnings("unchecked")
	protected void loadSecurity(final IInfoObject o, final HashMap<Integer, AccessLevel> accessLevels,
			final boolean doAdvanced, final boolean doEffective) throws SDKException {
		final ISecurityInfo2 si2 = o.getSecurityInfo2();
		final IExplicitPrincipals ieps = si2.getExplicitPrincipals();
		final Iterator<IExplicitPrincipal> expit = ieps.iterator();
		while (expit.hasNext()) {
			final IExplicitPrincipal iep = expit.next();
			if (iep != null) {
				final SecurityInfo si = new SecurityInfo(iep, accessLevels, doAdvanced);
				hasAdvancedSec = hasAdvancedSec || si.hasAdvancedRights();
				security.add(si);
			}
		}

		if (doEffective) {
			final IEffectivePrincipals eps = si2.getEffectivePrincipals();
			final Iterator<IEffectivePrincipal> effit = eps.iterator();
			while (effit.hasNext()) {
				final IEffectivePrincipal ep = effit.next();
				if (ep != null) {
					final SecurityInfo si = new SecurityInfo(ep, accessLevels, doAdvanced);
					hasAdvancedSec = hasAdvancedSec || si.hasAdvancedRights();
					security.add(si);
				}
			}
		}
	}
}

And here’s the SecurityInfo class that I use for loading/storing security info:

package com.boetools.CMSInfo;

import java.util.HashMap;
import java.util.Iterator;

import com.crystaldecisions.sdk.occa.infostore.IEffectivePrincipal;
import com.crystaldecisions.sdk.occa.infostore.IEffectiveRight;
import com.crystaldecisions.sdk.occa.infostore.IEffectiveRights;
import com.crystaldecisions.sdk.occa.infostore.IEffectiveRole;
import com.crystaldecisions.sdk.occa.infostore.IEffectiveRoles;
import com.crystaldecisions.sdk.occa.infostore.IExplicitPrincipal;
import com.crystaldecisions.sdk.occa.infostore.IExplicitRight;
import com.crystaldecisions.sdk.occa.infostore.IExplicitRights;
import com.crystaldecisions.sdk.occa.infostore.IExplicitRole;
import com.crystaldecisions.sdk.occa.infostore.IExplicitRoles;

public class SecurityInfo extends baseInfo {
	private boolean inheritGroups = false;
	private boolean inheritFolders = false;
	private final HashMap<Integer, RoleInfo> roles = new HashMap<Integer, RoleInfo>();
	private final RightsList advRights = new RightsList();
	private boolean isEffective = false;

	@SuppressWarnings("unchecked")
	public SecurityInfo(final IEffectivePrincipal iep, final HashMap<Integer, AccessLevel> accessLevels,
			final boolean doAdvanced) {
		id = iep.getID();
		title = iep.getName();
		inheritGroups = iep.isInheritGroups();
		inheritFolders = iep.isInheritFolders();
		isEffective = true;

		// load the list of roles
		final IEffectiveRoles eRoles = iep.getRoles();
		IEffectiveRole eRole;
		final Iterator<IEffectiveRole> eit = eRoles.iterator();
		AccessLevel level;
		final RightsList roleRights = new RightsList();
		while (eit.hasNext()) {
			eRole = eit.next();
			if ((eRole != null) && !roles.containsKey(eRole.getID())) {
				roles.put(eRole.getID(), new RoleInfo(eRole));
				if (doAdvanced && accessLevels.containsKey(eRole.getID())) {
					level = accessLevels.get(eRole.getID());
					for (final AccessRight ar : level.getRights().list()) {
						if (!roleRights.contains(ar.getApplication(), ar.getRightName())) {
							roleRights.add(ar);
						}
					}
				}
			}
		}

		// if we have advanced rights, get them
		if (iep.isAdvanced()) {
			final IEffectiveRights eRights = iep.getRights();
			final Iterator<IEffectiveRight> rightIt = eRights.iterator();
			IEffectiveRight eRight;
			while (rightIt.hasNext()) {
				eRight = rightIt.next();
				if (!roleRights.contains(eRight.getApplicableKind(), eRight.getDescription(null))) {
					if (advRights.contains(eRight.getApplicableKind(), eRight.getDescription(null))) {
						advRights.get(eRight.getApplicableKind(), eRight.getDescription(null)).updateScope(eRight.getScope());
					} else {
						advRights.add(new AccessRight(eRight));
					}
				}
			}
		}

	}

	@SuppressWarnings("unchecked")
	public SecurityInfo(final IExplicitPrincipal iep, final HashMap<Integer, AccessLevel> accessLevels,
			final boolean doAdvanced) {
		id = iep.getID();
		title = iep.getName();
		inheritGroups = iep.isInheritGroups();
		inheritFolders = iep.isInheritFolders();

		// get the list of access levels assigned and store their rights so that
		// we can check for advanced rights too.
		final IExplicitRoles eRoles = iep.getRoles();
		IExplicitRole eRole;
		AccessLevel level;
		final RightsList roleRights = new RightsList();
		final Iterator<IExplicitRole> eit = eRoles.iterator();
		while (eit.hasNext()) {
			eRole = eit.next();
			roles.put(eRole.getID(), new RoleInfo(eRole));
			if (doAdvanced && accessLevels.containsKey(eRole.getID())) {
				level = accessLevels.get(eRole.getID());
				for (final AccessRight ar : level.getRights().list()) {
					roleRights.add(ar);
				}
			}
		}

		// now walk through the list of rights and add anything that's not
		// already in an assigned access level
		final IExplicitRights eRights = iep.getRights();
		final Iterator<IExplicitRight> rightIt = eRights.iterator();
		IExplicitRight eRight;
		while (rightIt.hasNext()) {
			eRight = rightIt.next();
			if (!roleRights.contains(eRight.getRightPluginKind(), eRight.getDescription(null))) {
				if (advRights.contains(eRight.getRightPluginKind(), eRight.getDescription(null))) {
					advRights.get(eRight.getRightPluginKind(), eRight.getDescription(null))
							.updateScope(eRight.getScope());
				} else {
					advRights.add(new AccessRight(eRight));
				}
			}
		}
		if (advRights.size() > 0) {
			roles.put(0, new RoleInfo(0, "Advanced", false));
		} else if ((advRights.size() == 0) && (roles.size() == 0)) {
			roles.put(-1, new RoleInfo(-1, "No Access", false));
		}
	}

	public RightsList getAdvancedRights() {
		return advRights;
	}

	public boolean getInheritFolders() {
		return inheritFolders;
	}

	public boolean getInheritGroups() {
		return inheritGroups;
	}

	public HashMap<Integer, RoleInfo> getRoles() {
		return roles;
	}

	public boolean hasAdvancedRights() {
		return (advRights.size() > 0);
	}

	public boolean isEffectiveRights() {
		return isEffective;
	}
}

Basically, my program walks through folders, using recursion, to load various types of objects - reports and other files from public and favorites folders, connections, universes, etc. It has a flag for whether or not to load security and, if loading security, another flag that indicates whether to load just explicit rights or to include effective (inherited) rights. As it loads the information, each IInfoObject and its associated security is stored in an List or HashMap for that type of object. Once each object type (or each folder, when walking the public or favorites folder tree) has been loaded, the list of objects is spit out to a pair of .csv files - one has the basic information about the objects, including which users or groups have access levels assigned for the object, and the other has the “advanced security” with minimal info about the objects along with which users or groups have been assigned individual rights that are not part of an access level.

Hopefully this can get you started.

-Dell