Welcome to the Inedo Forums! Check out the Forums Guide for help getting started.

If you are experiencing any issues with the forum software, please visit the Contact Form on our website and let us know!

Pulling variable values into PowerShell .ps1 scripts and potentially credentials



  • Hello all,

    I am working on testing Otter to see how it will work in our environment. One thing I wanted to use it for is a script repository/execution center. However, most if not all of our windows scripts are in PowerShell. Additionally, neither I nor my team have the bandwidth to learn Otterscript, so that leaves me in a bit of a situation with regards to global variables and so forth.

    Is there a way I can pull variable values into a regular PowerShell script? Potentially even Secure credentials?

    The documentation on this is a bit confusing, and doesn't give many examples of PowerShell script usage in general.

    Also, I did several searches on the documentation for Group Managed Service Accounts, and only found rough references to them. Are GMSAs supported? Is there a guide for setting those up?


  • inedo-engineer

    Hi @moriah-morgan_0490 ,

    We are working on documenting this all much better, so thank you for bringing it up. But the scenario you describe (using Otter as a script repository/execution center) is definitely possible and is something we are actively working on improving and making easier.

    Otter can pass in variables, read your existing Comment-Based Help, and you can then build Job Templates around the variables. We have a tutorial about that here: https://docs.inedo.com/docs/otter-create-a-gui-for-scripts-with-input-forms

    As for Secure credentials, no problem. Behind the scenes, this is handled through the $PSCredential function in OtterScript, and now that I write this, I think we should add support to Job Templates for this.

    Anyways, after uploading a script named MyScriptThatHasCredentials.ps1 to Otter, and creating a SecureCredential in Otter named defaultAdminAccount, you would just need to write a "wrapper" in OtterScript for it:

    PSCall MyScriptThatHasCredentials
    (
      User: $PSCredential(defaultAdminAccount)
    );
    

    Do you want the Otter Service and/or Inedo agent to run as a GMSAs? Sure, there's no problem as long as there's access; https://inedo.com/support/kb/1077/running-as-a-windows-domain-account

    Cheers,
    Alana



  • Thank you for that rundown. I have a few things I ran into.

    Firstly, I was not able to get a script to run as a resource credential. I saw another forum post here where a member of the support team dropped the following information to run a script "as a resource credential"

    Here's the sample I used:

    with credentials = TestCred2
    {
        PSCall whoami;
    }
    

    whoami is just a script I have that runs and outputs the current user who is executing that script. This is the output I get:

    DEBUG: 2022-02-22 00:33:01Z - Job will be run against servers sequentially (not asynchronously).
    DEBUG: 2022-02-22 00:33:01Z - Targeting servers: SERVERNAME
    DEBUG: 2022-02-22 00:33:01Z - Beginning execution run...
    ERROR: 2022-02-22 00:33:01Z - Username & Password credentials "TestCred2" not found.
    ERROR: 2022-02-22 00:33:01Z - Execution run failed.
    DEBUG: 2022-02-22 00:33:01Z - Cleaning up temporary files on Inedo Agent (v??, SERVERNAME:46336)...
    
    

    Am I doing this wrong? the credential is in there as a "Secure Credential".

    Lastly, I did as you showed and was able to get the password for the Test Credential, however, I seem to be having an issue with the "Secure" part of this credential. With or without the box being checked, I can grab the password in plaintext. Here's my code example:

    OtterScript Wrapper:

    PSCall PullPlaintextPS (
        credtest: $PSCredential(TestCred2),
    );
    

    PowerShell Script:

    Write-Host "Script Started"
    $credtest.GetNetworkCredential().Password
    $credtest.Username
    $credtest | get-Member
    $credtest.GetNetworkCredential() | get-member
    

    The most important line there is line 2, which outputs the password of the credential. I appear to be able to fetch this value, regardless of whether or not the box for "otterscript usage" is checked. Am I misunderstanding the usage of this checkbox, and is there another way to secure this password from being dumped like this? I just created testcred2
    as a standard "Secure Credential".

    Thanks!



  • Clarification: There are scenarios where I would need the password to be available in Plaintext, such as platforms that need password based auth, but there are also (more commonly) scenarios where I just need to run under that credential context. In the cases where I do not need the plaintext password, it would be insecure to have it accessible via other means as demonstrated above.


  • inedo-engineer

    This post is deleted!

  • inedo-engineer

    Hi @moriah-morgan_0490 ,

    If you've created a Secure Credential (Username & Password) under Admin > Secure Credentials that's named TestCred2 then the OtterScript you presented should work. There are several challenges with getting impersonation to work Windows in general (as I'm sure you've learned as a Windows admin), so we don't recommend using it unless you have to.

    In your Otter configuration, my guess is that there is a problem with environment scoping; that can get a bit tricky - I would just set it to use (Any) environment for now.

    As for "Secure" part of "Secure Credentials" - the password fields are stored as encrypted data, and you can only decrypt them with the Encryption Key (stored separately). They're also held in memory as securely as possible, and are "handed" to PowerShell as a PSCredential object.

    The "Allow encrypted properties to be accessed" prevents OtterScript from exposing the passwords using the $CredentialProperty() function. For example, this would cause an error unless that was checked:

    Log-Information $CredentialProperty(TestCred2, Password);
    

    However, PowerShell has no such restriction surrounding credentials. For example, you can always just do this:

    $credtest = Get-Credential
    Write-Host $credtest.GetNetworkCredential().Password
    

    Microsoft's recommended way to handle this is to use Windows Authentication.

    Our recommendation is to generally avoid passing important credentials to scripts (API keys, etc. seem fine)... but if you must, use a change process to ensure that you aren't running scripts that dump passwords like that.

    Hope that helps,

    Alana



  • @atripp

    Thanks again for the explanation. Regarding impersonation: Agreed. We don't have many scenarios where this will be used, but we wanted to test this as a potential requirement for the platform.

    I did change the scope of the test credential for impersonation, and it did work after changing the scope. Is there any way around this? I don't mind per-se to have it be in all environments, but I figured it wouldn't hurt to lock it down a bit more.

    Additionally, one of the ways we were able to get impersonation working was to make sure that the target of impersonation (not the account running the agent) was a local administrator on the target server. For some reason, this seemed to be the only way we saw that it worked. Would you happen to have any resources on hand that would explain what security rights the target of impersonation would need to run a script on the server? I tried several groups in the "local groups" on the server, as well as several different user rights assignments, but couldn't get anything outside of just dropping it in to the "Administrators" group.


  • inedo-engineer

    Hi @moriah-morgan_0490 ,

    Glad to see the environment un-scoping worked! It's definitely possible to get environment-scoping of credentials to work... but it'd probably be best to confirm what you're looking to accomplish.

    The main purpose of the environment-scoping is to enable limited management access to Otter. For example, users can edit/maintain all configuration except for production servers. Take a look at Multiple Environments per Server to see how the behavior works.

    I assume that you're running the Inedo Agent? We're still learning the exact privileges ourselves 😏

    We've seen systems restricted in very unexpected ways (and only in the field of course, never or own environments), and they don't give any logical error messages. But we'd love to help you get this working, so we can document it.

    Here's what we know so far:

    • local administrators seem to have no problems; this is what most people do, because it's domain credentials they are interested in using and it doesn't matter if they're an admin on that particular server
    • try running the Inedo Agent as the user you wish to impersonate as; this will identify most permissions issues
    • make sure the user target has permissions to the extension cache path and appropriate root paths; see the Agent Configuration File
    • "run as a service" permission seems to be important
    • logging into the server as the impersonated user (at least once) may help for some scripts, so we've heard
    • antivirus or other security tools may block this impersonation as well

    Let us know what you find :)


Log in to reply
 

Inedo Website HomeSupport HomeCode of ConductForums GuideDocumentation