Exchange – Performing A Pseudo/Fake/Dummy Backup

At some point during your Exchange admin life you may want to perform a quick backup of your Exchange server if your transaction log drive has become full. To clear down the transaction logs you will need to perform a backup of the Exchange database(s), this always isn’t possible due to the time needed to perform a backup. This is where a pseudo/fake/dummy backup comes in as makes Exchange think that a backup has completed and to truncate all the transaction logs, this will enable you to bring the Exchange server back online quickly.

This procedure should only be done after you understand the risks, as it will affect the ability to be able to restore the server in the event of a system failure. If a system failure was to occur you will potentially loose all emails sent/received since the last full backup. Once completed a full backup should always be performed as soon as possible. This is to ensure that window of potential data loss is kept to a minimum.

To perform the procedure:

  1. Open an elevated command prompt
  2. Type “diskshadow" and hit Enter
  3. Type “add volume x:" (“x” is the drive that the Exchange database is on, you can enter this line multiple times to add additional volumes if needed) and hit Enter
  4. Type “begin backup" and hit Enter
  5. Type “create" and hit Enter
  6. Type “end backup" and hit Enter
  7. Type “exit" and hit Enter

Example screenshot.

Please note: I accept no liability for any loss of data that may occur by you using this procedure, and you use it entirely at your own risk.

Zabbix – Zabbix LLD using zabbix_sender

I have recently been looking into monitoring our backup solution using PowerShell and Zabbix. I came across a solution that kind of worked and was intermittent due to the script timing out, and upping the timeout also has other performance implications.

Looking at how the script worked it was producing some JSON that was then being parsed by Zabbix to provide the LLD.

Example of output (re-formatted)

{
	"data":[
		{
			"{#JOBID}":"3d2ddd75-7276-41d0-bce2-6c25fce5d1c9",
			"{#JOBNAME}":"A Backup Job",
			"{#JOBSCHEDULED}":"True"
		}
	]
}

To get LLD working with the zabbix_sender we need to be able to send the JSON to the Zabbix server. This is where the problems began as sending the JSON from the command line using the -o/--value option failed.

The way to get it to work is to get zabbix_sender to use a temporary input file and send the data that way.

To set this up, set your discovery rule so that the type is “Zabbix trapper”

Example

Zabbix Discovery Rule Screenshot

Then setup your script/program to output the required JSON into a temporary file formatted in the following way.

<hostname> <itemkey> <JSON/value>

E.g.

