How to run a Powershell Script block with elevated privileges - sql-server-2012

I am writing a PowerShell script to archive compressed C2 Audit files to a file share. What is possibly the last problem I am having is giving the .Net compression routine the privilege to manipulate the files. During development, I could flaunt my account's admin role to propagate Full Access privileges to the files in the DATA directory. However, the script is to run from a PowerShell step in an Agent job, and I want to automate the ACL change as well.
For an added level of difficulty, I am doing this under SQL Server 2012, so I am stuck with PowerShell 2.0. I am using .Net 4.5 compression routines via a process of loading $RunActivationConfigPath with a temporary config file. I was not able to find a way to change that config file to promote the admin role, though.
This is a segment of a script by Benjamin Armstrong that checks if the connection is using Administrator privileges.
# Get the ID and security principal of the current user account
$runtimeWindowsID = [System.Security.Principal.WindowsIdentity]::GetCurrent();
$runtimeWindowsPrincipal = New-Object System.Security.Principal.WindowsPrincipal($runtimeWindowsID);
# Get the security principal for the administrator role
$adminRole = [System.Security.Principal.WindowsBuiltInRole]::Administrator;
Write-Output ("Running under "+$runtimeWindowsID.Name)
Write-Output ("PS Version "+$PSVersionTable.PSVersion.Major)
# Check to see if we are currently running as an administrator
if ($runtimeWindowsPrincipal.IsInRole($adminRole) -eq $true) {
Write-Output "We are strong."
} else {
Write-Output "We are not strong."
}
Running the script as an Agent Job step produces:
Running under NT Service\SQLSERVERAGENT
PS Version 2
We are not strong.
Running the script from sqlps in Admin mode produces:
Running under DOMAIN\myusername
PS Version 2
We are strong.
All the ways I've seen to elevate a script involve using a script file. For example, creating a new process and executing it with RunAs as the Verb. I want to avoid script files and have everything in the step. I like the added security (however small) of needing SSMS privileges to view the code.
So, here are my questions:
1) Is there a way to elevate commands in a script block?
2) Is there a way to have the PowerShell step in an Agent Job run in Admin mode?
Extra credit question:
3) If I do need to add the Agent service account to a Windows User Group, which of the two dozen groups would give that account the minimum privileges needed to alter an ACL for a file, then eventually delete it?

Related

Testing if user created in AD can be logged into on a VM

I am a QA automation engineer and in the web app I test there's a feature that creates Active Directory users.
My tools are - Selenium (Java), RemoteWebDriver, Selenium Grid (Docker)
I was trying to find ways to validate this process and came to a stop - this field (AD) is new
to me and I need to find a way to make sure the user was created and can be logged into in the
network.
I was trying to find a way to do this and came up with 2 options, where the first one is the least
preferred way:
Make a request (API? 3rd side tool?) to get the relevant user(s).
The issue:
A user created and registered in the AD doesn't necessarily mean that the client can log into it (at least by the way I understood how AD works), and so it loses the most important consequence of the feature.
Use a VM, get the AD user information (username + password: possible) and try to log into the VM using those details.
The issue:
I haven't came across a tool that does it, the closest thing is Robot class or WinAppDriver.
WinAppDriver seems like the best solution as of now although I don't know how to make the login process work since it's the process starts before the desktop is open and I don't know how to locate the username and password field, so I figured using Robot class seems like the simplest solution, if it works on a VM that is, which as of now doesn't seem like it does.
So, before advancing on learning how to use WinAppDriver with my current automation, I'd like and appreciate your opinions about the matter or if you have simpler solutions.
Thank you very much for reading!
• We can check whether a user is created successfully or not and if that user can log in to the AD domain or not by executing a script as below. It is a powershell script that auto logs in through remote desktop protocol in the other domain joined VM from an Azure domain joined VM that checks whether the recently created user can login or not.
Powershell script : -
cmdkey /list | ForEach-Object{if($_ -like "*target=TERMSRV/*"){cmdkey /del:($_ -replace " ","" -replace "Target:","")}}
echo "Connecting to 192.168.1.100"
$Server="192.168.1.100"
$User="Administrator"
$Password="AdminPassword"
cmdkey /generic:TERMSRV/$Server /user:$User /pass:$Password
mstsc /v:$Server
• In the above script, replace the ‘$user’ value by the user principal name of the newly created user, i.e., ‘$User=”testdemo#example.com”’ and the ‘$Password’ value by the password set for that user. Also, ensure that you replace and enter the correct IP address of the domain controller/AD server. Also, ensure that before executing the above powershell script, execute the below commands in an elevated (administrator privileges) powershell console.
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned
Lastly, please ensure that while creating the user, the option ‘User must change password at next logon’, ‘Account is Disabled’, ‘Password never expires’ and ‘User cannot change password’ are unchecked and not selected.
• Also, you can use the below command line script for logging in to the domain joined Azure VM through RDP protocol. In the below command, replace the ‘username’ and ‘password’ with the username and password of the user created recently to log in to the Azure VM with this command line script. Also, replace the ‘TERMSRC’ with the hostname of the server system or the domain joined VM where the specified UNC path is located and replace the ‘some_unc_path’ with the actual path UNC path of the shared directory folder. Please execute the below command through elevated (administrator privileges) command prompt.
Command script: -
c:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -nolog -command cmdkey /generic:TERMSRC/some_unc_path /user:username /pass:pa$$word; mstsc /v:some_unc_path

