function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
KellymtKellymt 

Callout to SOAP API fails when IP Restrict Requests is turned on for a Profile

We have setup a Salesforce Community and have turned on the "IP Restrict Requests" setting on the user's profile.
We have an apex class (see below) which makes a call out to the SOAP API to retrieve the layout metadata for an sObject. The exact method we call is GetLayout and the SOAP API endpoint we are hitting is 'https://SALESFORCEDOMAIN/services/Soap/u/32.0' where SALESFORCEDOMAIN is the domain of the account.
The problem we are having is that calling out to the SOAP API fails with INSUFFICIENT_ACCESS. If we disable "IP Restrict Requests" or enter in the IP ranges table for the profile the range 0.0.0.0 - 255.255.255.4 the call succeeds.
If we enter all Salesforce IP ranges published online the call fails. I think that because our Apex class makes the request to Salesforce itslef that I need to whitelist Salesforce's IPs for the callout to succeed but that is not the case.
Does anybody know what range should I have in my IP table for the call to succeed? 
 
Code: 

public String GetLayout(String sObjectName, String recordTypeId) {
    String requestXml = GetDescribeLayoutRequestXml(sObjectName, System.UserInfo.getSessionId());
    String responseXml = ExecuteRequest('Something', requestXml); //KM: The service does not return anything without soap action. The soap action value does not matter.
    
    return responseXml ;

 private String GetDescribeLayoutRequestXml(String sObjectName, String sessionId) {
    String xml = '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:partner.soap.sforce.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> \n' +
                    '<soapenv:Header> \n' + 
                        '<urn:SessionHeader> \n' + 
                            '<urn:sessionId>{0}</urn:sessionId> \n' + 
                        '</urn:SessionHeader> \n' + 
                    '</soapenv:Header> \n' + 
                    '<soapenv:Body> \n' + 
                        '<urn:describeLayout> \n' + 
                            '<urn:sObjectType>{1}</urn:sObjectType> \n' + 
                            '<urn:layoutName xsi:nil="true" /> \n' + 
                        '</urn:describeLayout> \n' + 
                    '</soapenv:Body> \n' + 
                '</soapenv:Envelope> \n';
                
    List<String> prms = new List<String>();
    prms.add(sessionId);   //{0}
    prms.add(sObjectName); //{1}
    
    return String.format(xml, prms);
}
private static string ExecuteRequest(String soapAction, String requestXml) {
    HttpRequest req = new HttpRequest();
    req.setTimeout(120000); 
    req.setEndpoint('https://SALESFORCEDOMAIN/services/Soap/u/32.0');
    req.setHeader('Content-Type','text/xml');
    req.setHeader('SOAPAction', soapAction);
    req.setMethod('GET');
    req.setBody(requestXml);
    
    Http h = new Http();               
    HttpResponse res = h.send(req);
    dom.Document doc = res.getBodyDocument();  
    
    return doc.toXmlString();       
}    
Best Answer chosen by Kellymt
KellymtKellymt
I was able to solve the problem. The solution was to add to the IP ranges table the IP range 10.0.0.0 - 10.255.255.255. This is because when Saelsforce calls itself i.e. my Apex class calls the Salesforce SOAP API which is also hosted by Salesforce the origin IP of the request is a local network IP and not one of the published external Salesforce IPs. 
I was able to discover that by creating a simple Apex Rest webservice which returns the IP of the caller. The class looks like this: 
@RestResource(urlMapping='/TestService/*')
global class NewService {
    @HttpGet
    global static String GetIPs () {
        RestRequest req = RestContext.request;
        Map<string, string> headers = req.headers;
        if(headers == null) { return 'Headers are null. '; }
        
        String res = '';
        res += headers.containsKey('True-Client-IP') ? headers.get('True-Client-IP') + ', ' : '';
        res += headers.containsKey('X-Salesforce-SIP') ? headers.get('X-Salesforce-SIP') + ', ' : '';
        res += headers.containsKey('X-Forwarded-For') ? headers.get('X-Forwarded-For') + ', ' : '';
        
        return res;
    }
}

Then I created another Apex class with a method which calls out to the above service and logs the result. In the log I saw the the IP was from the 10.x.x.x network.