Tuesday, October 21, 2014

PowerShell Profile Tips & Tricks


What is it?


A PowerShell profile is just a normal PowerShell script with a specific name and location. This means it's subject to your current ExecutionPolicy, so you'll either need to sign your profile or use RemoteSigned.
It's a similar concept as say autoexec.bat or .bashrc; when you launch the PowerShell console, or open a new tab in the ISE, the host process looks for and executes the applicable profile.
There are multiple possible profiles, and you can have several of them, although I prefer (and suggest) not doing so unless you have an overriding need as it makes it more complicated.
The Scripting Guy has an excellent post that explains in excellent detail, but here's the short version:
  • There is a CurrentUser set of profiles which live in your Documents\WindowsPowerShell folder
  • There is a AllUsers set of profiles which live in $PSHOME
  • Each set can have an AllHosts profile, as well as a host specific profile for each host (generally console and ISE)
  • If you have multiple profiles, the most specific one runs last (and thus "wins")
  • None of the profiles exist by default, they have to be created.
  • The profile scripts do not get invoked automatically by remote session.
There is a built-in variable ($profile) that makes life easier. Here's a command to show you where the profiles would live: $profile | get-member –membertype noteproperty

What good is it?


Here's the real meat of the story. J

Since the profiles are standard PowerShell scripts, anything you can do in a PowerShell script can be in your profile. Just remember though, that the profile scripts run every time you launch PowerShell, so you don't want them to take a long time to run. You also do not want them to require any user input as PowerShell won't finish loading until that input is provided. This is especially painful if you have PowerShell logon/logoff or start/shutdown script defined in your GPOs.
Anything you find yourself running/typing every time you launch the console or ISE should probably go in your profile.

The most common and useful things to put in your profile are:


  • Functions (help about_Functions)
  • Aliases (help about_Aliases)
  • PSDrives (help About_Providers)
  • PSDefaultParameterValues (help about_Parameters_Default_Values)
My profile started out originally because I didn't want to have to launch each of the different, separate, PowerShell "consoles" that each snap-in or tool seemed to create. After all, why go launch PowerCLI or Exchange Management Shell when I can just create a function in my profile that adds those things to my current session?
Another very useful case are modules/snap-ins that have to be run from a server with a specific role such as XenApp or SharePoint. The SharePoint PowerShell snap-in has to be run from a SharePoint server that is part of the farm you're working with. So rather than have to create a new session each time you want to access it (or worse RDP to the server to run PowerShell!) I've created a function that uses implicit remoting to import the snap-in.
I've posted a generalized and heavily commented version of my own profile script on GitHub: https://github.com/dsolodow/IndyPoSH/blob/master/Profile.ps1

Feel free to read through it, post questions or comments in the Issues or Discussion pages for the project. Also feel free to borrow snippets or sections out of it that you want to use for yourself.

Other ideas: 

The Scripting Guy has a series of posts about "What's in your profile" with information from various PFEs, PowerShell MVPs, members of the PowerShell team, etc. Links below.
What's in your profile (PFEs): http://bit.ly/1BxOImo

What's in your profile (PowerShell team): http://bit.ly/1rGAzm4

What's in your profile (MVPs): http://bit.ly/1vrjqxJ

What's in your profile (User favorites Part 1): http://bit.ly/1mIUOyV

What's in your profile (User favorites Part 2): http://bit.ly/1qPP7uf

What's in your profile (Scripting Guy): http://bit.ly/1uxMdlt

Any rules, best practices, no-nos? 

There aren't a lot of hard, fast rules but here are the ones I know of as well as some good practices/suggestions:
  • Don't make your profiles require user input
  • Be careful about system/version dependent features/cmdlets
  • Make sure you either sign your script or run PowerShell with the RemoteSigned executionPolicy
  • Don't make your profile script something that takes a long time to run as you'll run it a lot
  • It's a PowerShell script, treat it accordingly. This means comment it, format it appropriately, put it in version control, etc.
    http://windowsitpro.com/blog/my-12-powershell-best-practices
  • Do share cool tricks or ideas with your co-workers, fellow IndyPosh members, the PowerShell community
  • Let your profile grow organically; when in doubt K.I.S.S.
  • Remember: help about_profiles

