Monthly Archives: March 2017

JDF 17 Session Resources: Publishing your app on appexchange.

Resource Page for Jaipur Developer Festival session Publishing your app on Appexchange

Link to slide deck Publishing your app on Appexchange – Sagar Pareek

1. Storing Secrets –

What is it? : Sensitive data is exposed to user.
Remedy: Use protected custom settings.

Create custom settings with private as visibility.
Name it App Custom Settings.
Make sure setting type is List.

Create a custom object named Integration Setting
Name field should be of Auto Number ( I-{00000} )
Create 3 custom fields
Username
Password
Endpoint URL

Trigger Code –

/* Created By: Sagar Pareek
   Description: This trigger replaces the password with asteriks and saves the password in protected custom settings mapped with username.

*/

trigger IntegrationSettings on Integration_Settings__c (before insert, before update) {
    if (trigger.isBefore){
     //  Map to be checked against for the existence of a Custom Setting for a User
     map userToCustomSetting = new map();
      
     //  Lists for new, updated, and existing settings.
     list newSettings = new list();
     list updateSettings = new list();
     list existingSettings = [SELECT  Id, Name, Password__c FROM   App_Custom_Settings__c ORDER BY  CreatedDate LIMIT   25];  
        
     list validApplicationSettings = new list();
         
        //  Populate the map based on the above query's results - keyed by the Username (name contains username)               
     if (!existingSettings.isEmpty()){
      for (App_Custom_Settings__c s : existingSettings){
       userToCustomSetting.put(s.Name,s);
      } 
     }
      
        for (Integration_Settings__c  stg : trigger.new){
            if (stg.Password__c != null && stg.Password__c  != '' ){
             //  Inserts are easier - as long as the Password was provided, we'll add it
                if (trigger.isInsert)
              validApplicationSettings.add(stg);
             //  We'll make sure the old and new Password values don't match and aren't udpated to the "masked" value
                else if (trigger.isUpdate)
              if (stg.Password__c != '********' && stg.Password__c != trigger.oldMap.get(stg.id).Password__c)
                  validApplicationSettings.add(stg);
            }
        }
         
        if (!validApplicationSettings.isEmpty()){
            for (Integration_Settings__c  stg : validApplicationSettings){
                //  Do any Custom Settings exist for this User?  If so, update.  Otherwise, create.
                if (userToCustomSetting.containsKey(stg.Username__c)){
                    userToCustomSetting.get(stg.Username__c).Password__c = stg.Password__c;
                    updateSettings.add(userToCustomSetting.get(stg.Username__c));
                }
                else{
                    newSettings.add(new App_Custom_Settings__c(Name = stg.Username__c, Password__c = stg.Password__c));
                }
                //  Replace the Password
                stg.Password__c = '********';
            }
           
            //  Do inserts and updates
            if (!newSettings.isEmpty())
                insert newSettings;
            if (!updateSettings.isEmpty())
                update userToCustomSetting.values();
        }
    }
}


Security Scanner Link

Force.com Security Scan Report

Link to force.com security scan report

ZAP tutorial

Sample ZAP Report

ZAP Report Link

Reporting False Positives in ZAP report

Link to False positive documentation

On Passing your review –

Screen Shot 2017-03-29 at 1.57.43 PM