Null and Not Null with PowerShell

Finding out if an object has a null (i.e. blank) value or not isn’t a difficult task to do.

Consider this scenario – you’ve found a bunch of old disabled accounts that someone forgot to remove the ‘Manager’ field. Finding accounts that have another field that would be populated for a current employee but blank for a departed would be a reasonable way of finding the problem accounts, then you could null the ‘Manager field. (note – you could just refine your search to disabled accounts but that’s not as fun).

To find all Active Directory users that have a blank ‘Department’ field is easily done with this command:

get-aduser -filter * -properties department | where department -eq $null

Then, showing the users that don’t have a blank ‘Department’ field is a slight change. You can’t use !$null (!=not), but you can use -ne (not equals)

get-aduser -filter * -properties department | where department -ne $null

You can also check for users that have a manger by switching ‘department’ to ‘manager’:

get-aduser -filter * -properties maanger | where manager -ne $null

Easy. Adding in a second ‘where’ statement so we can get results of users that have a manager, but no department means we have to add in a few extra characters to make PowerShell happy:

get-aduser -filter * -properties department,manager | where {($_.department -eq $null) -and ($_.manager -ne $null)}

The results can be a bit hard to read, so piping (|) to a select command will just show us the results of each user we want to see:

get-aduser -filter * -properties department,manager | where {($_.department -eq $null) -and ($_.manager -ne $null)} | select name

Finally, to blank the ‘manager’ field, we can swap the ‘select name’ command with this:

get-aduser -filter * -properties department,manager | where {($_.department -eq $null) -and ($_.manager -ne $null)} |  set-aduser -manager $null

You can then go back to a previous command to confirm you get no results. As always, check your data first before blanking out a bunch of user’s values!

Update

As @mickesunkan pointed out, the above isn’t the most efficient way to do searches. I’m sure I’ve mentioned this before, but I’m not always going to write the cleanest, quickest way of doing something. For a once off tasks this really doesn’t matter. For a daily task it starts to matter – not really by itself, but if you keep making more and more inefficient scripts, you’re putting extra unnecessary load on your environment with lots of LDAP lookups.

Above, I’m just getting ALL AD users. You could use a better filter and narrow down to a certain OU. You could also put part of your ‘where’ command into the filter, such as this:

get-aduser -properties manager,department -filter {department -notlike “*”}

This doesn’t work for the ‘Manager’ field though, you’ll see this error:

get-aduser : Operator(s): The following: ”Eq’, ‘Ne” are the only operator(s) supported for searching on extended attribute: ‘Manager’.

I couldn’t work out a way of putting the $null value as part of the filter, but if you do – please share 🙂

 

@mickesunkan also wrote this github code showing a few differnet ways to do this search, and which way is most efficient. Thanks Micke!

 

 

 

Group Policy Preferences – Replace Existing File

I’ve written before on how great Group Policy Preferences are, and thought I’d write a quick ‘how to’ on a likely common scenario – replacing an older file with a new one, but only if it already exists.

Pushing out a file via Group Policy Preferences is quite easy and has been around for a long time.

When creating a new file rule, you’ll see 4 options under ‘Action’ – Create, Replace, Update and Delete:

gpp2

Create will only copy the file from the source to the destination if the file doesn’t exist at the destination
Replace will actually remove a file (if one exists), and copy the source to the destination regardless if a file existed or not
Update is the misleading one, it will modify the file attributes of the destination file to match the source – if the files themselves are different, it won’t copy them. If the file doesn’t exist, it will copy the file to the destination though!
Delete will delete the file(s) specified.

None of these provide a solution to ‘Replace file only if it exists’ though. There’s two obvious ways this can be achieved; you can use ‘Replace’ but this will continually replace the file every time Group Policy is run, which in the user context is every 90 minutes. You also can’t use the option ‘Apply once and do not reapply’ because it will run regardless of the file existing or not – which means if the file isn’t there before group policy runs, the file may be replaced by a software install or other mechanism, and with the order out of whack, resulting in the wrong file being left there in the end.

The next logical way to make sure the order is correct is to use Item Level Targeting. Under the ‘Common’ tab, you can tick the box for ‘Item Level Targeting’ and point to the file in question:

gpp3

This will only run once though, and that is regardless of the ‘Item Level Targeting’ being true or false. That only controls whether the policy does what it’s configured to do, at the client side it’s still ‘run’ the policy, it just had nothing to do.

thommck had the best answer on how to get around this that I’ve found – use a custom WMI query. You’ll need to remove the ‘Apply once and do not reapply’ tick, but the file itself will only be copied over when both targeting rules are true. Please read his post for all the details, but the second item will need to be a WMI query, and have a string similar to this:

SELECT LastModified FROM CIM_DataFile WHERE name=”C:\\windows\regedit.exe” AND LastModified < ‘20160701000000.000000+060’

This is checking the date of the file, and will only be ‘true’ if it’s less than that date.

Keep in mind that this is less than ideal, as WMI queries aren’t the most efficient way of processing group policy preferences, but it may be better than copying files around your network to every PC, every 90 minutes.

