We had a great example of an AD SPOF (single point of failure) recently. A vbscript had been written by someone with no malicious intent to (for some reason) hook into AD and check service accounts. What this script ended up doing though was locking out said service accounts. Within the span of 30 minutes we were well on our way to locking out 400+ service accounts in the enterprise, irrespective of environment. This took production out of commission.
Seems like a bit of a hole to me.
Showing posts with label vbscript. Show all posts
Showing posts with label vbscript. Show all posts
Friday, August 20, 2010
Monday, July 12, 2010
.Net Self Serve Automated deploy
There are a couple of prerequisites that need to be in place in order for a self serve automated deployment system to work.
1. You should have a Nant, MsBuild, Visual Build, or a similar type of scripting file that is doing deploys for you already - see my previous posts on doing that here
2. Your folder structure for every project you want to deploy should be similar. To have a good Self-Serve Deploy tool, it needs to work on the assumption that directory structures are consistent for certain types of projects. This could be set up using your repository tags directory, or automatically copying deployment files to the required folder structure after the build is successful. A folder structure I've used in the past is b:\deployment\projectname\version\ My build file(s). Any other required folders and files reside in the version folder with a consistent folder structure.
3. You need either a properties file or a DB table to manage which tag/version has been deployed to which environment. We've used a symlink in the past to denote the current 'tip' build. This example will use a file. The file is structured like:
Once the deploy is finished to a particular environment, logic in the deployment file automatically updates the respective project in the appropriate version file.
Here's a bit of sample code for a client side asp page for a Self Serve app. It passes some values to a server side asp page (deploy.asp) so that page will know which version of which project to deploy into which environment. The onchange event of the env select control called an AJAX function that retrieves the currently deployed version of the project from the versions.xml file.
Then on my deploy.asp page, the request parameters are set to variables which are then used to dynamically build the path to the deploy file (in this case a visual build file called Deploy-<serverName>-<component>.bld) This could be a nant, msbuild, or ant file as well, you'd just have to change which executable you're using in the executeString. The command is then executed in a Windows Shell and if it has a return code of '0' it was successful. Successful or not, we do some very simple logging to show who tried to deploy what, where, and when.
Here's the code:
1. You should have a Nant, MsBuild, Visual Build, or a similar type of scripting file that is doing deploys for you already - see my previous posts on doing that here
2. Your folder structure for every project you want to deploy should be similar. To have a good Self-Serve Deploy tool, it needs to work on the assumption that directory structures are consistent for certain types of projects. This could be set up using your repository tags directory, or automatically copying deployment files to the required folder structure after the build is successful. A folder structure I've used in the past is b:\deployment\projectname\version\ My build file(s). Any other required folders and files reside in the version folder with a consistent folder structure.
3. You need either a properties file or a DB table to manage which tag/version has been deployed to which environment. We've used a symlink in the past to denote the current 'tip' build. This example will use a file. The file is structured like:
<versions>
<serverType>
<server name="blahboxType" version="1.2" />
<server name="fooboxType" version="1.0" />
</serverType>
<blahboxType>
<project name="MyProject" version="3.1.0.23" />
<project name="MyProject2" version="3.1.4.11" />
</blahboxType>
<fooboxType>
<project name="fooProj1" version="6.2.123"/>
<project name="fooProj2" version="6.3.92"/>
</fooboxType>
</versions>
Here's a bit of sample code for a client side asp page for a Self Serve app. It passes some values to a server side asp page (deploy.asp) so that page will know which version of which project to deploy into which environment. The onchange event of the env select control called an AJAX function that retrieves the currently deployed version of the project from the versions.xml file.
<form action="deploy.asp" method="get" name="MyProject">
<input name="project" type="hidden" value="MyProject" />
<input name="serverType" type="hidden" value="blahboxType" />
<select name="version">
<option value="">--Select--</option>
<option value="" & version & "">" & version & "</option>
</select>
<select id="MyProject" name="env" onchange="getVersions('MyProject',this.value)">
<option value="">--Select--</option>
<option value="Test1">Test 1</option>
<option value="Test2">Test 2</option>
<option value="SB">Sandbox</option>
<option value="STG">Staging</option>
<option value="PRD">Production</option>
</select>
<div id="MyProjecttarget" style="color: green;">
-</div>
<input type="submit" value="Deploy" />
</form>
Then on my deploy.asp page, the request parameters are set to variables which are then used to dynamically build the path to the deploy file (in this case a visual build file called Deploy-<serverName>-<component>.bld) This could be a nant, msbuild, or ant file as well, you'd just have to change which executable you're using in the executeString. The command is then executed in a Windows Shell and if it has a return code of '0' it was successful. Successful or not, we do some very simple logging to show who tried to deploy what, where, and when.
Here's the code:
' need a longer server timeout setting so our deploy can finish
Server.ScriptTimeout=1200
'instantiate some vars
env = ""
version = ""
project = ""
severType = ""
'set the vars
set version = Request.queryString("version")
set env = Request.queryString("env")
set project = Request.queryString("project")
set serverType = Request.queryString("serverType")
'gets the user
Set WSHNetwork = CreateObject("WScript.Network")
user = WSHNetwork.UserName
if version="" then
Response.Write("Please ensure you chose a version <br/>")
elseif env="" then
Response.Write("Please ensure you chose an environment")
elseif project="" then
Response.Write("error occured - project required")
elseif LCase(env)="PRD" then
Response.Write("We don't want to deploy to Production from this app")
else
Response.Write(version & " " & env & " " & project)
'set up a dynamic path here to the deployment file (nant or ant or visual build file) This string assumes the
'build file is taking a parameter called Env - the environment to deploy to
execString = "<pathToVisualBuildExecutable>\VisBuildCmd.exe /b " & Chr(34) & version & "\visual build\Deploy-" & serverType & "-" & component & ".bld" & Chr(34) & " Env=" & env
Response.Write("<br/>" & executeString)
set oFs = server.createobject("Scripting.FileSystemObject")
set oTextFile = oFs.OpenTextFile("<pathOfFileToLogTo>\deploylog.txt", 8, True)
Dim WshShell
Set WshShell = CreateObject("WScript.Shell")
proc = WshShell.Run(executeString,6,true)
if proc="0" then
response.write("<br/><br/><div style='color:green;font-size:16px;'>Deploy of build " & component & " " & version & " to " & env & " as " & user & " was successful")
dt = now()
logtext = dt & ": Deploy of build " & component & " " & version & " to " & env & " was successful" & vbCrLf
oTextFile.Write logtext
oTextFile.Close
else
response.write("<br/><br/><div style='color:red;font-size:16px;'>Deploy of build " + component + " " + version + " to " + env + " failed using user " + user)
dt = now()
logtext = dt & ": Deploy of build " & component & " " & version & " to " & env & " failed as user " & user & vbCrLf
oTextFile.Write logtext
oTextFile.Close
end if
response.write("<br/>Deploy times and results are logged at <pathOfFileToLogTo>\deploylog.txt")
set oTextFile = nothing
set oFS = nothing
set WshShell=nothing
end if
response.write("<br/><a href='javascript:history.back()'>Back to deploy page<a/>")
Friday, August 14, 2009
XML manipulation in Visual Build (and vbscript)
We've been working on basically turning our Visual Build deployment files into DRP (Disaster Recovery Plan) scripts. Essentially, everything required to get our applications running on a 'blank' server box is documented as a config, permission, or push in our Visual Build files. This has required updating then machine.config and web.config files that reside under windows/microsoft.net/framework/v1.1.4322 or v2.0.50727/config at times. Sometimes we're adding attributes to existing element, sometimes we're adding entirely new elements.
It seems to me that adding entirely new elements in Visual Build (using the Write XML Action) has a bug in it. It will add new attributes to existing elements no problem. But it won't add new elements. So we hacked around that and used the 'Run Script' Action with vbscript to add elements to our files. To do this in vbscript it looks something like this:
Dim objXMLDoc, objNewNode, objText, strXPath, objParentNode, objChildNode, objCaseExist
Set objXMLDoc = CreateObject("Microsoft.XMLDOM")
objXMLDoc.async = False
' load the XML file - make sure to include the fully qualified path
fSuccess = objXMLDoc.load("\\%TARGET_SERVER%\c$\WINDOWS\Microsoft.NET\framework\v2.0.50727\config\web.config")
If Not fSuccess Then
wscript.echo ("error loading XML file")
Else
wscript.echo ("XML file loaded")
End If
' set to proper node
Set nodeList = objXMLDoc.getElementsByTagName("configuration/system.web/compilation/buildProviders")
If nodeList.length > 0 Then
Set objParentNode = nodeList(0)
' add the SGAS SecurityDisabled element/node
Set objNewNode = objXMLDoc.createElement("add")
objNewNode.setAttribute "extension", ".uplx"
objNewNode.setAttribute "type", "System.Web.Compilation.PageBuildProvider"
objParentNode.appendChild(objNewNode)
objParentNode.appendChild objXMLDoc.createTextNode (vbCrLf)
set objNewNode = Nothing
else
wscript.echo ("node list empty")
end if
' save the XML file
objXMLDoc.save("\\%TARGET_SERVER%\c$\WINDOWS\Microsoft.NET\framework\v2.0.50727\config\web.config")
It seems to me that adding entirely new elements in Visual Build (using the Write XML Action) has a bug in it. It will add new attributes to existing elements no problem. But it won't add new elements. So we hacked around that and used the 'Run Script' Action with vbscript to add elements to our files. To do this in vbscript it looks something like this:
Dim objXMLDoc, objNewNode, objText, strXPath, objParentNode, objChildNode, objCaseExist
Set objXMLDoc = CreateObject("Microsoft.XMLDOM")
objXMLDoc.async = False
' load the XML file - make sure to include the fully qualified path
fSuccess = objXMLDoc.load("\\%TARGET_SERVER%\c$\WINDOWS\Microsoft.NET\framework\v2.0.50727\config\web.config")
If Not fSuccess Then
wscript.echo ("error loading XML file")
Else
wscript.echo ("XML file loaded")
End If
' set to proper node
Set nodeList = objXMLDoc.getElementsByTagName("configuration/system.web/compilation/buildProviders")
If nodeList.length > 0 Then
Set objParentNode = nodeList(0)
' add the SGAS SecurityDisabled element/node
Set objNewNode = objXMLDoc.createElement("add")
objNewNode.setAttribute "extension", ".uplx"
objNewNode.setAttribute "type", "System.Web.Compilation.PageBuildProvider"
objParentNode.appendChild(objNewNode)
objParentNode.appendChild objXMLDoc.createTextNode (vbCrLf)
set objNewNode = Nothing
else
wscript.echo ("node list empty")
end if
' save the XML file
objXMLDoc.save("\\%TARGET_SERVER%\c$\WINDOWS\Microsoft.NET\framework\v2.0.50727\config\web.config")
Subscribe to:
Posts (Atom)