Friday, June 20, 2025

Enterprise Tips – Secure Credentials, Proxy Settings, and MID Server Options for PowerShell + ServiceNow API

Introduction

So far in this series, we've explored how to connect PowerShell to the ServiceNow Table API, handle errors, and optimize performance. But in enterprise environments, you'll run into real-world constraints like:

  • Secure credential storage
  • Network proxies
  • Internal ServiceNow instances behind firewalls
  • Compliance restrictions

In this final article, we cover how to run secure, robust API integrations in production environments using best practices and ServiceNow architecture features.

1. Securely Store and Use Credentials

Hardcoding usernames and passwords in scripts is a security risk. Before picking a storage method, it's worth connecting this back to Part 1 of this series: if you're authenticating with OAuth's Client Credentials grant (the current recommended approach), what you actually need to protect is a Client ID and Client Secret, not an end user's password. That's a meaningfully smaller attack surface than the credential-storage problem this section might otherwise imply — but it still needs protecting properly rather than living in plaintext in a script.

SecretManagement (Recommended Starting Point)

Microsoft's Microsoft.PowerShell.SecretManagement module is the current, cross-platform-friendly way to abstract secret storage — it works the same way whether the underlying vault is a local encrypted store, Azure Key Vault, HashiCorp Vault, or something else, so your script logic doesn't change if the backend does.

Install-Module Microsoft.PowerShell.SecretManagement -Scope CurrentUser
Install-Module Microsoft.PowerShell.SecretStore -Scope CurrentUser

# One-time: register a local vault and store the secret
Register-SecretVault -Name LocalVault -ModuleName Microsoft.PowerShell.SecretStore -DefaultVault
Set-Secret -Name "SNOW_CLIENT_SECRET" -Vault LocalVault

# In your script, retrieve it at runtime
$clientSecret = Get-Secret -Name "SNOW_CLIENT_SECRET" -Vault LocalVault -AsPlainText

Worth knowing: Microsoft has marked SecretManagement as feature-complete — it's still fully supported for security fixes, but not gaining new capabilities, specifically because the PowerShell team sees the industry moving toward passwordless and federated authentication (Entra ID, managed identities, hardware keys) rather than stored username/password secrets generally. That's not a reason to avoid it today — it's stable, well-documented, and does the job — but it's worth knowing this is a maturity/stability story, not an actively-evolving one, when planning long-term.

Windows Credential Manager (Simpler, Windows-Only)

For local automation on a Windows-only environment, the CredentialManager module wraps Windows Credential Manager directly:

Install-Module CredentialManager -Scope CurrentUser

# One-time setup
New-StoredCredential -Target "SNOW_API_CRED" -UserName "admin" -Password "your_password" -Persist LocalMachine

# In your script
$creds = Get-StoredCredential -Target "SNOW_API_CRED"
$user = $creds.Username
$pass = $creds.Password

This is simpler to set up than SecretManagement, but it doesn't support rotation, expiration, or audit logging the way a proper vault does, and it's Windows-specific — it won't work if any of your automation needs to run cross-platform under PowerShell 7+.

Secure Vaults (Enterprise)

If you're in a DevOps setup with centralized secret governance requirements, integrate with a dedicated vault directly — Azure Key Vault, HashiCorp Vault, or AWS Secrets Manager, each of which also has a SecretManagement extension vault available, letting you use the same Get-Secret/Set-Secret pattern above regardless of which one your organization standardizes on.

2. Use Proxy Settings When Required

Corporate environments often require internet access via proxy. PowerShell supports this:

$proxy = New-Object System.Net.WebProxy("http://proxy.company.com:8080")
$handler = New-Object System.Net.Http.HttpClientHandler
$handler.Proxy = $proxy

$client = [System.Net.Http.HttpClient]::new($handler)
$response = $client.GetAsync($url).Result

Or for Invoke-RestMethod (basic use):

Invoke-RestMethod -Uri $url -Proxy "http://proxy.company.com:8080" -Headers $headers

If the proxy requires authentication — common in corporate environments — pass credentials explicitly rather than assuming the default session context will satisfy it:

$proxyCred = Get-Secret -Name "PROXY_CRED" -Vault LocalVault
Invoke-RestMethod -Uri $url -Proxy "http://proxy.company.com:8080" -ProxyCredential $proxyCred -Headers $headers

3. Using MID Server as an Alternative to Direct API Calls

If ServiceNow is hosted internally or API access is restricted externally, a MID Server is the best approach.

What's a MID Server?

A Management, Instrumentation, and Discovery (MID) Server is a lightweight Java process that sits inside your network and acts as a secure bridge between ServiceNow and internal systems.

Use Cases:

  • When the target system is on-premises and ServiceNow's cloud instance can't reach it directly.
  • When you don't want to expose public API endpoints on your internal PowerShell-driven systems.
  • When calls need to run behind a proxy or firewall that only your internal network can traverse.

It's worth being precise about direction here, since these two mechanisms solve different problems:

  • A Scripted REST API is an inbound endpoint — it lets external systems (including a PowerShell script) call into ServiceNow. It processes whatever it receives using standard server-side script; it doesn't inherently involve a MID Server unless that processing logic separately needs to reach out to another on-prem system as part of handling the request.
  • A MID Server is what lets ServiceNow reach out to internal systems it can't call directly. If PowerShell needs to trigger something on an internal system via ServiceNow, or ServiceNow needs to pull data from an internal system, that's the MID Server's job — not the Scripted REST API's.

MID Server & Orchestration

You can use Orchestration + MID Server to trigger PowerShell scripts (via a PowerShell Probe) from a Workflow, and pull results back into ServiceNow. This is a well-established pattern, but it's tied to the classic Workflow engine. On current instances, the equivalent — and increasingly the more supported path going forward — is a Flow Designer flow calling the underlying probe API directly, or a vendor-provided Spoke if one exists for what you're trying to reach. Both approaches route through the same MID Server; the difference is which orchestration layer triggers it.

Bonus Tips

  • Understand rate limiting before assuming a number. ServiceNow doesn't enforce a single universal default rate limit like "100 calls/minute" — Rate Limit Rules are configured per-instance, typically per-hour rather than per-minute, and often aren't enabled at all unless a platform admin has explicitly set them up for specific users, roles, or APIs. Confirm what's actually configured on your instance with your platform team rather than assuming a fixed ceiling — building around an imagined limit can lead to either unnecessary self-throttling or an unpleasant surprise when a real one turns out to be lower than expected.
  • Rotate OAuth Client Secrets periodically, the same way you'd rotate a password.
  • Use roles and ACLs to limit what any given integration account can actually reach in ServiceNow — least privilege applies to service accounts as much as human users.
  • Log sensitive API interactions securely — don't let request/response logging become its own accidental data exposure.

Conclusion

Running PowerShell integrations with ServiceNow at scale requires more than just syntax — it takes planning for security, scalability, and reliability. By using proper secret storage (increasingly a Client Secret rather than a user password, if you followed this series' authentication recommendation), handling proxies correctly, and understanding what a MID Server actually does versus a Scripted REST API, you ensure your automation is enterprise-ready and compliant.

No comments:

Post a Comment