Get-NextBusinessDay

September 25, 2014 at 11:33 PMAndy Schneider

I had a need to calculate the next business day in a script I was writing.

Pretty short and sweet.

 

Function Get-NextBusinesDay {
param($days)
$date = get-date
$newDate = $date.AddDays($days)
switch ($newDate.DayOfWeek)

    {
       "Saturday" {$newDate = $newDate.AddDays(2); $newDate}
       "Sunday"   {$newDate = $newDate.AddDays(1); $newDate}
       Default {$newDate}
    }
}

 

image

Posted in:

Tags:

Seattle Script Club is Back!

September 23, 2014 at 12:02 AMAndy Schneider

James Brundage, Craig Martin, and I are happy to announce that after several years of hiatus, the Seattle Script Club is starting once again.

Script Clubs have been a great way to get people up and running with PowerShell, and a great place to meet other PowerShell enthusiasts.  They’re helpful for PowerShell newcomers, experts, and everything in between.  They’re a wonderful way to learn new things about PowerShell and improve your scripting skills.

The first new Seattle Script club is this Wednesday, September 24th, 2014.   They’ll happen every 4th Wednesday of a month.  The main event will happen in the Civica conference room at the Microsoft offices at 205 108th Ave NE, Bellevue, WA.   Social time will be in Bellevue, at a bar of the group’s choosing.  The first round for newcomers is on Start-Automating.

Here’s what the Seattle Script Club will have in store for you:

PowerShell Presentation (6:00PM-7:30 PM, Civica Conference Room, Microsoft Bellevue Offices (205 108th Ave NE)):

                Each month, we’ll be doing a 1-hour presentation on a topic of interest to Seattle area scripters.  The first month will be on SQL and PowerShell (It’s got some cool scripts in it, don’t miss it!).  The second month will be on PowerShell Cmdlet design.  The third month will be on intranet development with PowerShell.   Each presentation will be followed by extensive Q&A and interesting show and tell by other members of the group.

Socialization (8:00 - ?, Downtown Bellevue):

                After your brains have been thoroughly stuffed with PowerShell knowledge, clear your head and chat with your fellow scripters.  Each month we’ll be hanging out after Script Club and enjoying the company of our fellow scripters.  The first round for new attendees to Script Club is on Start-Automating.

We hope to see many familiar faces at Script Club, and meet new scripters in the Seattle area.

The Seattle Script Club is coordinated by James Brundage from Start-Automating, Craig Martin from Edgile, and Andy Schneider from Avanade

Posted in:

Tags:

Seattle Script Club is Back!

September 22, 2014 at 11:51 PMAndy Schneider

James Brundage, Craig Martin, and I are happy to announce that after several years of hiatus, the Seattle Script Club is starting once again.

Script Clubs have been a great way to get people up and running with PowerShell, and a great place to meet other PowerShell enthusiasts.  They’re helpful for PowerShell newcomers, experts, and everything in between.  They’re a wonderful way to learn new things about PowerShell and improve your scripting skills.

The first new Seattle Script club is this Wednesday, September 24th, 2014.   They’ll happen every 4th Wednesday of a month.  The main event will happen in the Civica conference room at the Microsoft offices at 205 108th Ave NE, Bellevue, WA.   Social time will be in Bellevue, at a bar of the group’s choosing.  The first round for newcomers is on Start-Automating.

Here’s what the Seattle Script Club will have in store for you:

PowerShell Presentation (6:00PM-7:30 PM, Civica Conference Room, Microsoft Bellevue Offices (205 108th Ave NE)):

                Each month, we’ll be doing a 1-hour presentation on a topic of interest to Seattle area scripters.  The first month will be on SQL and PowerShell (It’s got some cool scripts in it, don’t miss it!).  The second month will be on PowerShell Cmdlet design.  The third month will be on intranet development with PowerShell.   Each presentation will be followed by extensive Q&A and interesting show and tell by other members of the group.

Socialization (8:00 - ?, Downtown Bellevue):

                After your brains have been thoroughly stuffed with PowerShell knowledge, clear your head and chat with your fellow scripters.  Each month we’ll be hanging out after Script Club and enjoying the company of our fellow scripters.  The first round for new attendees to Script Club is on Start-Automating.

