Skip to content

Instantly share code, notes, and snippets.

@sean-m
Created December 6, 2018 00:19
Show Gist options
  • Save sean-m/b00dd399d4eaeae24d56743aa86b9f69 to your computer and use it in GitHub Desktop.
Save sean-m/b00dd399d4eaeae24d56743aa86b9f69 to your computer and use it in GitHub Desktop.
Compiles ADFS StringProcessingAttributeStore as documented on MSDN with an added capability to check bitfield flags.
#Requires -Version 4 -Module ADFS
<#
Compiles ADFS StringProcessingAttributeStore from here:
https://msdn.microsoft.com/en-us/library/hh599320.aspx?f=255&MSPPError=-2147217396
* Notice: must be run as Admin, will prompt UAC *
Steps taken:
1. download dependency from nuget
2. extract library and copy to C:\ADFS
3. compile attribute store to dll
4. register libraries with GAC
5. remove unpacked zip files (with confirmation)
- Sean McArdle 9/2018
#>
cd $(Split-Path -parent "$($MyInvocation.MyCommand.Definition)")
# Run as admin
If (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))
{
$arguments = "& '" + $myinvocation.mycommand.definition + "'"
Start-Process powershell -Verb runAs -ArgumentList $arguments
Break
}
if (-not (Test-Path C:\ADFS)) { mkdir C:\ADFS }
if (-not (Test-Path .\Microsoft.IdentityModel.dll)) {
Write-Host "Downloading archive msid.zip from nuget"
Invoke-WebRequest -OutFile .\msid.zip -Uri https://www.nuget.org/api/v2/package/Microsoft.IdentityModel/6.1.7600.16394 -UseBasicParsing
Expand-Archive -Path .\msid.zip -DestinationPath .\msid -Force
Write-Host "Copying dll from zip file"
Copy-Item .\msid\lib\net35\Microsoft.IdentityModel.dll "C:\ADFS\Microsoft.IdentityModel.dll" -Force
}
Write-Host -NoNewline "Compiling to: $env:temp\StringProcessingAttributeStore.dll"
try {
Add-Type -Language CSharp -TypeDefinition @"
//-----------------------------------------------------------------------------
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
//-----------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.IdentityModel.Threading;
using Microsoft.IdentityServer.ClaimsPolicy.Engine.AttributeStore;
namespace StringProcessingAttributeStore
{
public class StringProcessingAttributeStore : IAttributeStore
{
#region IAttributeStore Members
public IAsyncResult BeginExecuteQuery(string query, string[] parameters, AsyncCallback callback, object state)
{
if (String.IsNullOrEmpty(query))
{
throw new AttributeStoreQueryFormatException("No query string.");
}
if (parameters == null)
{
throw new AttributeStoreQueryFormatException("No query parameter.");
}
if ((query == "toUpper" || query == "toLower" || query == "base64") && parameters.Length != 1)
{
throw new AttributeStoreQueryFormatException("More than one query parameter.");
}
if (query == "bitFlag" && parameters.Length != 4)
{
throw new AttributeStoreQueryFormatException("bitFlag operations require 4 parameters: input, operand, true result, false result.");
}
string inputString = parameters[0];
if (inputString == null)
{
throw new AttributeStoreQueryFormatException("Query parameter cannot be null.");
}
string result = null;
switch (query)
{
case "toUpper":
{
result = inputString.ToUpper();
break;
}
case "toLower":
{
result = inputString.ToLower();
break;
}
case "base64":
{
// Assume that input string is in UTF-8 form.
result = Convert.ToBase64String(Encoding.UTF8.GetBytes(inputString));
break;
}
case "bitFlag":
{
// Expects parameters like so: bitfield value, field to check, success result, fail result.
// Parse inputs
UInt64 bitfield = UInt64.MinValue;
UInt64.TryParse(parameters[0], out bitfield);
UInt64 offset = UInt64.MinValue;
UInt64.TryParse(parameters[1], out offset);
string res_true = parameters[2];
string res_false = parameters[3];
// Check flag in bitfield
result = ((bitfield & offset) != 0) ? res_true : res_false;
break;
}
default:
{
throw new AttributeStoreQueryFormatException("The query string is not supported.");
}
}
string[][] outputValues = new string[1][];
outputValues[0] = new string[1];
outputValues[0][0] = result;
TypedAsyncResult<string[][]> asyncResult = new TypedAsyncResult<string[][]>(callback, state);
asyncResult.Complete(outputValues, true);
return asyncResult;
}
public string[][] EndExecuteQuery(IAsyncResult result)
{
return TypedAsyncResult<string[][]>.End(result);
}
public void Initialize(Dictionary<string, string> config)
{
// No initialization is required for this store.
}
#endregion
}
}
"@ -OutputAssembly $env:temp\StringProcessingAttributeStore.dll -ReferencedAssemblies @("C:\ADFS\Microsoft.IdentityModel.dll","C:\Windows\ADFS\Microsoft.IdentityServer.ClaimsPolicy.dll")
Write-Host -ForegroundColor Green " Done!"
copy-item $env:temp\StringProcessingAttributeStore.dll "C:\ADFS\StringProcessingAttributeStore.dll" -ErrorAction Stop -Verbose
[System.Reflection.Assembly]::Load("System.EnterpriseServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")
$publish = New-Object System.EnterpriseServices.Internal.Publish
$publish.GacInstall("C:\ADFS\StringProcessingAttributeStore.dll")
$publish.GacInstall("C:\ADFS\Microsoft.IdentityModel.dll")
del -Recurse .\msid -Confirm
}
catch {
Write-Host -ForegroundColor Red " Error!"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment