VMware {code} Community
Alex_Maxwell
Contributor
Contributor

(.NET SDK) Query service returns operation denied unless user is a system admin

I am trying to get a list of vapps owned by a user. I'm logging in with an Organization Admin user. If I use a system admin, it works fine.  VCD: 5.5.2.2000523, vcloud .NET SDK 5.5.0.0

Sample:

public bool GetVAppsForUser(string username) {

            bool hadError = false;

            client.Login("OrgAdmin", "Password");  // client is of type vCloudClient

            VcloudAdminExtension adminExtension = client.GetVcloudAdminExtension();

            ExtensionQueryService queryService = adminExtension.GetExtensionQueryService();

            // Sort by name, ascending

            Dictionary<QueryAdminVAppField, SortType> sortFields = new Dictionary<QueryAdminVAppField, SortType>();

            sortFields.Add(QueryAdminVAppField.NAME, SortType.SORT_ASC);

                      

            List<QueryAdminVAppField> fields = new List<QueryAdminVAppField>();

            fields.Add(QueryAdminVAppField.NAME);

            fields.Add(QueryAdminVAppField.ORG);

            fields.Add(QueryAdminVAppField.OWNERNAME);

            // Filter for all owned by user, adding an asterisk makes the comparison case-insensitive

            Expression expression = new Expression(QueryAdminVAppField.OWNERNAME, username + "*", ExpressionType.EQUALS);

            Filter filter = new Filter(expression);

            QueryParams<QueryAdminVAppField> queryParams = new QueryParams<QueryAdminVAppField>();

            queryParams.PageSize = 1000;

            queryParams.Page = 1;

            queryParams.Filter = filter;

            queryParams.Fields = fields;

            RecordResult<QueryResultAdminVAppRecordType> recordResult = queryService.QueryAllVappRecords(queryParams);

            foreach (QueryResultAdminVAppRecordType vappRecord in recordResult.GetRecords())

            {  /* Do stuff with vappRecord */ }

             return hadError;

}

Debug output:
ClientAppTrace Information: 0 : Status Code - 403
ClientAppTrace Information: 0 : Status - Forbidden
ClientAppTrace Information: 0 : Response - <?xml version="1.0" encoding="UTF-8"?>
<Error xmlns="http://www.vmware.com/vcloud/v1.5" minorErrorCode="ACCESS_TO_RESOURCE_IS_FORBIDDEN" message="This operation is denied." majorErrorCode="403" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.vmware.com/vcloud/v1.5 http://10.101.6.62/api/v1.5/schema/master.xsd"></Error>

Is there a way to narrow it down to a specific organization? Or combining Expression objects (ideally filter=(ownerName==somename*;organizationName=myorg) )? The user (somename) only has one vapp, in the same org as the Org Admin I'm using to perform the query. I tried filtering for all vapps in the org, and I got the same result, so I'm not sure why it gives me a 403. 

Has anybody gotten the query service to work with just an Org Admin? Oh, I'm doing it this way instead of  Vdc.GetVdcByReference(x,y).GetVappRefs()) because the query service is much faster.

        public bool GetVAppsForUser(string username)

        {

            //bool answer = false;

            //Vdc vdc = FindVdc(orgname, vdcname);

            int numVapps = 0;

            int vAppsCleared = 0;

            bool hadError = false;

           

          

            Dictionary<string, ReferenceType> organizationsMap = client.GetOrgRefsByName();   

            Dictionary<string, string> hrefToOrg = new Dictionary<string, string>();

            foreach (string orgName in organizationsMap.Keys)

            {

                hrefToOrg[organizationsMap[orgName].href] = orgName;

            }

            VcloudAdminExtension adminExtension = client.GetVcloudAdminExtension();

            ExtensionQueryService queryService = adminExtension.GetExtensionQueryService();

            // Sort by name, ascending

            Dictionary<QueryAdminVAppField, SortType> sortFields = new Dictionary<QueryAdminVAppField, SortType>();

            sortFields.Add(QueryAdminVAppField.NAME, SortType.SORT_ASC);

            // not sure why we need fields, but we'll take them.

            List<QueryAdminVAppField> fields = new List<QueryAdminVAppField>();

            fields.Add(QueryAdminVAppField.NAME);

            fields.Add(QueryAdminVAppField.ORG);

            fields.Add(QueryAdminVAppField.OWNERNAME);

            //fields.Add(QueryAdminVAppField.HREF);

            // Filter for all owned by user

            // Adding an asterisk makes the comparison case-insensitive

            Expression expression = new Expression(QueryAdminVAppField.OWNERNAME, username + "*", ExpressionType.EQUALS);

            //Expression orgFilter = new Expression(QueryAdminVAppField.ORG, "Engineering", ExpressionType.EQUALS);

            Filter filter = new Filter(expression);

           

            QueryParams<QueryAdminVAppField> queryParams = new QueryParams<QueryAdminVAppField>();

            queryParams.PageSize = 1000;

            queryParams.Page = 1;

            queryParams.Filter = filter;

            queryParams.Fields = fields;

               

            RecordResult<QueryResultAdminVAppRecordType>  recordResult = queryService.QueryAllVappRecords(queryParams);

            Dictionary<string, List<string>> vappsByOrganization = new Dictionary<string, List<string>>();

            //Dictionary<string, ReferenceType> vAppReferencesByName = new Dictionary<string, ReferenceType>();

            foreach (QueryResultAdminVAppRecordType vappRecord in recordResult.GetRecords())

            {

                // it's easier to transform the href into a reference.id with string replacement, rather than

                // getting the reference, then tracking down the organization.

                string lastPart = vappRecord.href.Substring(vappRecord.href.LastIndexOf("/") + "/vapp-".Length);

                string vcloud_id = "urn:vcloud:vapp:" + lastPart;

                string orgName = vappRecord.org; 

                if (!hrefToOrg.ContainsKey(vappRecord.org))

                    // If we can't find an org name in the the organizationMap, we'll just use the href we get from the vappRecord

                    log.ErrorFormat("Can't find organization name for vapp {0}. Org href is {1}.  This shouldn't happen.", vappRecord.name, vappRecord.org);                   

                else

                    orgName = hrefToOrg[vappRecord.org];

                   

                log.Debug("\t\towner: " + vappRecord.ownerName + ", vapp: " + vappRecord.name + ", vcloud id: " + vcloud_id + ", org: " + vappRecord.org);

                numVapps++;

                if (!vappsByOrganization.Keys.Contains(orgName))

                {

                    vappsByOrganization.Add(orgName, new List<string>());

                }

                vappsByOrganization[orgName].Add(vappRecord.name);

                if (checkForVapp(vappRecord.name, vcloud_id, orgName))

                {

                    vAppsCleared++;

                }

                  

                                   

            }

            log.Debug("\tCheck for vapps in DB that don't exist in this cloud");

            foreach (string org in vappsByOrganization.Keys)

            {

                if (!markOrphanedAsDeleted(vappsByOrganization[org], username, org))

                    vAppsCleared--;

            }

               

              

           

            return numVapps == vAppsCleared;

        }
Reply
0 Kudos
0 Replies