Invoking a Process/Batch to execute with elevated rights

We have a subversion system up and runnuing at a central server. At the moment I can access that svn repository over a network share. As this is not good practice I will close that network share and will access my svn only over the "svn" command (I use TortoiseSVN Client for that).
As new Projects will be started in the future, me and my fellow colleagues must be able to create new repositorys on that server. For the creation you would need write-rights on that server directory, but I don't want that. Also I don't want to run to our Admin every time (all this is ok with our admin and I have his support).
First, my idea: Trigger a process on the server which will create the Repository. But here I am stuck with how to trigger a process if I am not the server admin (tried a WMI VB Script) So here would be the question, how to elevate the rights of the caller during the script execution? I do not want to store the admin password in plain text in a script or batch file.
Second, can this be done in some other forms? how do you guys create your repositorys?
Afaik there is no way of auto-elevation in CMD. The only way to do that I can think of is to use the windows schduler. You could write a bat file that executes all the commands you need. Then create a task with the scheduler and tell it to run the bat file. During the creation leave the "Triggers" section empty, check the "run with highest privileges" box, enter a user account that has the rights you need and enter the password. Then go to "Settings" and check the "Allow task to be run on demand" box.
Now the second part (OPTIONAL). Adept the user policy on the server so that the users you want to be able to execute the process are allowed to trigger scheduled tasks on the server. You could also enter the users PCs as "trusted" on your server. There are several ways to achieve that. However, afterwards the users must be able to execute scheduled tasks on the server.
Now you are done! If you've done the optional section your users can trigger the task with SCHTASKS /RUN /S <RemoteServerName> /TN "<task name>". No stored credentials needed and the script runs with elevetad rights.
If you didn't use SCHTASKS /RUN /S <RemoteServerName> /U username /P password /TN "<task name>".

Powershell script to execute DDL statements on linked servers - not working when run using SSIS

I have a Powershell script that loops through a list of SQL Servers and creates server logins and database users.
The script runs on a separate server, under the administrator credentials on that server, and connects to the other SQL Servers via linked servers.
#Get administrator credentials
$password = get-content C:\Powershell\General\password.txt | convertto-securestring;
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist "DOMAIN\administrator",$password;
When this script is run manually (either directly through a Powershell window or using a batch file through a command prompt) it works perfectly well. I am logged onto the executing server as administrator when running the script manually.
I then tried to run this Powershell script using an SSIS package on the executing server, using the Execute Process Task to run a batch file. The package was executed from a SQL Agent Job. Although both the job and the package seemed to execute successfully, the DDL statements were not executed against the linked servers.
SQL Agent on the executing server is run under a designated Service Account. SSIS runs under the Network Service account.
Does anybody have any thoughts on what I might be doing wrong? I am happy to provide details of the script or anything else that is required.
Thanks
Ash
UPDATE: ok we have a little more information.
I took out the lines I posted above as I have discovered I don't actually need the administrator credentials I was retrieving.
I logged onto the server with the script on it using the service account. As per #ElecticLlama's suggestion I set a Profiler trace on the destination server. When running the script manually (or running a batch file manually that runs the Powershell script) everything works well and the Profiler shows the DDL actions, under the service account login.
When running a job through SQL Agent (either a CmdExec job or an SSIS package) that runs the same batch file, I get the following error:
'Login failed for user 'DOMAIN\ServiceAccount'. Reason: Token-based server access validation failed with an infrastructure error.'
Anybody have any further thoughts?
Thnaks to everyone for their help. Once I got that last error a quick search revealed I just had to restart SQL Agent and now everything works as it should. Thanks in particular to #ElecticLlama for pointing me in the right direction.
Ash

How to allow a user permission to recycle an application pool in IIS 6?

Is it possible to give a (non admin) user permissions to recycle a specific application pool? This is specifically for IIS 6.
I found a kind of round about way to get this done, as I couldn't find a simple way either. There may be some security concerns I've missed, so I would approach this with caution. My scenario involved a trusted, non-malicious user who requested less access.
I created a batch file with the command to reset the app pool in IIS. From there I created a single run scheduled task to run that batch file with an administrator user set up on the scheduled task. I then gave the required user read,write,and execute security permissions on that scheduled task.
I then gave the user read permission on c:\windows\tasks through the cacls command line utility. This then let that user access the scheduled tasks in control panel. From there, he could manually execute the scheduled task to reset the app pool. It works since the scheduled task is running under admin privileges.
You'll want to make sure that the user doesn't have access to modify the batch file, otherwise, you've basically given them an admin command prompt. If the scheduled task is modified, the password has to be reentered (at least on my server 2003 machine) so they can't just point the task to any executable.

Stop IIS 7 Application Pool from build script

How can I stop and then restart an IIS 7 application pool from an MSBuild script running inside TeamCity. I want to deploy our nightly builds to an IIS server for out testers to view.
I have tried using appcmd like so:
appcmd stop apppool /apppool.name:MYAPP-POOL
... but I have run into elevation issues in Windows 2008 that so far have stopped me from being able to run that command from my TeamCity build process because Windows 2008 requires elevation in order to run appcmd.
If I do not stop the application pool before I copy my files to the web server my MSBuild script is unable to copy the files to the server.
Has anybody else seen and solved this issue when deploying web sites to IIS from TeamCity?
This article describes using an htm file named App_offline.htm to take a site offline. Once the IIS detectes this file in the root of a web application directory,
ASP.NET 2.0 will shut-down the application, unload the application
domain from the server, and stop processing any new incoming requests
for that application.
In App_offline-htm, you can put a user-friendly message indicating that the site is currently under maintainance.
Jason Lee shows the MSDeploy calls you need to use (plus much more about integrating these steps in your build scripts!).
MSDeploy
-verb:sync
-source:contentPath="[absolute_path]App_offline-Template.htm"
-dest:contentPath="name_of_site/App_offline.htm",computerName="copmuter_name",
username=user_with_administrative priviliges,password=passwort
After deployment you can remove the App_offline.htm file using the following call:
MSDeploy
-verb:delete
-dest:contentPath="name_of_site/App_offline.htm",computerName="computer_name",
username=user_with_administrative_priviliges,password=passwort
The msbuild community tasks includes an AppPoolController that appears to do what you want (though as noted it is dated and at present only supports IIS6.) An example:
<AppPoolController ApplicationPoolName="MyAppPool" Action="Restart" />
Note that you can also provide a username and password if necessary.
Edit: Just noticed that the MSBuild Extension Pack has an Iis7AppPool task that is probably more appropriate.
this is the fairly hackey workaround I ended up using:
1) Set up a limited-access account for your service to run as. Since I'm running a CruiseControl.NET service, I'll call my user 'ccnet'. He does NOT have admin rights.
2) Make a new local user account, and assign to the Administrators group (I'll call him 'iis_helper' for this example). Give him some password, and set it to never expire.
3) Change iis_helper's access permissions to NOT allow local login or remote desktop login, and anything else you might want to do to lock down this account.
4) Log in (either locally or through remote desktop) as your non-admin user, 'ccnet' in this example.
5) Open a command terminal, and use the 'runas' command to execute whatever it is that needs to be run escalated. Use the /savecred option. Specify your new administrative user.
runas /savecred /user:MYMACHINE\iis_helper "C:\Windows\System32\inetsrv\appcmd.exe"
The first time it will prompt you for 'iis_helper's password. After that, it will be stored thanks to the /savecred option (this is why we're running it once from a real command prompt, so we can enter the password once).
6) Assuming that command executed OK, you can now log out. I then logged back in as a local admin and turned off the 'ccnet' user for local interactive login, and remote desktop. The account is only used to run a service, but no real logins. This isnt a mandatory step.
7) Set up your service to run as your user account ('ccnet').
8) Configure whatever service is running (CruiseControl.NET in my case) to execute the 'runas' command instead of 'appcmd.exe' directly, the same as before:
replace:
"C:\Windows\System32\inetsrv\appcmd.exe" start site "My Super Site"
with:
runas /savecred /user:MYMACHINE\iis_helper "\"C:\Windows\System32\inetsrv\appcmd.exe\" start site \"My Super Site\""
The thing to note there is that the command should be in one set of quotes, with all the inner quotes escaped (slash-quote).
9) Test, call it a day, hit the local pub.
Edit: I apparently did #9 in the wrong order and had a few too many before testing...
This method also doesn't completely work. It does attempt to run as the administrative account, however it still runs as a non-escalated process under the administrative user, so still no admin permissions. I didn't initially catch the failure because the 'runas' command spawns a separate cmd window then closes right away, so I wasn't seeing the failure output.
Its starting to seem like the only real possibility might be writing a windows service that will run as admin, and its only purpose is to run appcmd.exe, then somehow call that service to start/stop IIS.
Isn't it great how UAC is there to secure things, but in actuality just unsecures more servers, because anything you want to do you have to do as admin, so its easier to just always run everything as admin and forget it?
You can try changing the Build Agent Service settings to log-on as a normal user account instead of SYSTEM (the default), this can be done from the services control panel (Start | Run | services.msc).
If it doesn't help, you can also try configuring the appcmd to always run elevated, refer to this document for details.
In case such option is not available for appcmd or it still doesn't work, you can disable UAC completely for this user.
Here you go. You can use this from CC.NET with NAnt or just with NAnt:
http://nantcontrib.sourceforge.net/release/latest/help/tasks/iisapppool.html