We hope to see many familiar faces at Script Club, and meet new scripters in the Seattle area.

The Seattle Script Club is coordinated by James Brundage from Start-Automating, Craig Martin from Edgile, and Andy Schneider from Avanade

Posted in:

Tags:

ADAL and PowerShell

September 9, 2014 at 6:18 AMAndy Schneider

ADAL v2 was just released. This is a library that makes it super easy to auth against Azure AD in an application.  Here’s a link to a very quick demo. http://www.cloudidentity.com/blog/2014/09/08/getting-started-with-adal-for-netquick-video-tutorial/

Well, if it can be done in WPF, surely we can do this in PowerShell. The first thing you have to do is make sure you have the Nuget command line tool installed.

Then you just run this command -

nuget install Microsoft.IdentityModel.Clients.ActiveDirectory

 

After that, you can find the 2 dll’s you need in the Microsoft.IdentityModel.Clients.ActiveDirectory.2.9.10826.1824\lib\net45 directory.

Now comes the fun part.

 

Add-Type -Path .\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.dll 
Add-Type -Path .\lib\net45\Microsoft.IdentityModel.Clients.ActiveDirectory.WindowsForms.dll 
$tenant = "yourdomainhere.onmicrosoft.com" 
$resource = "https://graph.windows.net" 
$clientID = "dfbf167a-add-your-own-clientid-here" 
$redirect = new-object System.Uri("http://powershell") #as long as this is unique in your tenant, all good 
$AuthContext = new-object Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext("https://login.windows.net/$tenant") 
$result = $AuthContext.AcquireToken($resource,$clientID,$redirect) 
$result

Posted in:

Tags:

Why teach your kid times tables when you can teach them times tables and a little bit of coding ?

March 16, 2014 at 4:21 AMAndy Schneider

So I promised my daughter a big present if she could learn all of her times tables, up to 12 x 12. Sure, we have some flash cards, and there are endless apps on any software platform to practice math facts. But why do that when you can write your own? The side benefit, is that she and I can personalize it to whatever we want. Next up is division, but she is going to have to help me code up that functionality.

 

image

 

image

 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;


namespace PracticeMultiplication
{
    class Program
    {
        static void Main(string[] args)
        {

            // Get the largest number to multiply by, up to 12
            // Choosing 2 will get 1 x 12 - 2 x 12, choosing 6 will get 1 x 12 up through 6 X 12

            Console.Write("What's the largest number you want to multiply (1-12) ? ");
            int max = Convert.ToInt32(Console.ReadLine());
            Console.WriteLine("Just type 'done' or 'q' to quit");
                      
            string studentAnswer = String.Empty;
            int score = 0; //total correct answers
            int correctAnswersInARow = 0; // correct answers in a row

            while (true)
            {

                ShowCurrentScore(score, correctAnswersInARow);

                // Generate a new problem using random numbers based on the max value
                // num2 will always be between 1 and 12
                Random random = new Random();
                int num1 = random.Next(0, max);
                int num2 = random.Next(0, 12);
                Console.Write("{0} x {1} = ", num1, num2);
                studentAnswer = Console.ReadLine();

                // check to see if we should quit
                if (studentAnswer == "done" || studentAnswer == "q")
                { 
                    break; 
                }
               // Convert to Int so we can multiply and see what the answer is
                int studentNumber = Convert.ToInt32(studentAnswer);
                int answer = (num1 * num2);

                if (answer == studentNumber)
                {
                    // Score and Correct get bumped up if they get it right.
                    score++;
                    correctAnswersInARow++;

                    // If they get 5 rigth in a row, they get a bonus of 5 points
                   // Using Modulo 5 to test for divisible by 5
                    if (correctAnswersInARow > 1 && correctAnswersInARow % 5 == 0)
                    {
                        score += 5;
                        WriteMessage("Bonus 5 points for getting 5 right in a row!", ConsoleColor.DarkGreen, score);
                    }
                    WriteMessage("Great Job Madeline! ",ConsoleColor.Green,score);
                }
                else
                {
                    WriteMessage("Oh bummer! Let's try another one",ConsoleColor.Red,score);
                    // reset to 0 since we got it wrong
                    correctAnswersInARow = 0;
                }
            }
        }

