Initialising arrays in PowerShell

Initializing arrays in PowerShell (en-US spelling for search engine purposes Smile).

I think it’s taken me three years to work this out and it took a rushed script with a typo to figure it out.  Later I finally found the answer on stackoverflow.com but by then it was too late…could have made my life easier when trying to write some simple base 64 conversion code for a colleague last year.  Smile

Anyway.  How to define or initialise (initialize) an array in PowerShell?

For example, in C# we’d do this:

Person[] p = new Person[];

or

DirectoryAttribute[] d = new DirectoryAttribute[5];

How do we do this in PowerShell?  In much the same way, except we use New-Object in place of new and we don’t stipulate the upper bound in the square brackets but instead next to the square brackets, e.g.

[String[]]$str = New-Object String[] 5;

Or, seeing as I was using System.DirectoryServices.Protocols.DirectoryAttribute…

[System.DirectoryServices.Protocols.DirectoryAttribute]$dsa = `
    New-Object System.DirectoryServices.Protocols.DirectoryAttribute[] 10;

Simple yet hugely helpful I hope.  Happy initialising…

Posted in Scripting, PowerShell | Tagged , , | Leave a comment

AD FS 2.0 Issuance Authorization Rules

I had to create a couple of issuance authorization rules in my last engagement and it took me a little longer than it should have to get the syntax correct so I thought I’d post a couple of examples that might be of interest to others.

Firstly, lets clarify what I’m talking about.  Taken from When to Use an Authorization Claim Rule in the AD FS 2.0 Design Guide:

You can use this rule in Active Directory Federation Services (AD FS) 2.0 when you need to take an incoming claim type and then apply an action that will determine whether a user will be permitted or denied access based on the value that you specify in the rule. When you use this rule, you pass through or transform claims that match the following rule logic, based on either of the options you configure in the rule:

To wrap some further context around this post you define issuance authorization rules on relying party trusts.  These rules are applied early on in the claims pipeline process.  You use issuance authorization rules to determine whether or not a user has access to an relying party application. 

A common issuance authorization rule is the permit access to all users rule template.  If you look at the underlying claim rule language for this template you will see the following:

=> issue(Type = “http://schemas.microsoft.com/authorization/claims/permit”, Value = “true”);

Nice and easy.  Issue a claim of the type http://schemas.microsoft.com/authorization/claims/permit with a value of true. 

It’s worth pointing out here that the value is irrelevant.  The authorisation engine only looks for the type of claim, allowing access if there is a claim with a type of http://schemas.microsoft.com/authorization/claims/permit, and not allowing access if there’s no permit claim type or if there is a claim with a type of  http://schemas.microsoft.com/authorization/claims/deny present.  More information on this here.

The purpose of this post is to share two simple examples.  I just designed an AD FS solution and made use of authorization rules to achieve the requirement of all users in domain-a have access to RP application XYZ.  In this environment there were three domains in the forest.  We only wanted users in one of the domains to access the application.  I achieved this by creating a rule with the Send Claims Using a Custom Rule template and the following rule:

c:[Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname", Value =~ "^(?i)CORP\\.+$"]
=> issue(Type = “http://schemas.microsoft.com/authorization/claims/permit”, Value = “true”);

To explain the rule lets assume we have the following domains in the forest: corp.contoso.com, partner.contoso.com, and emea.corp.contoso.com.  The above claim rule only permits access to a relying party if the Windows account name (http://schemas.microsoft.com/ws/2008/06/identity/claims/windowsaccountname) claim type has a value of CORP\something, e.g. CORP\paulw or CORP\chucn.

Next we had a similar requirement that we achieved with a rule around the value of the UPN claim type.  We wanted partners to be able to access an RP.  Non-employee accounts in the directory had a different UPN suffix to employees and contractors (non-employee accounts are created in partner.contoso.com if the partner organisation doesn’t have federation infrastructure).  In this scenario we decided to permit access to an RP application for all users with a UPN of something@partner.contoso.com.  Here’s an example:

c:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn", Value =~ "^(?i).+@partner\.contoso\.com$"]
=> issue(Type = “http://schemas.microsoft.com/authorization/claims/permit”, Value = “true”);

Hopefully this will help someone.  It took me longer than it should have to get the regex right.  Smile

Just in case you need a little more guidance on how to create these rules…

If you’re new to AD FS and have just read the above and are thinking awesome, I really want to use that UPN rule but…I have no idea how to create it here goes…

  1. Open AD FS 2.0 management console, click Relying Party Trusts, click the RP trust that you want to configure and click Edit Claim Rules… in the actions bar.
  2. The Edit Claim Rules for <RP name> dialog opens.  Click the Issuance Authorization Rules tab (the middle tab).  If you’re accessing the RP presently you likely have a single rule called Permit Access to All Users with an issued claims of Permit in the list.  Remove this rule and click Add Rule…
  3. Choose the Send Claims Using a Custom Rule template and click Next.
  4. Supply a name and then paste your syntax into the custom rule input.  Click Finish.

If you consider the following rule:

c:[Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn", Value =~ "^(?i).+@partner\.contoso\.com$"]
=> issue(Type = “http://schemas.microsoft.com/authorization/claims/permit”, Value = “true”);

The part that you need to configure is the regex –the contents within the quotes after =~ e.g. ^(?i).+@partner\.contoso\.com$.

Regarding the regex.

  • (?i) makes the pattern case insensitive.
  • ^ means starts with.
  • .+ means anything one or more times.
  • @partner\.contoso\.com is the URL with an escape sequence for the dot (or period).
  • $ means ends with.
Posted in AD FS | Tagged , , , , | Leave a comment

Update Rollup 2 for Active Directory Federation Services (AD FS) 2.0

Yesterday Microsoft released Update Rollup 2 for Active Directory Federation Services (AD FS) 2.0.

This update rollup includes hotfixes and updates that fix four (4) product issues and add one (1) new capability to the product.  Summarised, the changes are as follows.

New capability

  • AD FS 2.0 does not fully support the RelayState parameter for Security Assertion Markup Language (SAML) protocol.  Update Rollup 2 for AD FS 2.0 adds a new capability that enables AD FS 2.0 to consume relay state in order to redirect the user to the RP application.

For more information on this new capability please see Supporting Identity Provider Initiated RelayState.

Product issues resolved

  • Issue 1: There is a reliability issue in AD FS 2.0 in which AD FS 2.0 Federation Service stops responding to requests in certain cases, especially when there is a large load on AD FS 2.0 federation server or federation server proxy.  This issue can occur in both federation passive and federation active scenarios.
  • Issue 2: The whr parameter that is specified by an application for a home realm discovery scenario overwrites the previously set home realm discovery cookie.  This causes a user to be redirected to a different identity provider that the user cannot use to sign in when the user uses a different application.
  • Issue 3: The AD FS 2.0 service stops unexpectedly when a valid certificate is set to the archived state.
  • Issue 4: When you add an AD FS 2.0 federation server to a Windows Internal Database (WID) farm, you receive an error message.  This issue occurs when the federation server is in a time zone that is later than the primary federation server in the WID farm.
Posted in AD FS, News | Tagged , , , , , , , , , | Leave a comment

Failure when making a web service call when running Start-FIMReportingInitialSync.ps1

You invoke the script Start-FIMReportingInitialSync.ps1 and get the generic Failure when making web service call error from Import-FIMConfig.  The error itself is “The web service client has encountered the following class of error: SystemConstraint”.  The additional text details state: “The Request contains changes that violate system constraints”.

As we’re running the Start-FIMReportingInitialSync.ps1 we know that we’re actually trying to create an msidmReportingJob resource.  If we inspect the Forefront Identity Manager event log there’ll be a corresponding event (we have a correlation ID now too).  The event will define the requestor, the correlation ID and then define the system constraint within the PermissionDeniedException:

SystemConstraint —> System.InvalidOperationException: This service instance could not create a reporting job because ReportingLoggingEnabled setting is false.

OK.  How do we set the ReportingLoggingEnabled option to true?  Quite easily actually.

Navigate to Administration | All Resources | System Configuration Settings (msidmSystemConfiguration) in the FIM Portal and you’ll see a single resource: System Configuration Settings.  Open the properties of this resource, click Extended Attributes and toggle the Reporting Logging Enabled checkbox.

Run the script again and all is well.

Looks like this isn’t toggled when you install Reporting via a change installation, i.e. you didn’t install Reporting when you installed the FIM Service.  Whether or not the RTM bits will change this I don’t know…

Posted in FIM, FIM 2010 R2, Reporting, Troubleshooting | Tagged , , , , , , , , | Leave a comment

Make the installation and FIM MA accounts filtered disconnectors and save yourself a headache (and possibly a rebuild).

I know others have written and talked about this but please, please implement the following two connector filters on your FIM MA.

image

Two separate filters defined for the Person data source object type: <dn> equals <GUID>.  In case the screenshot isn’t clear the filters are:

  1. <dn> Equals fb89aefa-5ea1-47f1-8890-abe7797d6497
  2. <dn> Equals 7fb2b853-24f0-4498-9534-4e10589723c4

Basically that’s telling the FIM Synchronization Service to make the installation account (often referred to as the administrator account with a well-known GUID of 7fb2b853-24f0-4498-9534-4e10589723c4) and the Built-in Synchronization Account (the FIM MA account with a well-known GUID of fb89aefa-5ea1-47f1-8890-abe7797d6497) filtered disconnectors, i.e. exclude those two accounts from synchronisation.

Why, you might ask.  Here’s why:

  • You have an inbound flow defined from your AD DS MA that flows objectSid into the MV.
  • You have an outbound flow rule defined on the FIM MA that flows objectSid out to the FIM Service.
  • You have configured the flow to flow NULL values (i.e. delete values). 

Right, so what?

Well when you import and synchronise the FIM MA (to get your SRs into the MV for example) you will delete the ObjectSid value of both the administrator and FIM MA account because they’re usually not joined to anything else and the MV attribute is null because you haven’t flowed the FIM Service value into it because that configuration is more or less pointless (except to possibly save this issue Smile).

And?

Well no ObjectSID == no access to the FIM Service which means you can’t render the portal.  Sure, if you poke around in the SQL database (perhaps you’ll look at the SPROCs in the [debug] schema), you can fix it but many people don’t and therefore end up rebuilding because the environment is new and nothing’s been backed up yet!

I’ve fielded two separate instances of the above in as many weeks, plus a colleague new to FIM did it about a month ago and two people on my FIM training course at the start of the month!  So please implement the connector filters and be safe.  Smile

For more info. on and around this topic look at Carol’s blog post on her recommended practices for the installation/administrator account: Best practices for the FIM Portal Administrator account.

Posted in FIM | Tagged , , , , , , , , , , | Leave a comment

PWReset Activity could not connect to the directory

A user of Forefront Identity Manager 2010 Self-Service Password Reset successfully authenticates the question and answer (Q&A) gate, inputs a new password and fails to successfully reset with the generic error “An error occurred when attempting to reset password, please try again”.

Upon inspection of the Forefront Identity Manager log in Event Viewer the following error has been recorded:

image

Textually, that’s an event ID 3 from Microsoft.ResourceManagement with a description of “PWReset Activity could not connect to the directory”.

As the error suggests the issue is that the entered password did not make it to the directory.  Or another way, the call into MIIS_CSObject::SetPassword failed.

The reason?  There might be several, i.e. an ADMA connectivity or authentication issue but one sure reason is that the Enable password management option under Password management in the Configure Extensions page of your ADMA is not checked –see screenshot below.

image

We must enable password management to be able to utilise MIIS_CSObject::SetPassword which is what the Password Reset Action Workflow calls.

Posted in FIM, FIM 2010, Self Service Password Reset, Troubleshooting | Tagged , , , , , , , , | Leave a comment

PWReset Activitiy’s MIIS Password Set call failed with ma-access-denied

A user of Forefront Identity Manager 2010 Self-Service Password Reset successfully authenticates the question and answer (Q&A) gate, inputs a new password and fails to successfully reset with the generic error “An error occurred when attempting to reset password, please try again”.

Upon inspection of the Forefront Identity Manager log in Event Viewer the following error has been recorded:

image

Textually, that’s an event ID 3 from Microsoft.ResourceManagement with a description of “PWReset Activity’s MIIS Password Set call failed with ma-access-denied”.

As the error suggests the issue is that the AD MA account does not have permissions to reset the password of the user in question.

Microsoft help and support knowledgebase article kb2028194 also describes this issue but instead focuses on “protected users”, i.e. those who’s security descriptor (SD) is managed by the Active Directory Domain Services (AD DS) adminSDHolder object.  Probably because the SSPR deployment guide does state what permissions are required.

The purpose of this post is to provide instructions on what permissions are required and how to deploy them.  I’ve already posted this information in the form of a CMD script at the bottom of this post.  In this post I’ll provide a PowerShell script to set the permissions.

The discussion of protected users is outside of the scope of this blog post.  The aforementioned KB describes this quite well.  In my experience I’ve kept them out of the scope of FIM 65% of the time and modified adminSDHolder the other 35% of the time.  Here’s an example script.

# SsprPermissions.ps1 v1.0 Paul Williams (pawill@microsoft.com) Microsoft Services Feb. 2012
# Simple script that grants an account (ideally a domain local group) the necessary permissions
# for the AD MA to perform a password set operation.

PARAM
(
    [Parameter(Mandatory = $false)]
    [String]$Target = "OU=People,DC=corp,DC=contoso,DC=com",
    
    [Parameter(Mandatory = $false)]
    [String]$Trustee = "CORP\FimSyncAdmaResetPasswordAccess"
);

Write-Host "`nSsprPermissions.ps1 v1.0 Paul Williams (pawill@microsoft.com) Microsoft Services Feb. 2012`n";
Write-Host "`nTarget:  $Target`nTrustee: $Trustee`n";
Write-Host "Granting the following permissions...";
Write-Host '"Reset Password" Control Access Right (CAS) on descendent user objects';
[String]$cmd = "dsacls '$Target' /I:S /G '`"$Trustee`":CA;`"Reset Password`";user'";
Invoke-Expression $cmd |Out-Null;

Write-Host "Write Property (WP) lockoutTime on descendent user objects";
[String]$cmd = "dsacls '$Target' /I:S /G '`"$Trustee`":WP;lockoutTime;user'";
Invoke-Expression $cmd |Out-Null;

Write-Host "`nScript complete.`n`n";

In summary, the ADMA account needs the following permissions on users in scope of the SSPR solution:

  • Reset Password extended right.  This controls the ability to actually set (not change) a password.
  • Write Property lockoutTime.  This attribute is written to unlock the account.
Posted in FIM, FIM 2010, Self Service Password Reset, Troubleshooting | Tagged , , , , , , , , | Leave a comment