Friday, September 19, 2014

Fun with certificates – Outlook Web Access certificate error

The Problem:

We recently had a user (we’ll call them “Bob”) send in a ticket because when he tried to access Outlook Web Access from home he got a certificate error in the web browser that said the site wasn’t secure. Understandably concerned by this, he closed out the browser and contacted us.

The Diagnosis:

So the first order of business was to determine if it was a global issue or just poor Bob. Since no other tickets had come in, and the site loaded correctly for us here it was almost certainly just Bob having this issue.

A few items that made this even more interesting:


  •          Bob got this security warning on any secure Harrison websites, not just Outlook Web Access
  •          Bob didn't have problems with non-Harrison secure websites
  •          This included secure websites that use the same certificate provider that we do (DigiCert)
  •          Internet Explorer and Chrome both gave a certificate warning for Harrison sites, but Firefox worked fine.
This last point is rather interesting and is actually rather telling. IE and Chrome both use the Windows certificate store, whereas Firefox maintains its own certificate store. On a side-note, this is why Firefox is problematic with non-public Certificate Authorities; you can’t deploy the root certificates to it via GPO.

So we took a look at Bob’s PC, and visited our Outlook Web Access page to get the certificate warning. We pulled up the certificate info (HowTo) so we could try to find out why his browser thought something was wrong.  Here’s what we saw:

The Details tab wasn't immediately helpful, but the Certification Path tab was. The Certification Path tab shows the Certificate Chain for the given certificate:

Our certificate (*.harrison.edu) said that it was OK. The next one up the chain (DigiCert Secure Server CA) also said it was OK. However, the top (or root) certificate was not OK.
Ah-ha! This meant that the Windows certificate store had a corrupt copy of that certificate that needed to be replaced.

The Solution:

  1.          Determine which certificate in the store needs to be replaced
  2.          Get a good copy of the certificate
  3.          Replace the bad one
  4.      Test

Determining which certificate needed to be replaced was a matter of selecting the bad certificate (DigiCert) from the dialog shown above and clicking View Certificate.
This told us that the certificate we needed was “DigiCert Global Root CA” with an expiration date of 11/9/2031.
A quick Google search for “DigiCert Global Root CA” pointed us here: https://www.digicert.com/digicert-root-certificates.htm
Scrolling down to “DigiCert Global Root CA” showed the expected expiration data, and had a handy Download link.
Now that we had the correct and valid certificate, we just needed to replace the bad one. Here’s how that was done:

  1. Click Start, click Start Search, type mmc, and then press ENTER.
  2. On the File menu, click Add/Remove Snap-in.
  3. Under Available snap-ins, click Certificates,and then click Add.
  4. Under This snap-in will always manage certificates for, click Computer account, and then click Next.
  5. Click Local computer, and click Finish.
  6. In the console tree, double-click Certificates.
  7. Click Trusted Root Certification Authorities store.
  8. Scroll down to find the bad certificate (DigiCert Global Root CA)
  9. Right click the bad certificate and click Delete
  10. This displayed a warning that we could be breaking things, but since we were about to replace it, we clicked Ok
  11. Right-click the Trusted Root Certification Authorities store.
  12. Click Import to import the certificates and follow the steps in the Certificate Import Wizard, pointing it to the certificate we’d just downloaded from DigiCert.

Once this was done, we launched IE, and visited Outlook Web Access. This time no certificate warnings came up, and Bob finally got to his email.

Monday, May 20, 2013

Out-State -Destination "TechEd"

I'm leaving , on a jet-plane..

But I know when I'll back again...

So for the first time in my IT career, I'm making it to TechEd. This year it's down in New Orleans during the first week of June. 