        private static void ShowCurrentScore(int score, int rightInarow)
        {
            Console.BackgroundColor = ConsoleColor.Blue;
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("Your score is {0}                        ", score);
            Console.WriteLine("You have got {0} correct answers in a row", rightInarow);
            Console.WriteLine();
            Console.ResetColor();
        }


        private static void WriteMessage(string Message, ConsoleColor Color, int score)
        {
            Console.ForegroundColor = Color;
            Console.WriteLine(Message);
            Console.WriteLine("Your score is {0}",score);
            Thread.Sleep(1000);
            Console.ResetColor();
            Console.Clear();
        }

    }
}

Posted in: C# | Parenting | Kids

Tags:

Active Directory Search that works - Ambiguous Name Resolution

March 5, 2014 at 10:40 PMAndy Schneider

I am not a big fan of having to specify filters using the syntax prescribed for Get-ADuser.  Ambiguous Name Resolution is an old API that allows you to query against multiple attributes at the same time. There is some more information on ANR here http://support.microsoft.com/kb/243299

By default, the following attributes are set for ANR:

  • GivenName
  • Surname
  • displayName
  • LegacyExchangeDN
  • msExchMailNickname
  • RDN
  • physicalDeliveryOfficeName
  • proxyAddress
  • sAMAccountName

It turns out you just need to pass in an LDAP Query. Once you get the list of results, you can pipe them into the Get-ADuser cmdlet to get the user objects as you would expect them. All we have to do is build an LDAP Filter and query against an attribute called ANR. This will return all objects that have an attribute from the list above that maches User. You can kind of think of it as a wildcard search on steroids.

Function Get-User {
param(
[Parameter(ValueFromPipeline)]
$User
)
BEGIN {import-module activedirectory}
 
PROCESS {
 
   $filter = "(&(ObjectClass=User)(ANR=$User))" 
   Get-ADObject -LDAPFilter $filter  |
   Get-ADUser
}
 
}

Hope this is helpful.

Posted in:

Tags:

FIM and Orphaned Expected Rule Entries (ERE’s)

June 24, 2013 at 7:51 PMAndy Schneider

I just started working with FIM 2010 R2 in a development environment. Before you read any further, please take this into consideration. All of this has come from a development environment. I would never do this in a production environment. I would probably go as far as to say that my level of fear and caution for “Hey, what does this button do?” type of scenarios is probably a little too low.

With that understanding, let’s get to the point. I was setting up a typical scenario with a SQL MA and and Active Directory MA. The SQL Database has approximately 50,000 entries that I needed to pull into the metaverse. I like to learn by doing. Yeah, I read a little bit before I started, but clearly not enough. I was still trying to figure out if I was going to use classic rules or if I was going to need to use the FIM portal to create Synchronization rules. After several imports, exports, and syncs, and then messing with Sync rules, I finally decided that I actually did need to use the FIM portal and Synchronization rules. I wanted to start with a completely clean slate. So I went in and deleted everything, including MA’s.

The problem came up when I deleted the FIM service Management Agent connector space. No matter what I did, every time I did an import, it would pull in about 150,000 Expected Rule Entries, or ERE’s.

Poking around in the FIM Script Box, I found some PowerShell code that could delete these for me. Basically, it does a search for all the orphaned ERE’s using the FIM web service under the hood of the “Export-FIMConfig” PowerShell cmdlet. Well this is great if you are looking at a couple 100 objects. But with 150,000 objects, I was looking at more like days.

So I decided to poking around a bit more. I figured that at the end of the day, these objects have to be somewhere in the database. If you are getting worried now, don’t. I promise it gets better. Looking at the FIMService database, I found one table that was particularly interesting. There is a FIM.objects table. Sweet!

image

Here’s where it got a little nuts. Looking in the connector space, I found the object ID of ONE of my orphaned ERE’s. It had an objectID of something like “B8A72DEB-6A7F-482F-81A6-8DD66D91D6EA.”

So I ran a quick query like the following

SELECT * FROM Fim.Objects
WHERE ObjectID = 'B8A72DEB-6A7F-482F-81A6-8DD66D91D6EA'

Here I found out that it had an ObjectType of 11. Looking at the table, it was referencing the ObjectTypeInternal table.

image

So the next thing I did was run a similar query and found “Astonishingly!” that there were about 150,000 ERE objects with ObjectType = 11.

Using this query, I was able to find all the ObjectKey’s of all the objects I needed to delete.

SELECT * FROM Fim.Objects
WHERE ObjectTypeKey = 11

Now I needed a way to delete these suckers. Looking over the database, I was wondering if there might be some stored procedure I might be able to use.

Low and Behold, sitting there, was something called debug.DeleteObject

image

Nevermind the “Debug” prefix on this stored procedure. Using a little Excel Magic, I created a huge long SQL command (What can I say, I am not a SQL guy) that looked something like this. I basically took the ObjectKey column from the last query, dumped it in excel, and then used some string manipulation to generate my SQL script.

image

 

Here’s what eventually what went into SQL Query Analyzer – actual code was 150,000 calls.

image

Running this only took about a little over 2 hours. Way faster than using the Import-FimConfig and Export-FIMConfig. Using the web service abstraction layer is great and all, but sometimes you just need to bypass as much as possible.

So the next time you are working in a development environment and feel like taking a chance on blowing off your toe, or maybe your whole foot, this just might help!

Posted in: PowerShell | FIM

Tags:

Using Claims Authorization Rules in ADFS 2.0

December 19, 2012 at 2:10 AMAndy Schneider

I am willing to bet that 90% of the time you have created claims you never really noticed that there are actually 3 tabs for claims that you can use.

image

Most of the time, we are just messing with the “Issuance Transform Rules.” When you walk through the “Add a Relying Party” Wizard, you may not notice the claim that gets created automatically in “Issuance Authorization Rules.”

Here is a screen shot of the rule that says “Allow everyone”

image

If we look at the claim, we can see that it is of type permit and the value it true

image

You can also create a rule that says “Deny someone with this value of a claim.” For instance, I can add a rule that says “Deny access to this Relying Party if anyone tries to log in and has a claim of type Name with a value that looks like “Andy”

image

By the way, the =~ syntax is saying If a claim of type Name has a value that matches the regular expression, then issue the claim of type deny with a value of “DenyUsersWithClaim.”

You can also issue a strict deny all by doing a straight deny like this

=> issue(Type = "http://schemas.microsoft.com/authorization/claims/deny", Value = "true");

So this is all great but what if you need to combine some of these rules and perhaps make an exception for a handful of users. When I first started messing with this, I figured these authorization claim rules would act like a firewall policy. It would start at the top, and then would act on the first rule that it matched, and then processing would stop. THIS IS NOT THE CASE. What made me really think this was the case was that there is an option to rearrange the order of the claims.

image

You wish it were so easy!  It turns out that if there is a “Deny” rule that matches a users claim anywhere, it will always win, no matter where on the list it is. So in this case, even though permit all is first, if I have a claim that says my “Name” is “Andy” then I will get a denied access error.

We have to get a little tricky. Lets say we want to deny everyone from a particular Identity Provider except for 3 separate users. How would we go about it. Here is one way.

First, lets figure out an easy way to determine at the claims authorization rule, which IDP the user came from. If you go to “Trust Relationships | Claims Provider Trusts” You will see a trust for Active Directory and any other IDP’s that you have added. For the sake of demonstration, lets say you have one called Contoso.  Right click on the Contoso IDP and select “Edit Claim Rules”

You can add a claim using a custom rule. Choose “Send Claims Using a Custom Rule.” You can use any namespace that you want. I would suggest using one namespace for custom claims and sticking with it. For this demo, I am using http://sso.contoso.com/users

This rule will add a claim to all users that log in from the Contoso STS that says “Company” = “Contoso”

image

 

All right so now we have the claim for people from Contoso, but we want to create exemptions for foo@contoso.com, bar@contoso.com, and andy@contoso.com.

To do this, we need to go back to our Relying Party Authorization Rules and add a new custom rule.

 

image

Here’s how this rule breaks down. For a bit more details, I would highly suggest reading through the claims rule language primer.

Here’s the actual claim rule

