Active Directory

Updating the Country Field in Active Directory

Wanting to have all users to have the country ‘Australia’ in Active Directory, I thought it would be a simple PowerShell command. Get all the users you want and set a field to ‘Australia’. However, it’s more complicated than that.

As you can see from the above, the Country/region field is a dropdown, where you can select the country. If you look in PowerShell using ‘get-aduser username -properties *’, there’s 4 fields that get populated with this setting:

c : AU
co : Australia
Country : AU
countrycode: 36

Trying to just change one of these fields will result in an error such as:

Set-ADUser : A positional parameter cannot be found that accepts argument ‘Au’.
Set-ADUser : A positional parameter cannot be found that accepts argument ‘Australia’.
Set-ADUser : A value for the attribute was not in the acceptable range of values

The answer is that all fields need to be set at the same time. The C and Country fields are based on ISO 3166 codes, with Australia being AU and 36.

The resulting command would end up being:

set-aduser adam.fowler -Replace @{c="AU";co="Australia";countrycode=36}

Of course this can be done on a boarder scale by using ‘get-user’ with a larger scope, and piping that into the set-aduser command:

get-aduser -filter "company -eq 'Contoso'" | foreach {set-aduser $_ -Replace @{c="AU";co="Australia";countrycode=36}}

That’s all that’s required to change the field.

Checking CSV Against Active Directory Users

I’ve written before on how to update Active Directory from a CSV. This time, I’ve got a CSV list of users that I want to check are valid users against my Active Directory (AD) environment.

There’s a huge amount of ways this can be done, and this is just one of them. If you have others, or ways to improve this I’m always keen to hear!

This script assumes you have a CSV file with the header (first line) with the word ‘users’. Here’s an example CSV file: myusers.csv

Below is the PowerShell script I wrote. I’ve also written about ‘If’ and ‘Else’ before, so read that if you want some clarification. The user list I have is based on User Principal Name (UPN) rather than just username, so I’m searching AD to see if there’s a match or not.

Import-Module ActiveDirectory

$Data = Import-Csv myusers.csv

foreach ($user in $data){
$upn = $users.user
$check = $(try {get-aduser -filter "userprincipalname -eq '$upn'"} catch {$null})
if ($check -ne $null) { }
else { "$upn Doesn't Exist" }
}

What I’m doing here is setting each line of the CSV as the $UPN variable to search for. Then using the ‘Try‘ function, I’m catching if there is no result/match (null). If there’s a match, it won’t equal null, so display nothing. Else, show the UPN via the $UPN variable and follow that with ‘Doesn’t Exit’.

This way, I will only get results back from each AD search where the UPN in the CSV doesn’t match a user’s UPN in my AD environment – and I get to see what those results are.

This script method can be applied in many different ways of course, but it was the first time I’d used the Try function, and it worked really well.

 

Azure AD Group-Based License Management For Office 365

It’s finally here! At least in public preview…

The ability to allocate Office 365 licenses via groups is now available for everyone to use. This has been a long-awaited feature, up until now licenses have either been applied manually via the portal, or via scripts/3rd party software with logic applied for automation.

Now, you can automatically apply and manage license allocation using whatever logic you like. You can create on-premise AD groups, apply a license set to the groups, and members will be allocated the relevant licensing. If that doesn’t work for you, there’s also cloud based Dynamic Groups which let you use whatever logic you can come up with to add members to the group. You could do it on something like a department name, or use an extension attribute and populate that based on what license you want to allocate.

The above link covers a lot of information about how to deploy this. At the time of writing, I couldn’t get to the Azure Licensing page by searching for the word ‘Licensing’, and instead had to use a direct link: https://portal.azure.com/#blade/Microsoft_AAD_IAM/LicensesMenuBlade/Products

I’ve already deployed it, it seems to work quickly and without issue.

 

Once you’re done, you’ll need to remove the Office 365 licenses applied manually. This TechNet article shows the commands to use for removal. I used this:

$Users = Get-MsolUser -All | where {$_.isLicensed -eq $true}; $Users | foreach {Set-MsolUserLicense -UserPrincipalName $_.UserPrincipalName -RemoveLicenses "litwareinc:ENTERPRISEPACK"}

This removes licenses from all your users, to be more specific add extra criteria to the first ‘Get-MsolUser’ command. Also note you need to swap ‘litwareinc’ with your tenant ID, and ENTERPRISEPACK with whichever license you’re removing. I’d recommend testing on one account first!

To see what your tenant’s license options are just use:

Get-MsolAccountSku

And you’ll see a list of the license options along with existing allocations.

If you have any questions please comment below.

Azure Active Directory – Assigning Groups to Applications in PowerShell

Azure Active Directory Applications have been around for a while, but it’s I’ve found it hard to find good information on them beyond the biggest benefit of Marketplace Apps.

Along with my Azure AD B2B journey (still in preview at time of writing), the option of pushing out something like a SharePoint Online site as an app is one of the jigsaw pieces required to make the whole B2B process work – as a version of the apps page is displayed as the default link to anyone who accepts an Azure AD B2B invite and logs in for the first time.

MyApps – an externally invited user will only see the apps they have access to (by default, none)

I’m trying to gloss over details here, as there’s a lot of steps with different parts of the Microsoft world to get a process automated end to end for inviting external users to a SharePoint Online site – but the last step of assigning a user or group to an application has no documentation I could find, that showed how to achieve this via PowerShell.

All I want to do here, is create an Application in Azure AD, then assign a group to it. Members of the group will then see the application on MyApps.

Two different modules are required – Azure Active Directory V2 PowerShell module and Azure Resource Manager.

What we can do with these two modules is first create the application with the New-AzureRMADApplication command:

New-AzureRmADApplication -DisplayName "SharePoint Online Site A" -HomePage "https://contoso.sharepointonline.com/sitea" -IdentifierUris "https://contoso.sharepointonline.com/sitea"

Easy, now you have an application that will point to the URL entered in Azure Active Directory. Assigning a group to it is a bit trickier…

First, a few values need to be obtained:

$app = Get-AzureRmADApplication | where displayname -eq "SharePoint Online Site A"
$appid = $app.ApplicationId
$fullgroup = get-msolgroup -all | where displayname -eq "SharePoint Online Site A"

This is getting the two objects as variables – the Application itself, and the group that you want to add onto it.

Then a new Service Principal needs to be created based on the Application, as this is required when adding the group onto the application:

New-AzureADServicePrincipal -AppId $appid

Another variable is needed, which is the new Service Principal we just created:

$servicePrincipal = Get-AzureADServicePrincipal -Filter "appId eq '$appId'"

Finally, we can assign the group to the application:

New-AzureADGroupAppRoleAssignment -objectid $fullgroup.objectid -principalid $fullgroup.objectid -resourceid $serviceprincipal.objectid -id ([Guid]::Empty)

You can check that this has applied by the Azure Active Directory portal too, by going to your Active Directory section, choosing ‘Applications’ and finding your app, then go into ‘users and groups’ and find the group. You should see a ‘yes’ in the assigned field.

If there’s any interest in documenting the entire SharePoint Online and Azure AD B2B invite process and script, let me know. It’s a great way of sharing data with clients via a portal.

Update 15th June 2017

Microsoft made a change with the IdentifierURI field, which is also called AppID if you view it in the Azure portal. Previously, it could be any unique URL, it just has to be unique amongst your apps (as to why it has to be a URL at all, I couldn’t get an answer on). Now, it can be anything as long as it’s not sharepoint.com or dynamics.com as they’ve reserved those for other reasons. My example above, and what I’d been using in production was variants of sharepoint.com – as the unique URI might as well be the actual URL of the site. If you use a URL that’s not allowed anymore, you’ll get the error:

New-AzureRMADApplication : Operation returned an invalid status code ‘BadRequest’

 

AzureAD – Assign Application to User via PowerShell

Scenario:

You’ve created an application in Azure AD, and want to script allocating access to the app rather than using the web interface. App show up at https://myapps.microsoft.com

Azure AD Premium is required for group access which would be ideal, but if you don’t have that you’ll need to add access on a user by user basis.

Answer:

PowerShell of course. First, you’ll need Azure AD for PowerShell (Preview version 2.0.0.17 at time of writing).

The below script which I modified from Philippe’s comment here should cover both internal, cloud and B2B invited users. The original script was using -objectid rather than -searchstring which works better and is more accurate for the internal and cloud accounts, but doesn’t work at all for B2B accounts.

The AppID can be obtained from this command:

Get-AzureADApplication -SearchString “Display Name for App”

Put the corresponding AppID into the below script, and you’re good to go. You’ll get prompted for Azure AD credentials as per usual. You can also get this

This is designed for a single user addition, but you could easily import the email addresses from a CSV file, and do a ‘for each’ on each entry like I did here.

# The UserPrincipalName or ObjectId of the user
  $userId = "email@contoso.com"

# The AppId (a.k.a. "client ID") of the app to assign the user to
  $appId = "AppIDGoesHere"

# Connect to Azure AD
  Connect-AzureAD -Confirm

# Get the user to be added
  $user = Get-AzureADUser -searchstring $userId

# Get the service principal for the app you would like to assign the user to
  $servicePrincipal = Get-AzureADServicePrincipal -Filter "appId eq '$appId'"