Azure AD Connect Health with AD DS

Azure AD Connect Health with AD DS is now in preview!

You’ll need Azure AD Premium for this, but it’s a little agent that gets installed on each of your domain controllers and provides health and alerting via Azure AD Connect Health.

The service is a light health and monitoring solution which reports back on some basics such as these:

azure health 3

Also, it will show any replication issues and other DC related problems for you to re-mediate. You can also configure email alerts, so you know when a problem is detected, rather than relying on checking the health page to notice something.

The setup of Azure AD Connect Health with AD DS is incredibly easy – download and install the agent (check you meet the prerequisites first!), use credentials of an Azure AD global administrator (set up a service account for this), and you’re done. If you install it on a server that doesn’t have the required Windows Server roles, you’ll get an error such as ” Microsoft.Identity.Health.Common.RoleNotFoundException: No role was registered.

The two other currently Health services are for ADFS and Azure AD Connect, so check those out too if you haven’t already.

One issue I had after installing was that I couldn’t see the box for Active Directory Domain Services in the Azure portal, it was just blank:


Pasted image at 2016_07_21 12_22 PM

After trying to work out why for a while, @kengoodwin pointed out that I should try resetting the view. This is done by clicking one of the ‘Add tiles’ options, then at the top of the screen choosing hte ‘Restore default’ option.

Doing this resulted in my tiles showing as they should – I’d never made adjustments to my tiles, but had previously gone into edit mode and saved the zero changes I did, which I believe stopped the portal from adding in the new tiles once the new health service was detected. This is how it should look:

ad health 2

Much better!

If you have Azure AD premium, then check out this free extra!

There’s Some Spam On Your Slacks

I’m a member of a few different Slack channels – they’re great for collaboration, helping others out and asking for assistance when you get stuck on something.

The biggest one is Windows Admins; winadmins.slack.com with over 1700 members (highly recommended if you’re a Windows Administrator).

An interesting event occured today, where an account called ‘jb’ joined, and immediately posted this:

 

Rather spammy in itself from where I sit, and a few others piped up being unimpressed with this action. ‘jb’ apologised and removed the post.

Doing this in a sysadmin channel however, is asking for a bit of further investigation. Putting aside the name itself (which along with the logo, looks like it should be a product for a completely different industry), it was a bit weird that ‘jb’ appeared to be doing marketing, but had also signed up with an email address which was admin@theirdomain – not something that a marketer would have access to.

I’ve censored the image as I don’t have permission to use it, and it’s not about them at all – but for context, it was a black and white face shot of a young, white female, with their title as ‘designer and inventor’

Slack for iOS Upload

A reverse google image search on the profile picture used revealed this:

person

…which turns out to be photos of people at a clothing launch in Berlin, and ‘jb’s’ photo was a cropped version of that. Now, it could be that this fashion industry person in Berlin is also the the person that runs this Japanese based tech company’s PR, AND has access to the admin email account for their domain.

Asking this mystery person what was going on was just met with silence, and then the account became inactive. What happened?? We may never know.

There’s a few take away points from all from this:

  1. Don’t steal a photo from the internet to use as your marketing tool, reverse Google images is good enough to find even part of a photo if it’s indexed.
  2. Don’t go into a sysadmin channel and spam your product; it won’t end with a positive experience from the people who generally have to stop spam.
  3. Slack communities should be treated as open available information – if an account gets approval, they could be scraping the conversations (and using for legitimate business purposes too)
  4. Don’t be fake when peddling your wares; people see through it.
  5. Spellcheck your automated messages; morarale isn’t a word.

Again, I don’t know how much of this applies to the company in question, draw your own conclusions. Maybe it was an elaborate test to see how the mood changed in the Slack channel?

Adaxes User Management Customisation

At the start of 2016, I reviewed a product called Softera Adaxes, which automates user management. I’m a big fan of it, and have been continually using it since (yes I’m a paying customer!).

The more we’ve used it, the more refined my rules have been. Sometimes they need to be adjusted to cover a scenario I didn’t consider (such as, a new starter with a hyphen in their last name, but not wanting the hyphen in the username). Other times it’s been a new requirement, and a re-think on how the rules need to be modified to cover new scenarios.

How Easy Was It To Change?

I’m happy to report that these changes have been quite easy to do. You need to be careful and think about changes before you do them. One trick for testing new user creations was to not send out email alerts if a certain field had the word ‘Test’ in it, which let me test the system live without other staff getting advised. Pretty simple, but effective:

adaxes1

Since using it, I’ve learnt through both trial and error, as well as Softerra support, several improvements on how to manage my rules based on my personal requirements. I thought it would be a good idea to share these tips which should help both new and existing users.

One quick one that Adaxes Support on their forums helped me with, was stopping a new user creation before it started, if the username already existed. A quick ‘Before User Creation’ business rule created with this script ensures the task will bomb out with a nice message, rather than potentially making changes on an existing user that were unwanted.

