Forefront Endpoint Protection: Automatically Deploy Updates via SCCM
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:
- WSUS or SUP (Software Update Point in ConfigMan)
- UNC shares
- Windows Update
- Microsoft Security Portal (http://www.microsoft.com/security/encyclopedia/adlpackages.aspx)
- 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’sdeployment 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:
- Determines the current engine version.
- Determines the current signature version.
- Downloads either a delta update (if engine and signature have not passed the rebase period) or a full update.
- 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 directoriesC:\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 every7 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