# Create the app role assignment
 new-AzureADUserAppRoleAssignment -ObjectId $user.ObjectId -PrincipalId $user.ObjectId -ResourceId $servicePrincipal.ObjectId -Id ([Guid]::Empty)

 

Note: If you try this and get the error below, it’s because the app is already assigned.

new-AzureADUserAppRoleAssignment : Error occurred while executing NewUserAppRoleAssignment
StatusCode: BadRequest
ErrorCode: Request_BadRequest
Message: One or more properties are invalid.
At Z:\script.ps1:17 char:1
+ new-AzureADUserAppRoleAssignment -ObjectId $user.ObjectId `
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [New-AzureADUserAppRoleAssignment], ApiException
+ FullyQualifiedErrorId : Microsoft.Open.AzureAD16.Client.ApiException,Microsoft.Open.AzureAD16.PowerShell.NewUser
AppRoleAssignment

Softerra Adaxes – Several Months In

logo-1

Softerra Adaxes is an Active Directory management & automation tool which I’ve grown very fond of.

First I reviewed Softerra Adaxes, then I actually bought Softera Adaxes and even did a brief case study for them. I thought it would now be good to share how far we’ve come through using this tool, and what the experience is like for those considering this option of automation. Here’s my thought process and how I personally approached the rollout, along with my experiences along the way:

Initially to me, the idea of having an ‘Outlook rules’ style approach to building a system that automated user management was enough to me. We’d been creating accounts manually for a long time, and the process was documented but took 20 minutes or so to perform. There was also a lot of room for human error, especially when someone was interrupted while creating an account.

There was of course the ‘selfish’ reason of not wanting to do these user management tasks myself, but it’s hard to pass those tasks off with the inherit risks or lack of knowledge of the tools being used to ease the process. This is what had held me off writing my own giant PowerShell script to automate all the steps.

After mucking around with the Adaxes basics, I started to realise that this software solution seemed to actually deliver on what I was personally looking for – something that wasn’t complex, but also let me define whatever criteria, business rules and caveats to the user creation process that I wanted. On top of that, there was inbuilt webpages where I could deliver these options to other staff requiring no software installs, and the ability to show or lock down whatever I chose, to both control and protect the Active Directory environment.

It did take a few weeks to set up properly, but I wouldn’t have really spent more than an actual day’s worth of work in those few weeks doing it. That was just to create a new user in all the various systems I wanted, with our unique user setting requirements. I wouldn’t say the entire system is so simple and easy to navigate that you can get cracking, but it’s also not complex. Once you find the setting or understand how Adaxes achieves a solution, it’s not difficult to set things up.

The inbuilt functionality of website templates – where you can create multiple sites displaying whichever fields you like to whichever users you like – is a good way to deliver the solution to end users. You can have a page for IT and another page for Finance with completely separate functions to best fit each use case.

For me, it was great that I could create websites with zero programming requirements. It’s all driven by a GUI, and somehow it’s still very flexible in what it can do. It might be frustrating to someone who actually writes code, but that’s not who would normally be using this solution. I really feel it’s aimed at someone like me, the IT Pro/Sys Admin who wants to automate and allow others to use the tools, without needing to code or expect others to run PowerShell commands themselves.

adaxes1Basic site with one option – menu and right side options can even be hidden if required.

Once I’d finished the user creation process and published the method of doing so to a website, I had internal staff muck around with it and use it, purely for new user creations. The feedback I received was immediately positive – that 20 minute or so process had been reduced to a few minutes, and even generated out an email saying the account creation was done. This in itself to me was the tick of a successful project, and I knew I could do a lot more around automation and empowering others to do repeatable tasks.

Some of the problems I hit on the user creation automation were:

  • After upgrading from Lync 2010 to Skype for Business 2015, there were intermittent errors popping up for creating a SfB user. This was a known problem to Softerra, and took several months to resolve with a new version of Adaxes. I did have a workaround luckily, so it only took some rule modifying to work around it until a proper solution was found.
  • ‘User unknown’ – I ran into some problems where I’d create the user or enable them for Exchange, but then the next command wouldn’t find the account. Adaxes was faster than what other systems could replicate changes, so some tactful ‘start-sleep’ PowerShell command steps during the workflows to allow replication to occur before the next step triggered. This does mean that the overall process can take a minute or two, and the person who triggered the user creation has to wait for it to finish.
  • Not all functionality was available that I needed in the GUI. For example, creating a Skype for Business user is easy, but you can’t assign a policy. Instead you need to use PowerShell commands to do what you want. That took a bit longer and needed more testing, but wasn’t much of an issue once I found that out.
  • When a new user was created that already existed (e.g. another John Smith – john.smith) I hadn’t considered that scenario. I asked in the Adaxes forums and was told how to run some pre-checks to make sure the username and phone number were unique and bomb out if they weren’t, rather than half creating an account and having to clean it up afterwards.
  • The upgrade process isn’t painful when a new version of Adaxes comes out (which came out while I was doing the user creation and I wanted to try upgrading early on), but there’s a few more steps than next, next finish. An uninstall is required with backing up a few files, then a fresh install and importing what you backed up. I’m hoping that will be streamlined a bit in the future.

After the user creation process was settled, I started to create more automation tasks. Deprovisioning was an obvious one, and was a lot easier than user creation as well as taking a lot less time to set up. This command would clean up all the bits and pieces from an account, including home drives and Exchange settings (along with moving the mailbox to a different database). This was rolled out relatively quickly.

I should also note, the logging is very helpful. If someone triggers a command from the website, they can see if it was successful or not, or where it failed. It made testing easy to do, but I was also able to read through logs via the GUI on the server to find out more about what failed and why.

adaxes2Updating options on one of the web interfaces – no coding required.

I then decided to wait for common scenarios to come up and build them as needed. We often had ‘returning staff’ which if their Active Directory account still existed, I couldn’t use my user creation method when the account already exists. This took a rethink of how I’d designed my rules so far, and decided to re-do a lot of it in a more modular fashion. Because there’s the ability to copy and paste rules, this was a lot easier than I expected. The end result was that I’d have a list of modules to run against a task – e.,g. a new user would call commands such as ‘enable email’ and ‘enable Skype for Business’ which my new ‘returning staff’ would call ‘re-enable email’ but the same ‘enable Skype for Business’ command as a new user. This now meant I could move a mailbox from one database to another and unhide the user from the Global Address Book when they returned, but because all users have their Skype for Business disabled, that step was the same in either scenario.

Another valuable idea I had was to let users control the membership of Active Directory groups that they were the owner of. After some mucking around, I created a website solely for that purpose. The great part about it was that whomever logged onto the site (with passthrough authentication so no extra typing required) could only see groups they were an owner of, based on the Manager field in Active Directory. This gives anyone in the company who is in control of a group, the ability to add or remove members without any IT assistance required. Perfect for application owners who control who can get to their application or not via a security group.

My next task will be the automation of a user name change. With the updated modular design, I can copy out the steps that I need and modify them to my new requirements; of course finding the hour or two to build and test this is the hardest part. (Note: Between the week of writing this and publishing, I’ve now done it.

I’ll give praise to both the Adaxes forums and their helpdesk support via email- almost always, within 24 hours max (and usually 4-5 hours) I’d get a specific and clear answer on how to do something I couldn’t work out personally, and it was from someone who knew the product rather than a basic 1st level helpdesk type response.

I hope this gives a real impression of my experience and opinion of Softera Adaxes at a high level, after using it for an extended time. There’s no real gaps to the product that I’ve found. and you can pick and choose as to how much customisation you want to do through PowerShell scripting. I’m still happy with the product, and it will continue to evolve with us.

Fix Wrong Domain for Users Azure Active Directory

I ran into a problem where a user couldn’t sign into Intune, which uses Azure Active Directory to authenticate users.

After checking the user in question on the Azure Active Directory portal, I noticed the domain was wrong:

aad

The user was being synced from On Premise Active Directory, so I had a look via Users and Computers to see what was going on. The user’s User Principal Name domain field was set differently to other users – instead of the proper mydomain.com, it was set to mydomain.local – another valid internal domain to Active Directory, but not one that Azure Active Directory knew about:

aad2

The unknown domain caused Azure Active Directory to disregard it, and instead use it’s default tennancy domain of wrong.onmicrosoft.com. I thought just changing the dropdown menu to mydomain.com instead of mydomain.local would fix it, but a forced Azure Active Directory Sync sync reported the change was successfully synced, but didn’t actually change the value.

I’m going to guess this is by design, as you don’t usually want logins changing. There is an easy way to change the via PowerShell instead.

Once you’ve run the standard ‘Connect-MsolLService‘ cmdlet, you can use ‘Set-MsolUserPrincipalName‘ to change the user. The full command is:

Set-MSolUserPrincipalName -userprincipalname “existinguser@mydomain.local” -NewUserPrincipalName “existinguser@mydomain.com”

Pretty simple, and the change is immediate.

I then realised there may be other users with the same problem, so dediced to use the Active Directory PowerShell Module with this command:

get-aduser -filter * | where {$_.userprincipalname -like “*local*” -and $_.enabled -eq “true”} | select name

This showed all the users who had ‘local’ in their UPN. As there were only a few, I changed them all one by one with the first command above.

The same check can be run against Azure Active Directory users with this command:

get-msoluser -all | where userprincipalname -like “*local*”

Easy!