For the bigger picture on how I’d designed Adaxes for new users, I’d originally created a bunch of steps in the business rules for ‘After User Creation’. I had a big runsheet of many ‘ifs’ and ‘ands’ for a new user, but then had a thought; what if I want to re-enable a disabled user? None of these rules could be applied, because they’re against a new user. I don’t want to delete and re-create the account as that causes a lot of 3rd party app issues. Adaxes Support helped me on this one again, and suggested Custom Commands instead.

Now You’re Working With Modules

The idea was to make the whole design modular. Instead of having all the steps inside the ‘After User Creation’ business rule, move each step into it’s own custom command. From there, the custom commands can be called in order from the ‘After User Creation’ business rule. This reduced the Business Rule from 40 lines down to 9:

adaxes3

Of course that complexity was moved to the Custom Commands, but as each grouping (e.g. Enable Email) was it’s own command, it became much cleaner and easier to read as well as manage.

adaxes4

After chopping up all the rules this way, I created a dummy user. I was impressed that it worked perfectly first time! (side note – when you run something via the web interface, you’ll get back a very useful report on each step that ran and any errors. This is really helpful when troubleshooting.)

My next step will be to now create a ‘modify user’ rule that is for returning staff, and will call most of these modules. The ones that don’t fit for an existing account can just be replaced by a modified custom command for what I need.

Another basic point I worked out by going through this process, is that I should be more granular in where by business rules are pointing. Originally I pointed the ‘after a user is created’ business rule at my entire AD structure. After realising that I want a different process for contractor accounts, I narrowed down the rule to only point to the OUs that normal new users would be placed in, allowing for a different set of rules when a new user is created in the contractor’s OU.

Conclusion

One of the great things about all this, is that it’s easy to change your setup. There’s no re-writing from scratch – everything can be modified, or copy/pasted to where you want it to go.

I’m still really enjoying managing and using Softerra Adaxes, often with it sitting in the background for months while other staff use it for user management; with very little room for user error.

Softera sponsored the writing of this post.

Crane Game Toreba – I Won A Japanese Toy?

I’m still not sure what I think about this, but thought it was worth sharing:

I saw an advert online to install an app from the Play Store – ‘Crane Game Toreba; win real prizes!’. Out of interest due to a childhood of playing skilltesters, I wanted to check out what it was

logo_toreba_en

I’d been watching a few YouTube videos on arcade games, and the Japanese ones are a bit different to the ones I’m used to in Australia:

 

I installed the app; their main website is toreba.net with links to Android and iOS versions of the app. Weirdly, the app lets you pick a Japanese crane game with a particular prize, and play it. You get 3 shots for free with a new account, then need to start paying for turns.

I say weirdly, because this isn’t an animated game. It’s a real life crane that you control, with two webcam views. Via the internet, you’re remotely controlling an electronic and mechanical crane in Japan, trying to win a prize.

The prizes themselves are very Japanese, of which many I have no idea what they are. You can also win food, or sometimes both; such as a soft toy watermelon slice. Something we all need in our lives.

Here’s someone winning a ‘Grand Blue fantasy Byi stuffed’ with the crane, which again I’m not sure what it is….

I was suckered in after my 3 free shots and not winning, but decided to play a ‘ping pong’ game instead. This is where a ping pong ball is scooped up, and dropped into a second area. You win if the ball lands in a particular hole.

It took a few shots, but I won! They sent me a link of the replay of my win, which you can watch too.

The cost to play incudes free shipping worldwide, which means this thing should turn up on my doorstep in a few weeks:

9443f6b7cd8a0f81e4a354cbc6021aeb_1920_KR

I’m sure my son will have fun with it, being 17 months old. I don’t think I’ll play the game again either, but there’s something both interesting and strange about this whole setup. Remote controlling a silly game somewhere else in the world to try and win a prize seems both so right, and so wrong.

If nothing else, try the game for your free 3 shots. You don’t have to use a credit card, and it just seems to use your Play Store or Google Play account.

Oh, I also have an invitation code. I can’t work out what it does, and if either of us get something or not, so if someone could try we can both report back 🙂 My code is EHEHE9D4

 

 

Search Group Policy with PowerShell Script

I was looking for a certain Group Policy Preferences setting, where a registry value was being changed. Resultant Set Of Policy (RSOP) won’t help with these, and I couldn’t see a nice PowerShell command for searching through Group Policies.

I put the shoutout on Twitter to see who could help, and Tony Murray came back quickly with a script he’d created, and promptly uploaded to the Microsoft TechNet Gallery where I could download it.

It’s a reasonably simple script (which for me would have taken at least an hour to do beginning to end!) and is very easy to use.

Running the ps1 file will provide you with a prompt, asking what string you’re searching for. Enter the string, and it’ll give back all the Group Policy objects, along with if there was a match or not:

match

After seeing it work, I decided to make one slight change; I removed this section:

    else { 
        Write-Host "No match in: $($gpo.DisplayName)" 
    } # end else 

which results in the script only showing matches, and displaying no output otherwise. Handy if you have a long list of objects to look through!

Thanks again Tony for both writing this and sharing it!