c1:[Type == "http://sso.contoso.com/users/Company", Value =~ "^(?i)Contoso$"]
&& c2:[Type == "
http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn", Value =~ "(?<!foo|bar|andy)@contoso.com"]
=> issue(Type = "
http://schemas.microsoft.com/authorization/claims/deny", Value = "DenyUsersWithClaim");

Here’s the basic logic of the claim rule

If  ((claim.Company matches “Contoso”)  AND (claim.upn –NOTEQUAL (andy@contoso.com OR foo@contoso.com OR bar@contoso.com)) Then (Issue “DenyUsersWithClaim”)

Perhaps the trickiest part here is the REGEX that filters out the exceptions. Basically, the “!” says “not match” and the “|” symbol is the Alternation operator – or functionally the "-or” operator.

Now, all users from Contoso will get denied access except for the 3 that match the regex.

Posted in: ADFS | Claims | Authorization

Tags:

Using Enterprise AD Credentials to Manage Azure Access Control Service

December 15, 2012 at 2:10 AMAndy Schneider

ACS is Azure’s Access Control Service. It is a cloud based Secure Token Service (STS). With the recent advent of Windows Azure Active Directory and ACS being offered for free, I am envisioning more and more enterprises beginning to leverage these services.

Typically, when you create a Azure ACS namespace, you login with a Windows Live ID and create/delete/manage services. However, if you have an Identity and Access Management team in your enterprise, you may want to have a bit more control over who can manage ACS and also ensure that they are using their AD credentials rather people’s personal Windows Live accounts. This is now completely possible using on premise ADFS.

This post assumes you have built out and installed an ADFS infrastructure and are familiar with adding Relying Parties and using claims.

To create a new ACS namespace, you will need to go to https://manage.windowsazure.com, log in to the portal, and then click on your name and choose Previous Portal.

image

In the old portal, you can manage Service Bus, Access Control, and caching.

image

Click on there and create a new ACS Namespace. Once the namespace is created, you can go in and manage “Identity Providers”

Typically, this is allowing you to add ID Providers that you will use to authenticate users to your Relying Parties. Live ID is there by default, and you can add more like Google, Facebook, and Yahoo!

image

The one you need here is WS-Federation ID Provider (ADFS 2.0)

From there you can give the URL of your ADFS federation metadata. It is typically something like https://sts.example.com/FederationMetadata/2007-06/FederationMetadata.xml

You must also add ACS as a Relying Party to your ADFS instance as well to establish a trust.

Now that you have added your ADFS service as a Trusted Identity Provider, you can use ADFS to authenticate your relying parties.

However, that is not the end goal in this scenario. We want to set up ACS so that we can log in to the management portal with our Active Directory Credentials. Here’s what else you need to do.

In ACS, to to Administration and choose Add Administrator

image

The one thing you will need to do is specify the claim and value that has permission to manage the portal.

I would suggest you use a Role claim and then in ADFS on your side, you can map a group in AD to that role claim.

Here’s the role claim

image

The value you specify is the value of the claim you set in ADFS when you add the claim rule to map a claim to a Group Membership. An example would be Domain\ACSAdministrators

To test this out, you should add yourself to the ACSAdministrators group you created and then try and authenticate to the management URL for your ACS Namespace. It will be something like https://get-powershell.accesscontrol.windows.net/v2/mgmt/ From there, you will be prompted for which ID Provider you want to log in with. Choose your ADFS provider, log in with your corporate credentials, and you will have access to manage ACS.

Posted in:

Tags:

A New Blog !

August 9, 2012 at 5:19 AMAndy Schneider

Hey folks. I wanted to let you know I have started a new blog over at The IT Fishing Pole. The basic concept of the Fishing Pole is the old saying “Give a man a fish, feed him for a day. Teach him how to fish, feed him for a lifetime.. or at least until he’s sick of seafood.”

I will still keep Get-PowerShell around and write occasional posts here but I am starting to get into a lot more technologies including Identity Management, ADFS and  PKI to name a few, and I wanted a more generic platform for these articles. Plus, I have to say, there is something that just feels good about starting something brand new.

Thanks for reading!

-Andy

Posted in:

Tags: