Automate Failover Clustering

Hey Folks,

I’m trying to automate the creation of a failover cluster when I deploy some instances by writing a PowerShell script that runs at start-up to achieve this.

I have a service user in AD which is the only account with permission to create the CNO for the cluster, it is configured correctly (Domain admin, local admin on all instances being deployed, etc), and all instances in the deployment are able to communicate with each other with the desired connectivity.

I’m able to manually run the Failover Cluster Manager GUI as this service user to validate/create the cluster, but I’m having some difficulties with the PowerShell scripting side of things as I’m being met with various access denied errors at every opportunity.

So far I’ve been able to manually run the Test-Cluster command by doing:

Start-Process powershell -Credential $cred  -ArgumentList "Start-Process powershell -Verb RunAs"

Which gives me an elevated PS Session as the desired user after accepting the UAC prompt; allowing me to run the Test-Cluster and New-Cluster commands just fine.
However I’m unsure how to achieve this same result without having to manually accept the UAC prompt or any other dialog boxes, and any attempt to pass the above further arguments to run doesn’t seem to work.

I’ve also attempted to make use of Invoke-Command by doing things along the lines of:

Invoke-Command -ComputerName . -Credential $cred -ScriptBlock { 
        Test-Cluster -Node Server1, Server2
}

But this does not work and gives me:

Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))

Which I have seen a few times when trying various approaches.

Any help you could give would be much appreciated, thanks :slight_smile:

tl;dr - I need to automate a way to switch from the local admin to the service user, elevate that session, then run the clustering commands without having to manually accept any prompts from UAC and i’m not sure how to go about it/if it is possible.

Could this be the infamous double hop issue?

1 Like

Absolutely. Invoke the script locally with the credentials and it will work. You’ve used up your one hop with those credentials with the invoke-command. You could set up delegation instead or invoke the command as user A passing in your service creds to be used on the actually command, assuming it accepts credential.

Thanks for the replies guys - I did take a look into something similar with CredSSP authorisation but didn’t pursue it very far and went down the Invoke-Command path instead; I’ll give the delegation route another crack in the morning :slight_smile:

@krzydoug - I’m not sure if i’m understanding your alternative approach right; are you saying I should run the first invoke-command with local admin credentials, then pass the service user credentials to the actual script inside the scriptblock like:

Invoke-Command -ComputerName . -Credential $cred1 -ScriptBlock {
        Test-Cluster -Credential $cred2 -Node Server1, Server2 
}

If so, the cluster commands don’t seem to accept credentials as far as I can see :frowning:

Yes that is mostly what I was suggesting. If you’re running it locally, simply do this

Invoke-Command -ComputerName $env:COMPUTERNAME -ScriptBlock {
        Test-Cluster -Node Server1, Server2
    } -Credential $servicecredential

If you are running remotely, and since Test-Cluster doesn’t seem to support credentials itself (I didn’t check myself) then you may try this. (same thing with two different approaches

$otheradmincredential = Get-Credential
$servicecredential = Get-Credential

# Use the $using: modifier to pull the local variable remote
Invoke-Command -ComputerName RemoteServer -Credential $otheradmincredential -ScriptBlock {
    Invoke-Command -ComputerName $env:COMPUTERNAME {
        Test-Cluster -Node Server1, Server2
    } -Credential $using:servicecredential
}

And if the account you’re using to run the command remotely has rights, you can forego the first credentials

$otheradmincredential = Get-Credential
$servicecredential = Get-Credential

# Pass the credential in as an argument
Invoke-Command -ComputerName RemoteServer -Credential $otheradmincredential -ScriptBlock {
    Param($passedcredential)

    Invoke-Command -ComputerName $env:COMPUTERNAME {
        Test-Cluster -Node Server1, Server2
    } -Credential $passedcredential
} -ArgumentList $servicecredential

Cheers for the help - realistically I will only need the script to run locally on one of the nodes to performing the clustering, so it’s looking like that first invoke-command approach will be the easiest.

It seems I may have some firewall/security issues preventing me from doing it as I’m getting a HTTP error (12152), so i’ll deal with that and then try again :slight_smile: