Author Archive | jbmurphy

Powershell signing, makecert.exe and group policy – Part 1

We don’t have a pki infrastructure at my current job, and I like to keep my powershell scripts on my network drive. So I needed a way to run my .ps1 files off a network drive. Setting Set-ExecutionPolciy to Unrestricted seemed like a bad idea. So I looked into using a signed script and setting Set-ExecutionPolicy to RemoteSigned. I could not justify $300 to buy a trused third party cert, so I looked at makecert.exe from the Windows SDK.

First step make the Root CA cert, private key, and pxf.

  1. makecert -n “CN=RootName” -a sha1 -eku 1.3.6.1.5.5.7.3.3 -r -sv Root.pvk Root.cer
  2. pvk2pfx.exe -pvk Root.pvk -spc Root.cer -pfx Root.pfx -pi password

makecert and pvk2pfx can be found in the Windows SDK or in the Visual Studio bin directory. First command results in a private key (.pvk) and a certificate (.cer). Second command makes a pfx out of the first 2.

Second step is to create a certificate from the root cert above.

  1. makecert -pe -n “CN=Certificate” -a sha1 -eku 1.3.6.1.5.5.7.3.3 -ic Root.cer -iv Root.pvk -sv Certificate.pvk Certificate.cer
  2. pvk2pfx.exe -pvk Certificate.pvk -spc Certificate.cer -pfx Certificate.pfx -pi password

Now we are ready to sign our powershell script.

  1. $cert = Get-PfxCertificate Certificate.pfx
  2. Set-AuthenticodeSignature -Filepath script.ps1 -Cert $cert

Probably can be combined into one line, but I am not a guru yet.

Next post will talk about how I added this certs above to all the servers.

New MD5 based backup script

I found this use of md5 and find the other day. I based my current backup script around it. The md5 will show if anyone modifies a file, or adds/removes a file in the web hosting root (/var/www) or in the config directory (/etc/httpd/conf.d/). If there is a change then zip each site up individually and move to a backup folder to be rsynced to other servers.

NewWWWMD5=$(find /var/www/ -type f -exec md5sum {} \; | md5sum - | awk '{print $1}')
OldWWWMD5=$(cat $PARENTDIR/_var_www_*.md5)
NewConfMD5=$(find /etc/httpd/conf.d/ -type f -exec md5sum {} \; | md5sum - | awk '{print $1}')
OldConfMD5=$(cat $PARENTDIR/_etc_httpd_conf.d_*.md5)

if [ $NewWWWMD5 = $OldWWWMD5 -a $NewConfMD5 = $OldConfMD5 ]; then
	echo "Neither /var/www/ nor /etc/httpd/conf.d/ have changed"