Should be an interesting experience and looks rather like an IT related GenCon (which I'm going to this year as well). I've got my schedule of events roughed out, and am planning my what to bring and what to leave list.

I've already told my co-workers that I'll be mostly offline during that period so if something catches fire, call 911. 

Any of you making it out there this year?

Thursday, May 16, 2013

Write-Blog "Dear IIS, please tell my *why* it failed." -UsefulContent $true

So I got this error...

After seeing it mentioned in a thread about multi-user password vaults I decided to take a look at the product PasswordState. The capabilities looked like a good fit what the IS department at $Work was looking for, it's a web based app and it's an ASP.NET app that runs on IIS and works with MSSQL. These counted on the plus side of the ledger for us as we have in house expertise with that platform. 

They offer a free license good for up to 5 users (with no expiration) and larger licenses are under $30 a person. And to make it even better, they have excellent documentation for installing and configuring the application. 

So why am I talking about it and an error? Well I ran into an issue during the post install configuration. 
The install was straight-forward and the configuration was handled by hitting the web page for the app. Everything went fine until the penultimate step; selecting a user for the first SecurityAdmin. It gave me an error message about not being able to query Active Directory to get the list of users. 

The message it gave was very straight-forward and pointed me to their documentation on the problem. The issue was that by default new Application Pools in IIS 7+ run as "ApplicationPoolIdentity" which is a specialized local user account unique to the application pool. This makes a lot of sense from a "least user" perspective. More information on this account can be found at IIS.Net.

Their documentation correctly and helpfully pointed out that these accounts can't talk to Active Directory, and to resolve this issue the Application Pool should be reconfigured to run as a domain user account. They continued with step by step directions on how to make this change. 

Once I made this change, recycled the AppPool and reloaded the web page, I received one of the more non-specific errors I've seen:
The page cannot be displayed because an internal server error has occurred. 

Well, it's accurate but not at all useful. So now it was time to dig down and find out what's going on...

The first step was getting it to tell me something more meaningful so I find out why it didn't like the new identity account. 

"Internal Server Error" translates to an HTTP 500 error, and by default IIS shows very generic messages for these errors to clients. This is because the information provided by detailed error pages would be very useful not just to troubleshooters but to trouble causers (aka attackers). 

A quick change in IIS Manager (details here) and a refresh of the page showed a much more helpful message: 
Either a required impersonation level was not provided, or the provided impersonation level is invalid. (0x80070542) 

Now that's useful! This is because the account being used as the Application Pool Identity didn't posses the right "impersonate a client after authentication" on the web server. 

By default when you install IIS on a server it creates a local group called IIS_IUSRS that is granted this right as well as permissions to the Inetpub directory tree. 

Once the domain account was added to this group and the AppPool restarted, the web app loaded properly and the installation completed successfully.

Microsoft has a handy KB article on the default permissions and user rights for IIS7+: http://support.microsoft.com/kb/981949

This is a pretty common issue with IIS applications (including classic ASP) that require domain accounts but is easy enough to solve. One way to avoid it is to create a domain group for AppPool identities, and that group can be granted the necessary user rights by GPO on the IIS servers and being added to the local IIS_IUSRS groups on them. 


Wednesday, May 15, 2013

Write-Blog "Hello World!"

The blog equivalent of "Hello World"

Anyone who has ever read/looked at/skimmed a programming or scripting book has inevitably seen the "Hello World!" program. It doesn't do anything more than display that message, some at the console, some in a pop-up, and others put it on a web page. 

It's intended as nothing more than a "look, you made a program/script that does something!". Then it lets you bask in your success before actually having you do something useful or productive. 

That's basically what this post is; a simple "Hi, I exist!" before something with content. 

Future posts will have content, but whether or not they are of interest or use will depend on you the reader. :)

If you're interested in seeing the various prototypical "Hello World" programs, Wikipedia has a nice list of them: http://en.wikipedia.org/wiki/List_of_Hello_world_program_examples