Automatically Deploy Forefront Endpoint Protection Updates via System Center Configuration Manager

Automatically Deploy Forefront Endpoint Protection Updates via System Center Configuration Manager

Overview

While Forefront Endpoint Protection 2010 (FEP) is integrating with System Center Configuration Manager 2007 R2 (ConfigMan) for management and monitoring, out of the box there is no preferred method for pushing updates using SSCM’s Advertisements.

Out of the box, FEP supports 5 methods of getting updates:

    1.       WSUS or SUP (Software Update Point in ConfigMan)

    2.       UNC shares

    3.       Windows Update

    4.       Microsoft Security Portal (http://www.microsoft.com/security/encyclopedia/adlpackages.aspx)

    5.       Manual method (such as ConfigMan, scheduled scripts or similar solution)

While we have a lot of options, some customers really want to use the Distribution Points and Advertisement in ConfigMan, as they have an existing investment in this and want the most control of the network bandwidth.

In the next version of ConfigMan, Microsoft hopes to include options for automatically approving updates, something that WSUS has and ConfigMan does not.  Until then, this article addresses one approach by leveraging the existing SSCM’s deployment methods.

Architecture

To accomplish this with ConfigMan 2007 R2, we will follow this architecture below:

 Step 1 and 2: We execute a scheduled script that:

1.       Determines the current engine version.

2.       Determines the current signature version.

3.       Downloads either a delta update (if engine and signature have not passed the rebase period) or a full update.

4.       Copies the downloaded file to a location for ConfigMan.


Step 3:
  On a scheduled basis, we update the remote distribution points with the new update.

Step 4:
  On a scheduled basis, the client (re)run the update Forefront advertisement.

 

Setup

While this entire setup could be scripted, part of this article try’s to fully explain what and how things are setup.  Please note that this approach only performs delta updates (to optimize network bandwidth) and will not update a new install with the full client.  Your FEP policy should include the ability for a client to get the full engine package by using other methods.


                 Step 1.  Create the directories C:\FEPUpdates, C:\FEPUpdates\script and C:\FEPUpdates\defs on the Primary Site Server.

                 Step 2.   In the C:\FEPUpdates\script directory, create the VBS Script in appendix A.

                 Step 3.   Schedule the script to run every 6 hours by using the Windows Task Scheduler as shown below:

Note: Because this will be a scheduled task, you will need a service account with a non-expiring password.










                 Step 4.   Manually run the scheduled task, so that  your directory structure and files will be populated before you setup the program and advertisement in ConfigMan.

                 Step 5.   Create a package in ConfigMan to where the package updates from the source every 7 hours as shown below:



Step 6.   Create a program in the above package that runs the command cmd.exe /c "%PROCESSOR_ARCHITECTURE%\mpam-d.exe" as shown below:






Step 7.   Schedule a reoccurring advertisement  in ConfigMan that runs every 8 hours, as shown below:




  

Appendix A – Download Script

' FEP Download delta definitions

    'Customer needs to modify these for local environment
    '================================================================================================

    strRootLocation =  "C:\FEPUpdates\Defs"     ' this need to be modified to local path for root of the folder structures for updates

    strLogFile =  "C:\FEPUpdates\script\DefDownloadv5.log"  ' set this to where you want to save the log file at if not placing in strRootLocation then will need to insure that folder structure exists and specify full path

    strLogData =  ""

    '================================================================================================

 

    'Constants to not modify value in this area

    '================================================================================================

    Const ForReading = 1, ForWriting = 2, ForAppending = 8, WindowsFolder = 0

    Const TristateUseDefault = -2, TristateTrue = -1, TristateFalse = 0

    '================================================================================================

    LogToEventLog = True

    strSigNameDelta =  "mpam-d.exe"

    AVDelta =   reduceByOne(ReadReg("HKLM\SOFTWARE\Microsoft\Microsoft Antimalware\Signature Updates\AVSignatureVersion"))

    ASDelta =   reduceByOne(ReadReg("HKLM\SOFTWARE\Microsoft\Microsoft Antimalware\Signature Updates\ASSignatureVersion"))

    Engine =   ReadReg("HKLM\SOFTWARE\Microsoft\Microsoft Antimalware\Signature Updates\EngineVersion")

    strMSEx86URLDelta = "http://go.microsoft.com/fwlink/?LinkID=121721&clcid=0x409&arch=x86&eng=" & Engine & "&avdelta=" & AVDelta & "&asdelta=" & ASDelta

    strMSEx64URLDelta = "http://go.microsoft.com/fwlink/?LinkID=121721&clcid=0x409&arch=x64&eng=" & Engine & "&avdelta=" & AVDelta & "&asdelta=" & ASDelta

  '=============== Logging Function =======================================

    Set objFSO = Createobject("Scripting.FileSystemObject")

    if (not objFSO.FileExists(strLogFile)) then

        objFSO.CreateTextfile strLogFile

        set fileObj = objFSO.GetFile(strLogFile)

        set logStream = FileObj.OpenAsTextStream(ForAppending, TristateUseDefault)

        logstream.writeline now & " " & "Log file created and opened"

    else

     set fileObj = objFSO.GetFile(strLogFile)

     set logStream = FileObj.OpenAsTextStream(ForAppending, TristateUseDefault)

    end if

  '=============== Logging Function =======================================

  

  '======================================================

  '= Sub to download and save the files

  '= __in objConnection winhttprequest object

  '= __in strURL the url of the fiel to download

  '= __in strPAth the path to save the file to

  '= __ FileName name of the file to be saved

  sub DownloadDefs(objConnection, strURL, Path, FileName, logfile)

    'turn on error handling

     on error resume next

    'copy PAth to temp variable to manipulate

    strPath = Path

   

    'check to see if the URL for x86 or x64 was passed

    set regEx = new RegExp

    regEx.Pattern = "x86"

    regEx.IgnoreCase = True

    regEx.Global = False

    if (regEx.Test(strUrl)) then

        strPath = strPath + "\" + "x86"

     Else

        strPath = strPath + "\" + "x64"

     end if

    LogData " > Download of " & strURL & " started at: " & now

    objConnection.open "GET", strURL, false

    if (err.Number <> 0) then

           LogData now & " " & "Error # " & CStr(err.number) & " " & Err.Description & " Source: " & Err.Source

           Err.Clear

           exit sub

    end if

    objConnection.send()

    if (err.Number <> 0) then

           LogData now & " " & "Error # " & CStr(err.number) & " " & Err.Description & " Source: " & Err.Source

           Err.Clear

           exit sub

    end if

    'check to see if download was successful before moving on

    If objConnection.Status = 200 Then

        Set objADOStream = CreateObject("ADODB.Stream")

        objADOStream.Open

        objADOStream.Type = 1 'adTypeBinary

        objADOStream.Write objConnection.ResponseBody

        objADOStream.Position = 0    'Set the stream position to the start

        Set m_objFSO = Createobject("Scripting.FileSystemObject")

        'check if folder structure exists

       

        if (m_objFSO.FolderExists(strPath)) then

             'create complete path

             strCompletePath = strPath + "\" + FileName

             'check if file exists if so delete

             If m_objFSO.FileExists(strCompletePath) Then m_objFSO.DeleteFile(strCompletePath) end if

                   if (err.Number <> 0) then

                     LogData now & " " & "Error # " & CStr(err.number) & " " & Err.Description & " Source: " & Err.Source

                     Err.Clear

                     exit sub

                end if

           

         else

           m_objFSO.CreateFolder(strPath)

           strCompletePath = strPath + "\" + FileName

           If m_objFSO.FileExists(strCompletePath) Then m_objFSO.DeleteFile(strCompletePath) end if

            if (err.Number <> 0) then

                LogData now & " " & "Error # " & CStr(err.number) & " " & Err.Description & " Source: " & Err.Source

                Err.Clear

                exit sub

            end if

        end if

   

        objADOStream.SaveToFile(strCompletePath)

        if (err.Number <> 0) then

           LogData now & " " & "Error # " & CStr(err.number) & " " & Err.Description & " Source: " & Err.Source

           Err.Clear

        end if

        objADOStream.Close

        LogData " >> " & strCompletePath & " Successfully downloaded at: " & now

    end if

    'Cleanup

    strCompletePath = ""

    strPath = ""

    Set objADOStream = Nothing

    Set m_objFSO = Nothing

 end sub

 function reduceByOne(versionnumber)

  versionnumberSplit= Split(versionnumber,".")

  reduceByOne = versionnumberSplit(0) & "." & versionnumberSplit(1) & "." & versionnumberSplit(2)-1 & "." & versionnumberSplit(3)

 end function

 sub LogData(mydata)

  logStream.writeline mydata

  if LogToEventLog then strLogData = strLogData & vbcrlf & mydata

 end sub

 sub WriteToEventLog()

  Set WshShell = WScript.CreateObject("WScript.Shell")

  WshShell.LogEvent 0, strLogData

 end sub

 Function ReadReg(RegPath)

  Dim objRegistry, Key

  Set objRegistry = CreateObject("Wscript.shell")

  Key = objRegistry.RegRead(RegPath)

  ReadReg = Key

 End Function

 '=======================================================================================

 '=== Main program body

 '=======================================================================================

 'Turn on error handling for Main program body

 on error resume next

 

 ' create WINHTTP object used to retrieve the file

 Set objWINHTTP = CreateObject("WinHttp.WinHttpRequest.5.1")

 LogData " "

 LogData "==================== " & now & " Download Session started ===================="

 DownloadDefs objWinHTTP, strMSEx86URLDelta, strRootLocation, strSigNameDelta, logstream

 DownloadDefs objWinHTTP, strMSEx64URLDelta, strRootLocation, strSigNameDelta, logstream

 LogData "===================== " & now & " Download Session ended ====================="

 if LogToEventLog then WriteToEventLog()

'Clean UP

set objFSO = nothing

Set objWINHTTP = Nothing
 

Author

Kevin Saye, Security Technical Specialist – Microsoft

Reviewers

Daniel Taylor, Security Technical Specialist – Microsoft

Kenneth Bess, Consultant – Microsoft Consulting Services

Chris Norman, Escalation Engineer – Microsoft

Andrew Plue, Anti-Malware Practice Lead – Certified Security Solutions

Adam Rafels, Senior Lead Consultant – Catapult Systems
 
Sort by: Published Date | Most Recent | Most Useful
Comments
  • Great documention on a workaround to what seems to be a lacking feature.

    Having tested this out though, it seems like the expectation is that the version of FEP is consistent across all machines.  Isn't this script checking the definition version on the SCCM server and then downloading the deltas accordingly?  If so, what happens to clients that are not at the same version?  In my testing it seems like the update fails.  Perhaps this is due to the clients having the original engine version or will issues exist if the versions are not the same as the SCCM server?

  • jpalarchio, you need to have the FEP client get the latest definitions before using the directions above.  It needs a full update before it can do deltas.  

  • gadgetadam is correct, you need the full engine update first, as this is just a delta update.

    If you look at the script, we use the function "reduceByOne" which rolls back the definition date.  In my testing, the update worked pretty well and even caught up if the machine was a revision or two behind.  the secret is the URL.  As of right now, my engine is 1.1.6603.0 and my AV and AS definitions are: 1.99.1311.0.  So you would use the URL: go.microsoft.com/fwlink to get the update.  If you change this URL to be an earlier AV and AS, say: 1.99.1211.0 (go.microsoft.com/fwlink) you will see that it downloads the same ~3.27 MB file.  This being the case, I don't imaging we will have an issue with a machine falling behind a day or so.  On the monthly rebase, when the engine version changes, the URL will pull down the needed update.  Try the URL: go.microsoft.com/fwlink and you will see what I mean (notice the engine version is -1.

     The customer who really prompted me to write this was also using a UNC location where they would place full engine updates, but those were much larger (~60 mb) and they would only update these once a week or so.

  • Here's an alternative method for accomplishing the same thing using code from the SDK. This was put together by Kim Oppalfens.

    www.myitforum.com/.../Articles.aspx

  • I'm new to SCCM/FEP and I will attempt to use this method to deploy updates to our remote DPs. In the guide it doesn't mention which collection I should advertise to...I was a little confused - do I advertise this to a collection that contains my DPs, my clients or both? I guess I'm not clear as to how the remote DPs get these updates and then distribute them.

    Thanks!

  • Hello:

    You should advertise the "Deployment Succeeded" collection and sub collections.

    Regards,

  • Great stuff.  In our environment, we have amd64 processors being detected.

    Is there any way to add it to the script?  

    Right now I have created a batch file (not that good at scripting) that calls the script, then copies the files from the 'x64' folder to an 'amd64' folder.

  • The program command line in Step 6 was causing this error (Although the updates were installing)

    "A failure exit code of -15 was returned. "

    Changing it to "%PROCESSOR_ARCHITECTURE%\mpam-d.exe" fixed the error and now advertisement shows as successfully completing.

    This method will definitely be used in our production environment when we switch over to FEP.

    Thanks.

Page 1 of 1 (8 items)