else
	rm -rf $BACKUPDIR/*Files
	echo "/var/www or /etc/httpd/conf.d has changed"
	mkdir -p $BACKUPDIR-Files

	# backup /var/www
	for directory in /var/www/*; do
	  	if [ -d $directory ]; then
	    	bu $directory;
	    fi
	done

	# replace previous /var/www MD5
	rm -f $PARENTDIR/_var_www_*.md5
	find /var/www/ -type f -exec md5sum {} \; | md5sum - | awk '{print $1}' > $PARENTDIR/_var_www_$CURRENTDAY.md5

	#backup /etc/httpd/conf.d
	bu "/etc/httpd/conf.d"

	# replace previous /etc/httpd/conf.d MD5
	rm -f $PARENTDIR/_etc_httpd_conf.d_*.md5
	find /etc/httpd/conf.d/ -type f -exec md5sum {} \; | md5sum - | awk '{print $1}' > $PARENTDIR/_etc_httpd_conf.d_$CURRENTDAY.md5
fi

Seems to work!

PowerShell is great

Okay, I drank the Kool-Aid. PowerShell is awesome. The first thing I wanted to do was make sure my $profile is always the most current no matter what machine was on. In the past I had a batch file that I would run that would open my command prompt the way I wanted. I modified that so if PowerShell is installed, then get my profile up-to-date and then launch PowerShell. This is part of my current batch file:

IF NOT EXIST "c:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" GOTO NO_PS
powershell -NoProfile $a=(Split-Path $profile -parent);if (!(Test-Path $a)) {New-Item $a -type directory};
powershell -NoProfile if (!(Test-Path $profile)) {Copy-Item %~dp0Scripts\Microsoft.PowerShell_profile.ps1 (Split-Path $profile -parent)}
powershell -NoProfile if (!(Compare-Object $(Get-Content $profile) $(Get-Content Scripts\Microsoft.PowerShell_profile.ps1)).Count -eq 0 ) {Copy-Item Scripts\Microsoft.PowerShell_profile.ps1 (Split-Path $profile -parent)}
@start  %COMSPEC% /K PowerShell -nologo

This will copy over my profile if it does not exist or is a different version. Now when I am on a server with PowerShell I can double click my batch file and my environment is up to date!

Using a sub-select to find machines that do not have the most recent version of a package.

Many people have blogged about this – how to find machines that don’t have the most recent version of a package installed.

First we write a query to show machines that don’t have the software installed (in this case firefox)
 select SMS_R_System.Name,SMS_R_System.LastLogonUserName
	from SMS_R_System
		inner join SMS_G_System_SYSTEM on SMS_G_System_SYSTEM.ResourceID = SMS_R_System.ResourceId
	where SMS_R_System.Client = 1
		and SMS_G_System_SYSTEM.SystemRole = "Workstation"
		and SMS_G_System_SYSTEM.Name not in (
			select SMS_R_System.Name
			from  SMS_R_System inner join SMS_G_System_ADD_REMOVE_PROGRAMS on SMS_G_System_ADD_REMOVE_PROGRAMS.ResourceID = SMS_R_System.ResourceId
			where SMS_R_System.Client = 1
			and SMS_G_System_ADD_REMOVE_PROGRAMS.DisplayName like "Mozilla Firefox%")
Next we write a query to show the machines that have the most recent software installed (this is used in the following query):
select SMS_R_System.Name, SMS_R_System.LastLogonUserName, SMS_G_System_ADD_REMOVE_PROGRAMS.DisplayName,
			SMS_G_System_ADD_REMOVE_PROGRAMS.Version
	from  SMS_R_System
		inner join SMS_G_System_ADD_REMOVE_PROGRAMS on SMS_G_System_ADD_REMOVE_PROGRAMS.ResourceID = SMS_R_System.ResourceId
	where SMS_R_System.Client = 1
		and SMS_G_System_ADD_REMOVE_PROGRAMS.DisplayName like "Mozilla Firefox%"
		and SMS_G_System_ADD_REMOVE_PROGRAMS.Version = "3.6.3 (en-US)"
	order by SMS_R_System.Name

Finally we write a query to show machines that aren’t in the query above

	select SMS_R_System.Name, SMS_R_System.LastLogonUserName, SMS_G_System_ADD_REMOVE_PROGRAMS.DisplayName, SMS_G_System_ADD_REMOVE_PROGRAMS.Version
	from  SMS_R_System inner join SMS_G_System_ADD_REMOVE_PROGRAMS on SMS_G_System_ADD_REMOVE_PROGRAMS.ResourceID = SMS_R_System.ResourceId
	where SMS_R_System.Client = 1
		and SMS_G_System_ADD_REMOVE_PROGRAMS.DisplayName like "Mozilla Firefox%"
		and SMS_R_System.Name not in (
			select SMS_R_System.Name
			from  SMS_R_System inner join SMS_G_System_ADD_REMOVE_PROGRAMS on SMS_G_System_ADD_REMOVE_PROGRAMS.ResourceID = SMS_R_System.ResourceId
			where SMS_R_System.Client = 1
			and SMS_G_System_ADD_REMOVE_PROGRAMS.DisplayName like "Mozilla Firefox%"
			and SMS_G_System_ADD_REMOVE_PROGRAMS.Version = "3.6.3 (en-US)")
order by SMS_R_System.Name

Import the First and Third queries into a collection and we have a collection that shows machines that need the updated package (including machines that don’t have any version of the package installed.)

How I created a “Copy to new item” functionality for a SharePoint list – Part 2

Second part. First Part can be found here. On the second page (NewForm.aspx), I grabbed out of the querystring the values for the source list item and the name of the list.
I used this person’s query string parser.

Then I used the following SOAP query :

$(document).ready(function() {
 var sourceID = getQuerystring('SourceID');
 var listName = getQuerystring('ListName');

 var soapEnv = "<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/'> \
<soapenv:Body> \
<GetListItems xmlns='http://schemas.microsoft.com/sharepoint/soap/'> \
<listName>" + listName + "</listName> \
<viewName>{GUID}</viewName> \
<viewFields /> \
<ViewFields /> \
<query> \
<Query><Where> \
<Eq> \
<FieldRef Name='ID' /> \
<Value Type='Integer'>" + sourceID + "</Value> \
</Eq> \
</Where></Query>\
</query> \
</GetListItems> \
</soapenv:Body> \
</soapenv:Envelope>";

 $.ajax({
 async: false,
 url: "http://site.com/subsite/_vti_bin/lists.asmx",
 type: "POST",
 dataType: "xml",
 data: soapEnv,
 complete: processResult,
 contentType: "text/xml; charset=\"utf-8\""
 });

 });
 function processResult(xData, status) {
 $(xData.responseXML).find("z\\:row").each(function() {
 $("input[title='Input']").val($(this).attr("ows_Input"));
 $("textarea[title='TextArea']").val($(this).attr("ows_TextArea"));
 $("select[title='DropDown']").val($(this).attr("ows_DropDown")).attr("selected", "selected"); 
 }
 )};

In the last three lines I changed the input box, textbox and dropdown boxes to their values in the results fromt the SOAP query.

Kinda fun. Just need to figure out how to do check boxes!

How I created a “Copy to new item” functionality for a SharePoint list – Part 1

I wanted to create a “copy to new item” functionality for a SharePoint list.

Steps I came up with:

  1. The first thing I had to do was add a link to the context menu (I learned that it is called an ECB) and have it point to the NewForm.aspx.
  2. Once I got that, I could append a querystring variable to the url that contained the “Source ID” of the item to copy and the name of the current list.
  3. Then I would grab that querystring value on the other side – in the NewForm.aspx page
  4. Next I would use that variable to query the SharePoint List via SOAP
  5. Inject the results the  into the form

Here is my script (add to a CEWP, I already have the jquery pointers to google in a Delegate control)

<script language="javascript">
function Custom_AddListMenuItems(m, ctx) {
var editURL = window.location.protocol + "//" + window.location.host + ctx.listUrlDir + "/NewForm.aspx?SourceID=" + currentItemID + "&amp;ListName=" + ctx.ListTitle;
 CAMOpt(m, "Copy To New Item" ,"window.location=('" + editURL + "');" , "/_layouts/images/Copy.GIF");
 CAMSep(m);
}
</script>

More to come.

How to add a webpart to a Sharepoint “NewForm.aspx”

I wanted to put a hidden CEWP on top of a standard SharePoint input form (you know when you click “NEW” too add an item to a list). The edit page was grayed out. I added to the querystring “NewForm.aspx?ToolPaneView=2” and I can add the CEWP to the top of the page. Once I added that, the edit page option is no longer grayed out.

BASH (readline) keyboard shortcuts

I was just in training and the instructor was a command line keyboard shortcut wizard. He was magically making words disappear and reappear. So i fond this list of shortcuts. Many of them did not work in my OS X BASH prompt.I fond I had to go into the terminal.app preferences and select “use option key as meta key” on the keyboard tab (it is at the bottom). Now I can add a few shortcuts to my repertoire.

Powered by WordPress. Designed by WooThemes