Getting Data In

Powershell unattended installation

Champion

How would you go about creating an unattend intallation on a Windows. I need a script for hte following reason:

  • constancy with base installation (people don't always follow directions and save time trouble shooting).
  • I dislike installing things by hand.
  • I won't have physical or remote terminal access to all Installations.
  • Didn't want to share my passwords (at least obfuscate them).
  • Handle installation and initial configuration not performed by Deployment Server.

Does anyonehave any good examples or ideas.

1 Solution

Champion

I soloved my problem using a couple of Powershell scripts for a scripted unattended install and wanted to share them with the community. Please keep in mind that this is my first Powershell script and I played around with a few methods, so not the pretties. The there are two scripts, the installer and encoder/decoder which I borrowed from http://blogs.metcorpconsulting.com. These scripts are provided as is.

Note: the script is run on a trusted box. Installation tests where performed with Splunkbeta 5.0.

The base64encodedecode.ps1 script generates the base64 encoded passwords and splunkinstaller.ps1 is ran locally on you soon to be Splunk instance. splunkinstaller.ps1 assumes all files are in the same directory as the itself. All other settings will come from the Deployment Server.

The splunkinstaller.ps1 could use a subroutine for added users and roles.

Any feed back would be great.


#base64encodedecode.ps1
Param(
[string][alias("p")]$password,
[switch][alias("e")]$encode,
[switch][alias("d")]$decode
)
If($encode){
## Display & Log Base64 Encoded password
$encoded = [System.Text.Encoding]::UTF8.GetBytes($password)
$encodedPassword = [System.Convert]::ToBase64String($encoded)
}
If($decode){
## Display & Log Base64 Decoded password
$decoded = [System.Convert]::FromBase64String($password1)
$decodedpassword = [System.Text.Encoding]::UTF8.GetString($decoded)
}

The script below has set default values for the unattended installation as well as creates a second user with the admin role.


#splunkinstaller.ps1
#default parameters and other options
Param(
[string][alias("id")] $installdir = $(if((Test-Path -Path "D:\")){"`"D:\Program Files\Splunk`""}else{"`"C:\Program Files\Splunk`""}),
[string][alias("ds")] $deployserver = "hellokitty`:8089",
[switch][alias("du")]$defaultUser,
[ValidateSet(0,1)][int][alias("s")]$start = 1,
[string][alias("u")]$domainuser = $(if($defaultUser){"mydomain\myuser"}),
[string][alias("p")]$password = $(if($defaultUser){"Y2ldmU="})
)
#var initallization
$splunkprocesses = @()
$pw1='JHBsrMQDQ='
$pw2="YldmWU="
$match = 0
$regex2 = [regex]'(?i)[\d\w\W\D]+splunkbeta[\d\w\W\D]+'
$regex1 = [regex]'[\d\w]+VM[\d\w]+'
#Functions
Function decoder($decode)
{
$decoded = [System.Convert]::FromBase64String($decode)
$decodedpd = [System.Text.Encoding]::UTF8.GetString($decoded)
return $decodedpd
}
Function ckinst($appname)
{
$installed = Get-WmiObject -Class Win32_Product | Where-object{$_.name -like "*$appname*"}
If($installed){ return "True"}else{return "False"}
}
Function pstart([string]$exec,[string]$argments)
{
$process = New-Object System.Diagnostics.Process
$process.StartInfo.FileName = $exec
$process.StartInfo.RedirectStandardError = 1
$process.StartInfo.RedirectStandardOutput = 1
$process.StartInfo.UseShellExecute = 0
if($argments){write-host $args;$process.StartInfo.Arguments = $argments}
$process.Start() | Out-Null
$process.WaitForExit() | Out-Null
$errorstream = $process.StandardError.ReadToEnd()
$stdoutstream = $process.StandardOutput.ReadToEnd()
if($errorstream)
{
write-host "Error occurred during Execution of $exec with the following arguments: $argments"
Exit 4
}elseif($stdoutstream)
{
write-host $stdoutstream
}
}

#building command line string for install
$comstr = " INSTALLDIR=$installdir DEPLOYMENT_SERVER=`"$deployserver`" LAUNCHSPLUNK=$start"
if($defaultUser)
{
$password = decoder($password)
$comstr += " LOGON_USERNAME=`"$domainuser`" LOGON_PASSWORD=$password"
}
elseif($domainuser -and $password)
{
$comstr += " LOGON_USERNAME=""$domainuser"" LOGON_PASSWORD=`"$password`""
}elseif(($domainuser -and !$password) -or (!$domainuser -and $password))
{
write-host "Warn: domainuser and password must both be defined"
Exit 4
}
#finding running path and executables
$scriptpath = $MyInvocation.Mycommand.Path
$rdir = Split-Path $scriptpath
$files = get-childitem $rdir
$match = $files | ForEach-Object {$regex2.Matches($_.FullName)}
#checking to see if Splunk is already installed
$x = ckinst("splunk")
if($x -eq "True"){write-host "Splunk already installed Exiting";Exit}else{Write-Host "Installing Splunk"}
#running installation
if($match -ne 0)
{
pstart "msiexec" "/i $match$comstr /quiet"
Start-Sleep -s 10
$x = ckinst("splunk")
if($x -eq "True"){write-host "Splunk successfully installed"}else{Write-Host "Splunk installed failed"; Exit}
}else
{
write-host "msi or executable not found"
Exit 4
}
$installdir = $installdir.Replace("`"","")
#verifing services
write-host "Verifying Services"
$splunkprocesses = get-service | where-object{$_.Name -like "*splunk*"}
if ($splunkprocesses.length -ne 0)
{
write-host "services verified"
#changing user information
write-host "changing user info"
$installdir = $installdir.Replace("`"","")
$splunkexe = "`"$installdir\bin\splunk.exe`""
$pw1 = decoder($pw1)
$pw2 = decoder($pw2)
pstart $splunkexe "add user splunk_local -password $pw1 -role admin -auth admin:changeme"
pstart $splunkexe "edit user admin -password $pw2 -role admin -auth admin:changeme"
New-Item "$installdir\etc\.ui_login" -type "file" -force | Out-Null
write-host "User Info Changed"
if($start -eq 1)
{
write-host "Restarting Splunk"
pstart $splunkexe "restart"
Start-Sleep -s 2
write-host "Restart Complete"
}
}else
{
write-host "Services do not appear to be installed correctly. Verification required."
Exit 4
}
write-host "Done"
Exit

Update and streamlined for Heavy Forwarder Install:


#var initallization
$installdir = "C:\Program Files\Splunk"
$splunkprocesses = @()
$deploy = 'server.yourdomain.com:8089' #Splunk Deployment server
$var1='MWwxaB0QA==' #base64 encoded password
$var2='NDBZG0z' #base64 encoded password
$match = 0
$regex2 = [regex]'(?i)[\d\w\W\D]+splunk-5.[\d\w\W\D]+.msi'
$regex1 = [regex]'[\d\w]+VM[\d\w]+'
#Functions
Function decoder($decode)
{
$decoded = [System.Convert]::FromBase64String($decode)
$decodedpd = [System.Text.Encoding]::UTF8.GetString($decoded)
return $decodedpd
}
Function ckinst($appname)
{
write-host "Checking Win32_Product for SPlunk"
$installed = Get-WmiObject -Class Win32_Product | Where-object{$_.name -like "*$appname*"}
If($installed){ return "True"}else{return "False"}
}
Function pstart([string]$exec,[string]$argments)
{
$process = New-Object System.Diagnostics.Process
$process.StartInfo.FileName = $exec
$process.StartInfo.RedirectStandardError = 1
$process.StartInfo.RedirectStandardOutput = 1
$process.StartInfo.UseShellExecute = 0
if($argments){$process.StartInfo.Arguments = $argments}
$process.Start() | Out-Null
$process.WaitForExit() | Out-Null
$errorstream = $process.StandardError.ReadToEnd()
$stdoutstream = $process.StandardOutput.ReadToEnd()
if($errorstream)
{
write-host "Error occurred during Execution of $exec with the following arguments: $argments"
Exit 4
}elseif($stdoutstream)
{
write-host $stdoutstream
}
}
#building command line string for install
$comstr = " INSTALLDIR=`"$installdir`" SPLUNK_APP=`"SplunkForwarder`""
#finding running path and executables
$scriptpath = $MyInvocation.Mycommand.Path
$rdir = Split-Path $scriptpath
$files = get-childitem $rdir
$match = $files | ForEach-Object {$regex2.Matches($_.FullName)}
#checking to see if Splunk is already installed
$x = ckinst("splunk")
if($x -eq "True"){write-host "Splunk already installed Exiting";Exit}else{Write-Host "Installing Splunk"}
#running installation
if($match -ne 0)
{
write-host "msiexec /i $match$comstr /quiet"
pstart "msiexec" "/i $match$comstr /quiet"
Start-Sleep -s 10 | Out-Null
$x = ckinst("splunk")
if($x -eq "True"){write-host "Splunk successfully installed"}else{Write-Host "Splunk installed failed"; Exit}
}else
{
write-host "msi or executable not found"
Exit 4
}
$installdir = $installdir.Replace("`"","")
#verifing services
write-host "Verifying Services"
$splunkprocesses = get-service | where-object{$_.Name -like "*splunk*"}
if ($splunkprocesses.length -ne 0)
{
write-host "services verified"
#changing user information
write-host "changing user info"
$splunkexe = "`"$installdir\bin\splunk.exe`""
pstart $splunkexe "disable webserver -auth admin:changeme"
write-host "Webserver disabled for Heavy Forwarder"
New-Item "$installdir\etc\system\default\deploymentclient.conf" -type "file" -Value "[target-broker:deploymentServer]`ntargetUri = $deploy`n
write-host "Deloyment Server set to $deploy"
$var1 = decoder($var1)
$var2 = decoder($var2)
pstart $splunkexe "add user splunk_local -password "$var2" -role admin -auth admin:changeme"
write-host "splunk_local added"
pstart $splunkexe "edit user admin -password "$var1" -role admin -auth admin:changeme"
write-host "passwords changed"
pstart $splunkexe "stop"
}else
{
write-host "Services do not appear to be installed correctly. Verification required."
Exit 4
}
write-host "Adding Splunk bin to Machine Environment Path"
$CurrentValue = [Environment]::GetEnvironmentVariable("Path", "Machine")
if(!$CurrentValue.contains($installdir)){ [Environment]::SetEnvironmentVariable("Path", $CurrentValue + ";$installdir\bin", "Machine")}else{write-host "$installdir\bin already exists"}
write-host "Done"
Exit

View solution in original post

Path Finder

I didn't use powershell but this is how I solved the password issue:

  • silent install msi with flags AGREETOLICENSE=Yes LAUNCHSPLUNK=0 SERVICESTARTTYPE=auto
  • remove ca.pem, cacert.pem
  • remove *.conf from system/local/
  • remove everything from var/
  • create a blank file called ftr in $SPLUNK_HOME
  • copy over your splunk.secret to auth folder (use same splunk.secret file)
  • copy over your passwd file to etc folder (use same passwd file)
  • copy over an app with deploymentclient.conf in it pointing to your DS
  • splunk start --accept-license --answer-yes --no-prompt

The idea being that if all forwarders use the same splunk.secret seed file, the hashed passwords will be identical across. Then, you can push out apps that already have the hashed passwords in conf files without sending cleartext over the wire.
Similarly, overwriting default passwd file with my own, not only do I get rid of the default changeme password as a security precaution, I also automatically create all the accounts I need in one go.
No more cleartext passwords. No more wondering if you typoed a password and having no way to check.
Single master admin password that works on all of my splunk machines and easy visual verification that the password hashes are correct.

Cheers

0 Karma

Champion

I soloved my problem using a couple of Powershell scripts for a scripted unattended install and wanted to share them with the community. Please keep in mind that this is my first Powershell script and I played around with a few methods, so not the pretties. The there are two scripts, the installer and encoder/decoder which I borrowed from http://blogs.metcorpconsulting.com. These scripts are provided as is.

Note: the script is run on a trusted box. Installation tests where performed with Splunkbeta 5.0.

The base64encodedecode.ps1 script generates the base64 encoded passwords and splunkinstaller.ps1 is ran locally on you soon to be Splunk instance. splunkinstaller.ps1 assumes all files are in the same directory as the itself. All other settings will come from the Deployment Server.

The splunkinstaller.ps1 could use a subroutine for added users and roles.

Any feed back would be great.


#base64encodedecode.ps1
Param(
[string][alias("p")]$password,
[switch][alias("e")]$encode,
[switch][alias("d")]$decode
)
If($encode){
## Display & Log Base64 Encoded password
$encoded = [System.Text.Encoding]::UTF8.GetBytes($password)
$encodedPassword = [System.Convert]::ToBase64String($encoded)
}
If($decode){
## Display & Log Base64 Decoded password
$decoded = [System.Convert]::FromBase64String($password1)
$decodedpassword = [System.Text.Encoding]::UTF8.GetString($decoded)
}

The script below has set default values for the unattended installation as well as creates a second user with the admin role.


#splunkinstaller.ps1
#default parameters and other options
Param(
[string][alias("id")] $installdir = $(if((Test-Path -Path "D:\")){"`"D:\Program Files\Splunk`""}else{"`"C:\Program Files\Splunk`""}),
[string][alias("ds")] $deployserver = "hellokitty`:8089",
[switch][alias("du")]$defaultUser,
[ValidateSet(0,1)][int][alias("s")]$start = 1,
[string][alias("u")]$domainuser = $(if($defaultUser){"mydomain\myuser"}),
[string][alias("p")]$password = $(if($defaultUser){"Y2ldmU="})
)
#var initallization
$splunkprocesses = @()
$pw1='JHBsrMQDQ='
$pw2="YldmWU="
$match = 0
$regex2 = [regex]'(?i)[\d\w\W\D]+splunkbeta[\d\w\W\D]+'
$regex1 = [regex]'[\d\w]+VM[\d\w]+'
#Functions
Function decoder($decode)
{
$decoded = [System.Convert]::FromBase64String($decode)
$decodedpd = [System.Text.Encoding]::UTF8.GetString($decoded)
return $decodedpd
}
Function ckinst($appname)
{
$installed = Get-WmiObject -Class Win32_Product | Where-object{$_.name -like "*$appname*"}
If($installed){ return "True"}else{return "False"}
}
Function pstart([string]$exec,[string]$argments)
{
$process = New-Object System.Diagnostics.Process
$process.StartInfo.FileName = $exec
$process.StartInfo.RedirectStandardError = 1
$process.StartInfo.RedirectStandardOutput = 1
$process.StartInfo.UseShellExecute = 0
if($argments){write-host $args;$process.StartInfo.Arguments = $argments}
$process.Start() | Out-Null
$process.WaitForExit() | Out-Null
$errorstream = $process.StandardError.ReadToEnd()
$stdoutstream = $process.StandardOutput.ReadToEnd()
if($errorstream)
{
write-host "Error occurred during Execution of $exec with the following arguments: $argments"
Exit 4
}elseif($stdoutstream)
{
write-host $stdoutstream
}
}

#building command line string for install
$comstr = " INSTALLDIR=$installdir DEPLOYMENT_SERVER=`"$deployserver`" LAUNCHSPLUNK=$start"
if($defaultUser)
{
$password = decoder($password)
$comstr += " LOGON_USERNAME=`"$domainuser`" LOGON_PASSWORD=$password"
}
elseif($domainuser -and $password)
{
$comstr += " LOGON_USERNAME=""$domainuser"" LOGON_PASSWORD=`"$password`""
}elseif(($domainuser -and !$password) -or (!$domainuser -and $password))
{
write-host "Warn: domainuser and password must both be defined"
Exit 4
}
#finding running path and executables
$scriptpath = $MyInvocation.Mycommand.Path
$rdir = Split-Path $scriptpath
$files = get-childitem $rdir
$match = $files | ForEach-Object {$regex2.Matches($_.FullName)}
#checking to see if Splunk is already installed
$x = ckinst("splunk")
if($x -eq "True"){write-host "Splunk already installed Exiting";Exit}else{Write-Host "Installing Splunk"}
#running installation
if($match -ne 0)
{
pstart "msiexec" "/i $match$comstr /quiet"
Start-Sleep -s 10
$x = ckinst("splunk")
if($x -eq "True"){write-host "Splunk successfully installed"}else{Write-Host "Splunk installed failed"; Exit}
}else
{
write-host "msi or executable not found"
Exit 4
}
$installdir = $installdir.Replace("`"","")
#verifing services
write-host "Verifying Services"
$splunkprocesses = get-service | where-object{$_.Name -like "*splunk*"}
if ($splunkprocesses.length -ne 0)
{
write-host "services verified"
#changing user information
write-host "changing user info"
$installdir = $installdir.Replace("`"","")
$splunkexe = "`"$installdir\bin\splunk.exe`""
$pw1 = decoder($pw1)
$pw2 = decoder($pw2)
pstart $splunkexe "add user splunk_local -password $pw1 -role admin -auth admin:changeme"
pstart $splunkexe "edit user admin -password $pw2 -role admin -auth admin:changeme"
New-Item "$installdir\etc\.ui_login" -type "file" -force | Out-Null
write-host "User Info Changed"
if($start -eq 1)
{
write-host "Restarting Splunk"
pstart $splunkexe "restart"
Start-Sleep -s 2
write-host "Restart Complete"
}
}else
{
write-host "Services do not appear to be installed correctly. Verification required."
Exit 4
}
write-host "Done"
Exit

Update and streamlined for Heavy Forwarder Install:


#var initallization
$installdir = "C:\Program Files\Splunk"
$splunkprocesses = @()
$deploy = 'server.yourdomain.com:8089' #Splunk Deployment server
$var1='MWwxaB0QA==' #base64 encoded password
$var2='NDBZG0z' #base64 encoded password
$match = 0
$regex2 = [regex]'(?i)[\d\w\W\D]+splunk-5.[\d\w\W\D]+.msi'
$regex1 = [regex]'[\d\w]+VM[\d\w]+'
#Functions
Function decoder($decode)
{
$decoded = [System.Convert]::FromBase64String($decode)
$decodedpd = [System.Text.Encoding]::UTF8.GetString($decoded)
return $decodedpd
}
Function ckinst($appname)
{
write-host "Checking Win32_Product for SPlunk"
$installed = Get-WmiObject -Class Win32_Product | Where-object{$_.name -like "*$appname*"}
If($installed){ return "True"}else{return "False"}
}
Function pstart([string]$exec,[string]$argments)
{
$process = New-Object System.Diagnostics.Process
$process.StartInfo.FileName = $exec
$process.StartInfo.RedirectStandardError = 1
$process.StartInfo.RedirectStandardOutput = 1
$process.StartInfo.UseShellExecute = 0
if($argments){$process.StartInfo.Arguments = $argments}
$process.Start() | Out-Null
$process.WaitForExit() | Out-Null
$errorstream = $process.StandardError.ReadToEnd()
$stdoutstream = $process.StandardOutput.ReadToEnd()
if($errorstream)
{
write-host "Error occurred during Execution of $exec with the following arguments: $argments"
Exit 4
}elseif($stdoutstream)
{
write-host $stdoutstream
}
}
#building command line string for install
$comstr = " INSTALLDIR=`"$installdir`" SPLUNK_APP=`"SplunkForwarder`""
#finding running path and executables
$scriptpath = $MyInvocation.Mycommand.Path
$rdir = Split-Path $scriptpath
$files = get-childitem $rdir
$match = $files | ForEach-Object {$regex2.Matches($_.FullName)}
#checking to see if Splunk is already installed
$x = ckinst("splunk")
if($x -eq "True"){write-host "Splunk already installed Exiting";Exit}else{Write-Host "Installing Splunk"}
#running installation
if($match -ne 0)
{
write-host "msiexec /i $match$comstr /quiet"
pstart "msiexec" "/i $match$comstr /quiet"
Start-Sleep -s 10 | Out-Null
$x = ckinst("splunk")
if($x -eq "True"){write-host "Splunk successfully installed"}else{Write-Host "Splunk installed failed"; Exit}
}else
{
write-host "msi or executable not found"
Exit 4
}
$installdir = $installdir.Replace("`"","")
#verifing services
write-host "Verifying Services"
$splunkprocesses = get-service | where-object{$_.Name -like "*splunk*"}
if ($splunkprocesses.length -ne 0)
{
write-host "services verified"
#changing user information
write-host "changing user info"
$splunkexe = "`"$installdir\bin\splunk.exe`""
pstart $splunkexe "disable webserver -auth admin:changeme"
write-host "Webserver disabled for Heavy Forwarder"
New-Item "$installdir\etc\system\default\deploymentclient.conf" -type "file" -Value "[target-broker:deploymentServer]`ntargetUri = $deploy`n
write-host "Deloyment Server set to $deploy"
$var1 = decoder($var1)
$var2 = decoder($var2)
pstart $splunkexe "add user splunk_local -password "$var2" -role admin -auth admin:changeme"
write-host "splunk_local added"
pstart $splunkexe "edit user admin -password "$var1" -role admin -auth admin:changeme"
write-host "passwords changed"
pstart $splunkexe "stop"
}else
{
write-host "Services do not appear to be installed correctly. Verification required."
Exit 4
}
write-host "Adding Splunk bin to Machine Environment Path"
$CurrentValue = [Environment]::GetEnvironmentVariable("Path", "Machine")
if(!$CurrentValue.contains($installdir)){ [Environment]::SetEnvironmentVariable("Path", $CurrentValue + ";$installdir\bin", "Machine")}else{write-host "$installdir\bin already exists"}
write-host "Done"
Exit

View solution in original post

Path Finder

What is $MyInvocation?

0 Karma

Influencer

Hi,

It's a great thing to share with the community. Can I suggest one thing...

You set your question as a proper question and then answer it with the information above, you can then accept it, and it may be picked up by people as a working solution (rather than a question that has not been answered... which is how it would appear at first glance).

🙂

New Member

Is there a way to change the default 'changeme' password for the admin user within the argument list?

Example.

Invoke-Command -ComputerName $totalComputers[$i] -ScriptBlock {
Start-Process "c:splunk-6.2.3-264376-x64-release.msi" -Wait -Verbose -ArgumentList (
'AGREETOLICENSE="Yes"',
'DEPLOYMENT_SERVER="SPLUNKDEPLOY:8089"',
"/Liwem!", "C:splunkinstall.log"
) }

Need to change the password for admin before the Splunk service starts...

thanks for the input..

0 Karma