TestHost TestItem[Discover] {"data":[{"{#JOBID}":"3d2ddd75-7276-41d0-bce2-6c25fce5d1c9","{#JOBNAME}":""A Backup Job","{#JOBSCHEDULED}":"True"}]}

Or

- TestItem[Discover] {"data":[{"{#JOBID}":"3d2ddd75-7276-41d0-bce2-6c25fce5d1c9","{#JOBNAME}":""A Backup Job","{#JOBSCHEDULED}":"True"}]}

Note1: The JSON/value must be on the same line as the hostname and itemkey.
Note2: Specifying a “-” for the hostname uses the hostname from the configuration file or from the command line.

Once you have the temporary file above use zabbix_sender and execute it using one of the following command lines.

zabbix_sender -c <Zabbix Agent Config File> -i <Temporary File>
zabbix_sender -s <Host Name> -c <Zabbix Agent Config File> -i <Temporary File>
zabbix_sender -z <Zabbix Server IP/Hostname> -i <Temporary File>
zabbix_sender -s <Host Name> -z <Zabbix Server IP/Hostname> -i <Temporary File>

e.g.

zabbix_sender -c zabbix_agentd.conf -i C:\Temp\TestJSON.tmp
zabbix_sender -s TestHost -c zabbix_agentd.conf -i C:\Temp\TestJSON.tmp
zabbix_sender -z ZabbixServer -i C:\Temp\TestJSON.tmp
zabbix_sender -s TestHost -z ZabbixServer -i C:\Temp\TestJSON.tmp

Whilst testing I would suggest also adding the -vv option to the command line to get debugging information. For example I found that I had to add the -s option to the command line, as there seems to be a bug in the zabbix_sender code where it doesn’t use the HostnameItem when Hostname is undefined.

And last but not least the discovery prototypes need setting up within Zabbix, which I wont cover here as it’s covered in the Zabbix manuals.

Announcement – GitHub Repository Now Available

I’ve had a few issue with posting scripts on WordPress as it on occasions changes special characters to their HTML equivalent for example the & has changed to &amp;, which is not good if you copy and paste the code.

For this reason I’ve setup a GitHub repository that contains all the scripts on the blog. Going forward I’ll also link to the scripts hosted on GitHib repository as well as posting them on the here.

I’d also like to in the future upload my MST transformations to GitHub. I’m just not sure on the legality of doing so, if anybody knows what the stance is on this it please let me know in the comments below.

The URL to all the scripts available is https://github.com/Maddog2050/Scripts

GPO – Deploying Java 8 Update 60

Update 19/05/2016: Added other version info.

Extracting the MSI

To extract the MSI, run the “jre-8u60-windows-i586.exe” or  “jre-8u60-windows-x64.exe” EXE do not proceed with the installation. Open the folder “%LOCALAPPDATA%Low\Oracle\Java”, depending if you ran the i586 or x64 version you will see one of the following folders.

  • jre1.8.0_60
  • jre1.8.0_60_x64

Open up the correct folder, and within the folder you will see the MSI file “jre1.8.0_60.msi”. Copy this MSI to another location then cancel the installation.

Silent Install Error

Now that you have the MSI file you have probably tried to install it from the command line using “msiexec /qb /i jre1.8.0_60.msi”. If you used a command prompt that isn’t elevated you get the following error in the event viewer, even though you elevate the MSI installation.

“Error 1722. There is a problem with this Windows Installer package. A program run as part of the setup did not finish as expected. Contact your support personnel or package vendor.”

MSI Fixes

The reason for the error above is that the MSI executes an installer that is embedded into the MSI, but when it runs this installer it doesn’t run it with administrative privileges instead it runs it in the logged on users security context. To fix this you need to modify the MSI DB with an MSI DB editor such as Orca (My personal preference is InstED http://www.instedit.com/). Open the MSI in your editor of choice and open up the table “CustomAction” and select the row “installexe” and change the value of the field “Type” to decimal 3090 or hexadecimal 0x0C12. This will set the msidbCustomActionTypeNoImpersonate bit so that it runs the embedded installer with administrative privileges.

Once the change above has been made the installer will now fail with the following error.

“Unable to install Java. Unable to open file C:\ProgramData\Oracle\Java\java.settings.cfg. Check that the configuration file exists and that the path to the file is correct.”

To fix this error an empty configuration file “java.settings.cfg” needs to be added to the “%ALLUSERSPROFILE%\Oracle\Java” folder by the installer. To do this we need to add 6 new entries to various tables in the MSI DB.

Once again open the MSI in your editor of choice and perform the following:

  1. Insert a new row into the table “Directory”
    • Directory Field = CommonAppDataFolder
    • Directory_Parent Field = TARGETDIR
    • DefaultDir Field = .:Common~1|CommonAppData
  2. Insert a new row into the table “Directory”
    • Directory Field = OracleDir
    • Directory_Parent Field = CommonAppDataFolder
    • DefaultDir Field = Oracle
  3. Insert a new row into the table “Directory”
    • Directory Field = JavaDir
    • Directory_Parent Field = OracleDir
    • DefaultDir Field = Java
  4. Insert a new row into the table “Component”
    • Component Field = emptycfgComponent
    • ComponentId Field = <Insert GUID>
    • Directory_  Field = JavaDir
    • Attributes Field = Decimal 0 or Hexadecimal 0x0000
    • Condition Field = <null>
    • KeyPath Field = <null>
  5. Insert a new row into the table “FeatureComponents”
    • Feature_ Field = jrecore
    • Component_ Field = emptycfgComponent
  6. Insert a new row into the table “File”
    • File Field = java.settings.cfg
    • Component_ Field = emptycfgComponent
    • FileName Field = java~1.cfg|java.settings.cfg
    • FileSize Field = 0
    • Version Field = <null>
    • Language Field = <null>
    • Attributes Field = Decimal 8192 or Hexidecimal 0x2000
    • Sequence Field = 2
  7. Insert a new row into the table “Media”
    • DiskId Field = 2
    • LastSequence Field = 2
    • DiskPrompt Field = <null>
    • Cabinet Field = <null>
    • VolumeLabel Field = <null>
    • Source Field = <null>
  8. Insert a new row into the table “RemoveFile”
    • FileKey Field = java.settings.cfg
    • Component_ Field = emptycfgComponent
    • FileName Field = java~1.cfg|java.settings.cfg
    • DirProperty Field = JavaDir
    • InstallMode Field = 3

This adds a reference to the file in the installer DB, now you need to create an empty “java.settings.cfg” file. To do this open the folder where the MSI is located and create the folder structure “CommonAppData\Oracle\Java” and then within the “Java” folder create an empty file called “java.settings.cfg”.

The last thing to be done is to set the embedded installer so that it installs silently when the UI level is set to “Basic UI” (/qb switch) , the current configuration is that it only installs silently if the UI level is set to “No UI” (/qn switch). To change this open the MSI in your editor and open the table “InstallExecuteSequence”, within that table locate the action “SetSilentInstall” and change the condition from “UILevel=2” to “UILevel<=3”.

With the changes above you will find that the MSI installer should work as expected.

Customisations

There are many articles out on the web on how to customise the installation of Java 7 by changing/adding properties to the “Properties” table in the MSI, the same properties still apply. Here are the ones that I’ve chosen to set in our deployment.

Disable Java Auto Update

  • AUTO_UPDATE=0
  • AUTOUPDATECHECK=0
  • JU=0
  • JAVAUPDATE=0

Disable the EULA

  • EULA=0

Disable the installation Java with sponsored software

  • SPONSORS=0

Lower the web Java security level (Note: High is the lowest setting in Java 8)

  • WEB_JAVA_SECURITY_LEVEL=H

Disable the sending of  installation-related statistics to Oracle

  • WEB_ANALYTICS=0

Transform File (MST)

Once I’ve amended the MSI file I create a transform file, with InstED this is an easy process of comparing your modified MSI with an unmodified file. I then use this for both the X86 and X64 versions of the Java MSI and it’ll hopefully it’ll be compatible with the next version that comes out, which saves time and effort of doing this again :-).

Deployment

I’ve only tested the deployment through the command line with both elevated and un-elevated command prompts, other people have deployed Java 8 based on my previous post via GPO successfully so it will more than likely work for this version as well.

Other Versions

There have been reports in the comments that this will also works for the newer versions of Java 8. I haven’t personally verified that they work as my work and home life are hectic at the moment, and at the time of writing I believe it works for the following versions.

  • Java 8 Update 92
  • Java 8 Update 91
  • Java 8 Update 77
  • Java 8 Update 74
  • Java 8 Update 73
  • Java 8 Update 72
  • Java 8 Update 71
  • Java 8 Update 66
  • Java 8 Update 65

GPO – Deploying Java 8 Update 25

Update 09/09/2015: If you are deploying Java 8 Update 60 please see my updated post GPO – Deploying Java 8 Update 60 as Oracle have made some changes to the MSI that means the instructions below no longer work.

Extracting the MSI

To extract the MSI, run the “jre-8u25-windows-i586.exe” or  “jre-8u25-windows-x64.exe” EXE do not proceed with the installation. Open the folder “%LOCALAPPDATA%Low\Sun\Java”, depending if you ran the i586 or x64 version you will see one of the following folders.

  • jre1.8.0_25
  • jre1.8.0_25_x64

Open up the correct folder, and within the folder you will see the MSI file “jre1.8.0_25.msi”. Copy this MSI to another location then cancel the installation.

Silent Install Error

Now that you have the MSI file you have probably tried to install it from the command line using “msiexec /qb /i jre1.8.0_25.msi”. If you used a command prompt that isn’t elevated you get the following error in the event viewer, even though you elevate the MSI installation.

“Error 1722. There is a problem with this Windows Installer package. A program run as part of the setup did not finish as expected. Contact your support personnel or package vendor.”

MSI Fixes

The reason for the error above is that the MSI executes an installer that is embedded into the MSI, but when it runs this installer it doesn’t run it with administrative privileges instead it runs it in the logged on users security context. To fix this you need to modify the MSI DB with an MSI DB editor such as Orca (My personal preference is InstED http://www.instedit.com/). Open the MSI in your editor of choice and open up the table “CustomAction” and select the row “installexe” and change the value of the field “Type” to decimal 3074 or hexadecimal 0x0C02. This will set the msidbCustomActionTypeNoImpersonate bit so that it runs the embedded installer with administrative privileges.

Once the change above has been made the installer will now fail with the following error.

“Unable to install Java. Unable to open file C:\ProgramData\Oracle\Java\java.settings.cfg. Check that the configuration file exists and that the path to the file is correct.”

To fix this error an empty configuration file “java.settings.cfg” needs to be added to the “%ALLUSERSPROFILE%\Oracle\Java” folder by the installer. To do this we need to add 6 new entries to various tables in the MSI DB.

Once again open the MSI in your editor of choice and perform the following:

  1. Insert a new row into the table “Directory”
    • Directory Field = OracleDir
    • Directory_Parent Field = CommonAppDataFolder
    • DefaultDir Field = Oracle
  2. Insert a new row into the table “Directory”
    • Directory Field = JavaDir
    • Directory_Parent Field = OracleDir
    • DefaultDir Field = Java
  3. Insert a new row into the table “Component”
    • Component Field = emptycfgComponent
    • ComponentId Field = <Insert GUID>
    • Directory_  Field = JavaDir
    • Attributes Field = Decimal 0 or Hexadecimal 0x0000
    • Condition Field = <null>
    • KeyPath Field = <null>
  4. Insert a new row into the table “FeatureComponent”
    • Feature_ Field = jrecore
    • Component_ Field = emptycfgComponent
  5. Insert a new row into the table “File”
    • File Field = java.settings.cfg
    • Component_ Field = emptycfgComponent
    • FileName Field = java~1.cfg|java.settings.cfg
    • FileSize Field = 0
    • Version Field = <null>
    • Language Field = <null>
    • Attributes Field = Decimal 8192 or Hexidecimal 0x2000
    • Sequence Field = 1
  6. Insert a new row into the table “Media”
    • DiskId Field = 2
    • LastSequence Field = 1
    • DiskPrompt Field = <null>
    • Cabinet Field = <null>
    • VolumeLabel Field = <null>
    • Source Field = <null>

This adds a reference to the file in the installer DB, now you need to create an empty “java.settings.cfg” file. To do this open the folder where the MSI is located and create the folder structure “CommonAppData\Oracle\Java” and then within the “Java” folder create an empty file called “java.settings.cfg”.

The last thing to be done is to set the embedded installer so that it installs silently when the UI level is set to “Basic UI” (/qb switch) , the current configuration is that it only installs silently if the UI level is set to “No UI” (/qn switch). To change this open the MSI in your editor and open the table “InstallExecuteSequence”, within that table locate the action “SetSilentInstall” and change the condition from “UILevel=2” to “UILevel<=3”.

With the changes above you will find that the MSI installer should work as expected.

Customisations

There are many articles out on the web on how to customise the installation of Java 7 by changing/adding properties to the “Properties” table in the MSI, the same properties still apply. Here are the ones that I’ve chosen to set in our deployment.

Disable Java Auto Update

  • AUTO_UPDATE=0
  • AUTOUPDATECHECK=0
  • JU=0
  • JAVAUPDATE=0

Disable the EULA

  • EULA=0

Disable the installation Java with sponsored software

  • SPONSORS=0

Lower the web Java security level (Note: High is the lowest setting in Java 8)

  • WEB_JAVA_SECURITY_LEVEL=H

Disable the sending of  installation-related statistics to Oracle

  • WEB_ANALYTICS=0

Transform File (MST)

Once I’ve amended the MSI file I create a transform file, with InstED this is an easy process of comparing your modified MSI with an unmodified file. I then use this for both the X86 and X64 versions of the Java MSI and it’ll hopefully it’ll be compatible with the next version that comes out, which saves time and effort of doing this again :-).

Deployment

I’ve only tested the deployment through the command line with both elevated and un-elevated command prompts. My plan is to deploy Java 8 using GPO, but I’ve not managed to test this yet, I will update this post once I have . If you do manage to test deploying via GPO before I do, please let me know and I’ll update this post accordingly.

 

AD – Force SYSVOL and AD replication

Update 17/03/2016: Added a download link for the script.

Recently I’ve been doing a lot of work on group policies and due to the nature of our network replication between our domain controllers is slow. This was causing me issues when testing my changes as they hadn’t replicated to some domain controllers. Knowing that group policies consist of two parts files located in the SYSVOL and a version attribute in AD, I wanted a quick way of replicating my changes to all DC’s within our domain.

Below is a batch file that I written to do this.

Update 17/08/2015 : Now automatically determines all domains in a forest, and forces the KCC to recalculate.

@ECHO OFF

REM Location of the ntfrsutil tool from the File Replication Service Diagnostics Tool.
REM This can be downloaded from: http://www.microsoft.com/en-gb/download/details.aspx?id=8613
SET NTFRSUTL="C:\Program Files (x86)\Windows Resource Kits\Tools\FRSDiag\ntfrsutl.exe"

CALL :ForceKCCUpdate

REM Get the forest partition dn without specifying the parent domain.
FOR /F %%p IN ('dsquery * forestroot -scope subtree -filter "(objectClass=crossRefContainer)" -l -limit 0') DO (

	REM Get all parent/child domains from the forest configuration.
	FOR /F %%d IN ('dsquery * %%p -scope subtree -filter "(&(objectClass=crossRef)(nETBIOSName=*))" -attr dnsRoot -l -limit 0') DO (
		CALL :ReplicateDomain %%d
	)
)

GOTO END

:ReplicateDomain
	ECHO Replicating Domain: %1
	
	REM Replicate SYSVOL.
	FOR /F %%f IN ('DsQuery Server -domain %1 -limit 0 -o rdn') DO (
		FOR /F %%t IN ('DsQuery Server -domain %1 -limit 0 -o rdn') DO (
			IF /I "%%f" NEQ "%%t" (
				ECHO Replicating SYSVOL from %%f to %%t
				%NTFRSUTL% forcerepl %%t /r "Domain System Volume (SYSVOL share)" /p %%f
			)
		)
	)

	REM Replicate AD.
	ECHO Replicating AD
	repadmin /syncall %1 /APed

GOTO END

:ForceKCCUpdate
	ECHO Forcing KCC Update

	REM Force the KCC to recalculate in all sites.
	FOR /F %%s IN ('DsQuery Site -limit 0 -o rdn') DO (
		repadmin /kcc site:%%s
	)

GOTO END

:END

Download (Right click and click ‘Save Link as’)

vSphere – ‘inaccessible’ VM’s

Update 17/03/2016: Added a download link for the script.

Recently we had a power  blip in our comms room where I work, this caused some of our VM’s to show as inaccessible. After a little reading I found that you could reload the configuration of the VM’s to remedy this issue.

Below is a PowerShell/PowerCLI script that I used to automate this.

# Refresh all VM's

param (
	[string]$server = $(Throw "parameter 'server' is required!"),
	[string]$username,
	[string]$password
)

# Connect to the specified server
If ($username -eq "") {
	# Connect to server without username & password
	Connect-VIServer -Server $server
}
ElseIf ($username -ne "" -and $password -eq "") {
	# Connect to server with username only
	Connect-VIServer -Server $server -User $username
}
Else{
	# Connect to server with username & password
	Connect-VIServer -Server $server -User $username -Password $password
}

# Get all VM's, excluding templates
$vms = Get-View -ViewType VirtualMachine -Property Name -Filter @{"Config.Template"="false"}
foreach($vm in $vms){
    $vm.reload()
}

Download (Right click and click ‘Save Link as’)

Example usage:

C:\>.\RefreshVMs.ps1 -server <server>
C:\>.\RefreshVMs.ps1 -server <server> -username <username>
C:\>.\RefreshVMs.ps1 -server <server> -username <username> -password <password>

GPO – Issue Deploying A Scheduled Task Running As “SYSTEM”

Recently whilst doing our windows 8.1 deployment I came across an issue where a computer based schedule task running as “SYSTEM” wasn’t applying. After doing some research and trying a few things depending how you set the task up you got one of the two error below:

  1. The computer ‘********’ preference item in the ‘OU Policies {********}’ Group Policy object did not apply because it failed with error code ‘0x80070534 No mapping between account names and security IDs was done.’ This error was suppressed.
  2. The computer ‘********’ preference item in the ‘OU Policies {********}’ Group Policy object did not apply because it failed with error code ‘0x80041316 The task XML contains an unexpected node.’ This error was suppressed.

Both the error codes point to the same issue, when creating a schedule task that runs as “NT AUTHORITY\SYSTEM”

The issue lies in the fact that the schedule task runs is set to run as the “SYSTEM” account. In the group policy preferences “Schedule Task (Windows Vista and later)” window you get two different results when looking up the system account.

  1. You get “NT AUTHORITY\SYSTEM” when you lookup the account on a domain.
  2. You get “BUILTIN\SYSTEM” when you lookup the account on a computer.

When you look it up by computer, it appears as if it’s working correctly as the security options grey out. When the policy is deployed though the computer it’s unable to lookup “BUILTIN\SYSTEM” as a security principal and fails to deploy (See error 1). When looked up by domain or by manually entering “NT AUTHORITY\SYSTEM” the security options do not grey out. Again when it’s deployed to a computer it fails with the error that it’s unable to deploy the task as it has an unexpected XML node (See error 2).

The only way I’ve found to work around this issue is to:

  1. Set the user as “NT AUTHORITY\SYSTEM”.
  2. Select the “Run only when user is logged on” option.
  3. Manually edit the XML file that the policy creates, and remove the XML node <LogonType>InteractiveToken</LogonType> from the task in question.

The XML file for the schedule tasks (1 file per group policy, multiple tasks per file) can be located in this location on the domain:

\\<DNSDomainName>\sysvol\<DNSDomainName>\Policies\<GroupPolicyUniqueID>\Machine\Preferences\ScheduledTasks\ScheduledTasks.xml

Here are the contents of the file with the XML node still in it. To make the file readable I have expanded the XML.

<?xml version="1.0" encoding="utf-8"?>
<ScheduledTasks clsid="{CC63F200-7309-4ba0-B154-A71CD118DBCC}">
  <TaskV2 clsid="{D8896631-B747-47a7-84A6-C155337F3BC8}" name="EMET Config Refresh" image="1" changed="2014-09-10 12:31:37" uid="{4501D60E-1D83-45A1-8A51-0D4CF9D8432A}" userContext="0" removePolicy="1">
    <Properties action="R" name="EMET Config Refresh" runAs="NT AUTHORITY\SYSTEM" logonType="Group">
      <Task version="1.3">
        <RegistrationInfo>
          <Author>TEST\AdminUser</Author>
          <Description></Description>
        </RegistrationInfo>
        <Principals>
          <Principal id="Author">
            <RunLevel>HighestAvailable</RunLevel>
            <GroupId>NT AUTHORITY\SYSTEM</GroupId>
            <LogonType>InteractiveToken</LogonType>
          </Principal>
        </Principals>
        <Settings>
          <IdleSettings>
            <Duration>PT5M</Duration>
            <WaitTimeout>PT1H</WaitTimeout>
            <StopOnIdleEnd>false</StopOnIdleEnd>
            <RestartOnIdle>false</RestartOnIdle>
          </IdleSettings>
          <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
          <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
          <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
          <AllowHardTerminate>true</AllowHardTerminate>
          <AllowStartOnDemand>true</AllowStartOnDemand>
          <Enabled>true</Enabled>
          <Hidden>false</Hidden>
          <ExecutionTimeLimit>P3D</ExecutionTimeLimit>
          <Priority>7</Priority>
        </Settings>
        <Triggers>
          <EventTrigger>
            <Enabled>true</Enabled>
            <Subscription>&lt;QueryList&gt;&lt;Query Id="0" Path="Application"&gt;&lt;Select Path="Application"&gt;*[System[Provider[@Name='SceCli'] and EventID=1704]]&lt;/Select&gt;&lt;/Query&gt;&lt;/QueryList&gt;</Subscription>
          </EventTrigger>
        </Triggers>
        <Actions>
          <Exec>
            <Command>%ProgramFiles(x86)%\EMET 5.0\EMET_Conf.exe</Command>
            <Arguments>--refresh</Arguments>
          </Exec>
        </Actions>
      </Task>
    </Properties>
  </TaskV2>
</ScheduledTasks>

After this has been done the schedule task will deploy and work as expected, but if the scheduled task that was modifed is edited you will need to reapply this workaround.

As of writing this issue still exists in Windows Server 2012 R2.

AD – Reset the pwdLastSet attribute using PowerShell

Update 17/03/2016: Added a download link for the script.

I had a requirement to change some of our AD accounts so that the password expired as per our company policy. Instead of having to call every user to see if they were on-site or not, I wanted a way of making the account adhere without causing the account to expire immediately. After a little look around the internet I found that you could reset the password last set date in AD which would cause the account to expire after x days that our policy defines with all the usual prompts.

Below is a Powershell script that I created to achieve this.

# This script sets a users account so that the password is to expire as per our policy,
# and resets the last password change date so that the user doesn't need login and change
# their password straight away.

# Define input parameters the script can accept.
param
(
	[Parameter(Mandatory=$True)]
	[string]$SearchBase,

	[Parameter(Mandatory=$True)]
	[string]$DNSDomainName,

	[Parameter(Mandatory=$True)]
	[string]$sAMAccountName,

	[bool]$Change = $False,

	[string]$LogFile = $MyInvocation.MyCommand.Name + ".log"
)

$Culture = Get-Culture
If ((Test-Path $Logfile) -eq $False)
{
	# Add headers to the LogFile if it doesn't already exist.
	Add-Content $LogFile "sAMAccountName, LastChange, Today, Changed"
}

# Get the user & properties from AD
$ADUser = Get-ADUser -Filter {sAMAccountName -eq $sAMAccountName} -SearchScope Subtree -SearchBase $SearchBase -Properties Name,pwdLastSet,PasswordNeverExpires -Server $DNSDomainName

# Check that user exist before going further.
If($ADUser -eq $Null)
{
	Write-Host "User not found. Aborting."
}
Else
{
	# Get the sAMAccountName from AD (Don't rely on the users input)
	$ADsAMAccountName = $ADUser.sAMAccountName

	# Get todays date and format it correctly.
	$Today = Get-Date -Format ($Culture.DateTimeFormat.FullDateTimePattern)

	# Get the date of the last password change and format it correctly.
	$LastChange = Get-Date -Date ([DateTime]::FromFileTime($ADUser.pwdLastSet)) -Format ($Culture.DateTimeFormat.FullDateTimePattern)

	If ($Change -eq $True)
	{
		# Set the password to expired, must be done first.
		$ADUser.pwdLastSet = 0
		# Set the account so that the password expires.
		$ADUser.PasswordNeverExpires = $False
		# Save the changes
		Set-ADUser -Instance $ADUser -Server $DNSDomainName

		# Reset the date of the last password change to today.
		$ADUser.pwdLastSet = -1
		# Save the changes
		Set-ADUser -Instance $ADUser -Server $DNSDomainName

		# Inform the user of the script that the account was changed.
		Write-Host "Account Changed."
	}

	# Log the change to the LogFile.
	Add-Content $LogFile "$ADsAMAccountName, $LastChange, $Today, $Change"
}

Download (Right click and click ‘Save Link as’)

Example syntax for the script

./<script>.ps1 -SearchBase "DC=contoso,DC=lan" -DNSDomainName "contoso.lan" -Change $True -sAMAccountName <accountName>

Palo Alto – Backup The Configuration For Restore

Recently I needed to get a hold of the configuration file that we were able to easily restore to another device in the event of a hardware failure. To perform this task we tried using RANCID but all it does is capture the output of

user@hostname> set cli config-output-format default
user@hostname> show config running

or

user@hostname> set cli config-output-format xml
user@hostname> show config running

Unfortunately the output of these commands are not easily restored to another device in the event of a hardware failure.

To get a configuration backup that you can reload easily on a new/existing device you need to get a copy of the proper XML configuration file. The way to get this is with the following command:

user@hostname> tftp export configuration from running-config.xml to <TFTP Server>

Once you have this you are able to load it back onto a device with no fuss or messing about.

Update: I did eventually get RANCID backing up the XML file that’s TFTP’d from the device with some custom scripts that I wrote, it’s a bit of a fudge but it works.