fredag 12. juli 2019

Keeping the system apps when enrolling corporate-owned Android devices in Intune

tl;dr

Add "android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED":true to your QR.

The full story

My current employer is trialing Intune as an organization-wide MDM solution. We already have M365 licenses for the entire organization, so Intune looks like an attractive option (we're already paying for the licenses anyway).

In addition to BYODs, we have tons of devices that are owned by the organization and meant strictly for business use. That means whatever MDM solution we end up using needs to be in complete control of the device, and for modern Android devices which support Android Enterprise, that seems to require the device owner mode of operation.

As of July 2019, Intune offers three ways to enroll Android devices:

Personal devices with work profile:
BYOD, the MDM controls a separate profile that contains work apps and data

Corporate-owned dedicated devices
The MDM controls the entire device, tailored towards kiosk and special-purpose devices

Corporate-owned, fully managed user devices (Preview)
The MDM controls the entire device, but the device still mainly functions as a regular user device

Both of the "corporate-owned" enrollment methods seem to use the device owner mode, and they both offer a handy QR code for easy enrollment. To start the QR-driven MDM wizard on most modern Android devices you simply tap a few times on a blank section of the first page of the device's out-of-the-box wizard.

I enrolled a couple of Samsung devices using the "Corporate-owned, fully managed" mode. The enrollment went without a hitch, but as I arrived at the start screen and looked through the app drawer, I noticed that several apps that I expect to see on an out-of-the-box Samsung device were conspicuously absent.

Admittedly, a lot of the software Samsung bundles with its phones is either pointless bloat no one ever asked for (Bixby), Samsung's version of something everyone else does better (Samsung Notes and Bixby) or straight-up evil (Facebook). Not a big deal if we accidentally happened to "lose" a few of those. The problem was that some of my enrolled devices were missing what I consider bare-minimum stock apps for a functional smartphone, like a camera app, an SMS/MMS app and a contacts app. Hmm.

Turns out that Android Enterprise in device owner mode disables or hides a lot of the OEM stock apps, although exactly which ones seems pretty random judging by my small sample of Samsung devices (most were missing the image gallery, some were missing the messages app, one had no camera, no gallery, no contacts and no messages).

There are certainly very good arguments for disabling some or all of the OEM stock apps in a business setting, but that's a separate discussion that I won't get into here. I just wanted to be able to leave the Samsung stock apps in place on a corporate-owned device, because at least in my organization's case there are a lot of devices where we'd want to do just that. Seems like a fairly basic MDM thing, so I'm sure Intune has a slider button for this, right? Right?

Well, it doesn't. At least I couldn't find one. I started googling and came across a few posts where people talked about running scripts with commands to enable specific stock apps, but I couldn't find a way to run Android scripts through Intune (at least not in a quick and easy way). This may be more because of my limited experience with and incomplete understanding of Intune than a limitation of the platform itself though.

Finally I found this post. "Just add this line to your QR, bro." After tons of fruitless research this seemed almost too good to be true, but how exactly do you go about adding that line of configuration to the enrollment QR code? Intune doesn't offer a way to customize it, so what do you do?

It's actually fairly easy. The enrollment QR code translates to a small chunk of JSON that tells your device which MDM system and tenant to enroll with, so if you use any kind of generic QR reader (app) on your Intune QR code, it should give you something that looks a little like this (formatting's gonna get mangled in the post so paste it into your favorite text editor or use this or something):


{

"android.app.extra.PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME":
"com.google.android.apps.work.clouddpc/.receivers.CloudDeviceAdminReceiver",

"android.app.extra.PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM":
"A1a2A3a4B5b6B7b8C9c0C1c2D3d4D5dEeEeFfFfGgGg",
    "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION":
"https://play.google.com/managed/downloadManagingApp?identifier=setup",

"android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE": { "com.google.android.apps.work.clouddpc.EXTRA_ENROLLMENT_TOKEN": "ABCDABCD" }



If you're familiar with JSON that's probably all you need to know. If not, what you have to do is add a comma and that single line of configuration before the closing curly bracket:


{

"android.app.extra.PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME":
"com.google.android.apps.work.clouddpc/.receivers.CloudDeviceAdminReceiver",

"android.app.extra.PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM":
"A1a2A3a4B5b6B7b8C9c0C1c2D3d4D5dEeEeFfFfGgGg",
    "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION":
"https://play.google.com/managed/downloadManagingApp?identifier=setup",

"android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE": { "com.google.android.apps.work.clouddpc.EXTRA_ENROLLMENT_TOKEN": "ABCDABCD" },

"android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED":true

}

Then stick that JSON in any random QR generator (online or otherwise) and use the resulting QR code to enroll your devices. Now Microsoft, could you please add that slider button? (Looks like it'll be here soon!)

onsdag 22. mai 2019

Changing the default admin password on a FortiExtender

We recently bought a couple of FortiExtenders at work, and I initially had a hard time figuring out how to set a password for the default admin account. Turns out the only way to do so is through the FortiExtender's web interface. The FortiExtender CLI has some superficial similarities to that of a FortiGate, but unlike on a FortiGate there is no way to set or change the admin password through the FortiExtender's CLI (at least not that I could find).

So Fortinet: please add at least at least a single sentence about this in your official documentation for the FortiExtender. I wasted a lot of time trying to figure this out.

mandag 25. februar 2019

Deleting the default "internal" virtual switch on factory-default entry-level FortiGates

Entry-level FortiGates usually have all the physical LAN interfaces wired into a single switch chip, and the factory-default configuration on these units defines a single virtual switch called "internal" which bridges all the LAN interfaces. The "internal" interface is then configured with a static IP address, a DHCP server and an IPv4 firewall policy which allows and applies source-NAT to all traffic coming in on the "internal" interface and going out the "wan" or "wan1" interface.

This configuration is fine for very simple deployments, but all of the smaller FortiGates that I've set up for my current employer have required splitting up the LAN interfaces into multiple virtual switches or multiple routed interfaces. The FortiGates won't let you delete a logical object in the configuration if that object is referenced anywhere else, so before you can delete the default virtual "internal" switch you need to delete the default IPv4 policy and the default DHCP server, since both of those reference the "internal" interface.

Below is a quick summary of the commands to do this through the CLI on a factory default. This will irreversibly delete all IPv4 firewall polices and DHCP server configuration, so obviously you wouldn't want to do this on a production device, only one with a factory-default configuration.

config firewall policy
purge

config system dhcp server
purge
 

config system virtual-switch
purge


Basically this enters the IPv4 policy configuration context and deletes everything, enters the DHCP server configuration context and deletes everything, and finally enters the virtual switch configuration context and deletes everything. Once again, do not do this on a production device.

fredag 10. august 2018

Catalyst 2960X stuck at "POST: Thermal, Fan Tests : Begin" during boot

I recently updated a couple of Catalyst 2960X switches at work, going from the previous Cisco-recommended IOS version to the current, 15.2.4E6(MD). Most of the switches updated just fine, but a 2960X-24TS-L failed to come back up after installing the new IOS image and reloading.

I tried power cycling the switch and watched the boot process in the console, where everything looked pretty normal until it got stuck on the thermal/fan test (POST: Thermal, Fan Tests : Begin). The SYST LED was flashing at this point and the switch's fan was at full speed. Time to google.

One post on Cisco's forums suggests power cycling the switch (which I had already tried), and another suggests checking out the solution for Cisco bug CSCtx90729. CSCtx90729 doesn't actually mention any switches from the 2960-X series in the list of affected devices though, so I had no way to know which image (if any) incorporated the fix for this bug. I picked 15.2.6E1 since it was the highest available IOS version, used a USB drive to copy it onto the switch alongside the 15.2.4E6 image and booted 15.2.6E1. The switch came up with zero issues, so I set the 15.2.4E6 image as the boot image, crossed my fingers and reloaded... and it worked.

I honestly have no idea if booting 15.2.6E1 actually fixed anything or if the switch just needed a bit more power cycling, but at least I didn't have to open up a TAC case and waste more time on the issue, so that's nice. I'm also really starting to appreciate the addition of USB ports on Catalyst switches. They're a fantastic way to quickly get an IOS image onto a switch if you're stuck in the bootloader.

lørdag 3. desember 2016

Unpin Edge with pure PowerShell, take two

Earlier this year I wrote a PowerShell script to unpin Microsoft Edge from the taskbar, since Microsoft didn't offer any official way to do so. Since then they have added a way to do it through Group Policy, but unfortunately this method seems a little half-baked. I stuck to using my script.

While the original script worked, it used a very stiff and fragile method to locate Edge in the taskbar registry key. If the Edge version number changed, the script would have to be updated. I've written a new version of the script which is intended to be less picky about new Edge versions. As a bonus, it comes with support for removing the Windows Store app right out of the box. If you don't want to unpin Windows Store you can just remove the entry from the hash table.

Note that changing the taskbar in this manner is not officially supported by Microsoft, and if something goes wrong it will likely end in all apps and applications being unpinned from the taskbar. Use the script at your own risk and make sure to thoroughly test it in your specific environment before using it in a production setting.

Here's the script:
Unpin Edge (and Windows Store)

The original version of the script can be found here, along with some more details on how it works.

fredag 17. juni 2016

Unpin Edge (and pin Internet Explorer) with pure PowerShell


The tl;dr
Here are the scripts, use at your own risk:

The first two scripts have some hopefully sensible comments, but I couldn't be bothered adding comments to the last one.

Update 2017-05-01
Added a link to the newer version of the script, which has been confirmed to work under Windows 10 version 1703 (Creators Update).

Update 2016-08-27
The script has been updated with the byte array for Edge on Windows 10 version 1607 (or Anniversary Update). Please note that the byte array was dumped on OS build 14393.82, since this was the newest available at the time. I had one computer that was running an older build of 1607, and I noticed that the byte array was different even if the Edge version number was the same as on the computers with build 14393.82.

If the script does not work for you it is probably because the Edge byte array on your particular flavor of Windows is different from the ones I have included in the script. To get around this you need to:

  1. Get the byte array for the app you want to remove
  2. Find the indexes of the "random" bytes in the array
  3. Add these two pieces of information to the UnpinApps.ps1 script
Get the byte array
This must be done once on two different computers (VM or physical doesn't matter). The computers need to be running the exact same edition of Windows and have the exact same updates installed. Copy the GetAppByteArray.ps1 script to each of the computers, unpin (yes, unpin) the app you're targeting from the taskbar, run the
GetAppByteArray.ps1 script, pin the app and finally click the script window and press a random button to unpause it. This will dump the byte array as a comma-separated list of decimals to a file called appByteArray.txt.

Do a quick visual comparison of the two byte arrays. If any of the first few bytes differ, you probably didn't get the arrays from similar enough computers.

Find the indexes of the "random" bytes in the array

Open CompareArrays.ps1 and paste in the two byte arrays so they end up in $array1 and $array2. Run the script and it will print out the index numbers of elements that differ between the two arrays. These are bytes that seem to be unique for every computer (or Windows installation at least), and must be skipped when the UnpinApps.ps1 script is looking for an app.

Add these two pieces of information to the UnpinApps.ps1 script
Open the UnpinApps.ps1 and create a new entry in the $apps array. Just copy one of the existing entries and clear out the values. One of the byte arrays that you got in the first step goes in "appByteArray" and the index numbers you found in the second step go in "bytesThatDontMatter". Save the script and it's ready for use.

Update 2016-08-05
As of Windows 10 version 1607, which was released to the general public a few days ago, Microsoft has added an officially supported method for pinning and unpinning apps (although you can still not unpin apps that users have pinned manually, only those that are pinned by default).

You can read more about this addition here: https://technet.microsoft.com/en-us/itpro/windows/manage/configure-windows-10-taskbar

Thanks to Robert Grohman for pointing this out in the comments!

Now that pinning and unpinning can be done through officially supported means, the scripts in this post are pretty much rendered unnecessary. I guess the exception would be for those who are stuck on older versions of Windows for the foreseeable future, and maybe if you want to force-remove specific user-pinned apps.


The why and how
We recently started rolling out Windows 10 at work, and one of the pain points that we’ve run into is Microsoft Edge. Not that there is anything wrong with Edge, it seems like a pretty alright web browser, but, well, it’s not Internet Explorer and it does not support addons/plugins. It’s also the default browser in a vanilla Windows 10 installation and it’s pinned to the taskbar. To top things off, the Edge icon is very similar to IE’s icon. If you’re reading this post I guess you already know why these things are problematic in an enterprise environment.

So, being the “group policy guy” in the IT department, I set out to find a way to unpin Edge. At this point I’d never had to deal with unpinning modern/universal Windows apps before, but it seemed like a pretty basic task. How hard could it possibly be?

Pretty hard it turned out, at least if you want to avoid messing up user-pinned apps and applications (which we do). Microsoft simply does not offer a straightforward way to unpin a single app with scripts or group policy. In earlier versions of Windows you could apparently get around this by programmatically “right-clicking” the program’s EXE and invoking one of the available actions from the pop-up menu, but as of Windows 10 that functionality has been removed by Microsoft.

Even if that functionality had still been there it wouldn’t have helped us any with the Edge issue, because with modern apps you can’t just right-click their EXE and pin them to the taskbar. There’s some more magic happening under the hood. At least that is the case with Edge.

Anyway, Windows stores the list of pinned apps and desktop applications in the registry key HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Taskband\Favorites. Regular desktop applications additionally have a shortcut added to %AppData%\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar, but since Edge is an app we don’t have to worry about deleting any shortcuts.

The Favorites registry key is of the type REG_BINARY and contains a binary blob representing the list of pinned taskbar items. That makes it a bit tricky to parse. You can view the hex and character representation of the registry key via the Windows Registry Editor, which shows that it contains at least some data that translates into meaningful ASCII characters.

PowerShell’s Get-ItemProperty Cmdlet allows you to dump and manipulate registry keys, by default as an array of bytes. After a bit of experimentation, I found that each pinned app or application adds a specific number of bytes to the taskbar registry key, and that the registry key is terminated by a single all-ones byte, or 255 in decimal.

The position of each app or application’s bytes in the registry key corresponds with the order of the items on the taskbar. Very simplified, you could say that if I have Edge, Firefox and Notepad pinned to the taskbar, in that order, the registry key contains EdgeFirefoxNotepadEND. If I move Firefox all the way to the left, the key changes to FirefoxEdgeNotepadEND, and if I finally unpin edge the key changes to FirefoxNotepadEND. You see where I’m going with this?
I wrote two basic PowerShell scripts. The first is used to find the byte array for a given app, and the second takes one or more of these byte arrays and removes them from the current taskbar registry key. Finally, it restarts explorer.exe to refresh the taskbar.

At this point I was all smiles, until I went to test the script on a different computer, running the exact same version of Windows with same updates installed. The script didn’t work. Much dismayed, I checked the length of the Edge byte arrays from both computers (they matched), and then converted them to their character representations. To the naked eye they looked the same, but there had to be some bytes in there that differed. I used PowerShell to step through the arrays and compare every single byte, writing out the index numbers if two bytes didn’t match.

The bytes at index 1227 through 1232 differed. I had a look at them in character representation, but they were either garbage or blanks. Testing on a third computer turned up the same results, bytes 1227 through 1232 were different from the two other computers. All right then, I guess we should just ignore those bytes when doing the array comparison.

Since we’re using the Current Branch for Business of Windows 10 at my workplace, we were still on build 10.0.10240-something-something at the time I made this script. This was reflected by Edge’s version number, and thus the byte array that needed to be removed. In an attempt to futureproof the script a little I also added two flavors of the Edge byte array from 10.0.10586 builds of Windows. In the end the script successfully removed Edge from all the computers I tested it on at work, as well as the few couple of 10.0.10586 computers that I have at home.

All right, we’re rid of Edge! That wasn’t so bad, was it? Now we just need to pin Internet Explorer. Surely this has to be officially supported by Microsoft? Nope. And as mentioned, the old “right-click”-workaround has been removed by Microsoft. Good grief, it’s like they hold a personal grudge against me.

So back to the drawing board. What I ended up doing was taking my existing PowerShell script to unpin Edge and modifying it a bit to check if IE was pinned, and if not, pin it. The script first checks if IE is pinned by looking for a small subset of the full IE byte array, a subset that I’m pretty sure will stay the same no matter what version of Windows you’re using. If it doesn’t locate that byte array subset, it creates a shortcut in the aforementioned taskbar shortcut directory and adds a known-to-work IE byte array to the taskbar registry key.

We’re currently testing these two scripts at work and everything looks promising so far. The scripts consistently unpin Edge and pin IE, and no one has had their taskbar broken yet. That doesn’t necessarily mean it’s safe for anyone to put these scripts into production, and it could also be that the byte array for Edge in your particular flavor of Windows differs from the ones I have included with the Edge script. In that case you’ll have to dump the Edge array yourself, figure out which bytes always stay the same and update the script accordingly. Don't blame me if the scripts set your dog on fire, though. You've been warned.

There are several different approaches you could take to getting Edge off the taskbar and replacing it with IE, but this was really the only solution I could find that did not involve any third-party software, could be easily deployed through group policy and would preserve any user-pinned apps. Suggestions for improvements and refinements of the scripts are very welcome, please leave a comment below.

søndag 13. mars 2016

Using someonewhocares.org/hosts to create a BIND domain blacklist

2016-06-17 update:
Switched to using uniq for duplicate removal. Uniq can do case-insensitive matching, sort can't.

Original post:
Some awesome guy named Dan Pollock (pollock@theorem.ca) maintains a list of advertising, malware, shock and otherwise potentially unwanted domains at someonewhocares.org/hosts. I've been using this list for years on most of my private computers, but one day I got tired of manually copying the list into my hosts files and decided to set up a more centralized solution in the form of a Linux box running BIND.

Now I'm not going to do a write-up on how to install BIND since it's readily available in the repositories of most Linux distros and there are already plenty of good tutorials on installing and configuring it. Instead, I will supply the Bash script that I use to convert the hosts file from someonewhocares.org into .zones and .db files for BIND to load.

The end result after you've run this script is that the BIND server will return 127.0.0.1 on lookups for any of the blacklisted domains. It's probably worth pointing out that I'm not mainly a Linux guy and that my Bash skills are not the greatest, so the script probably has a lot of room for improvement and doing things more elegantly. But hey, at least it works. Feel free to leave a comment if you have suggestions for improvements.

Oh, and please note that this script was written on a Raspberry Pi running Raspbian. If you're on a different flavor of Linux I guess it's possible that BIND's config files are in different locations or something else like the service name is different. Adjust the script accordingly.

Make sure that the user you're running the script as has sufficient rights to write to BIND's config directories and restart the BIND service.

If Blogger is messing up the formatting for you, try downloading a plaintext version from here: holmvikit.no/Personal/update-dns-blacklist.sh

##############################################################################
#!/bin/bash

# THE DOMAIN BLACKLIST USED BY THIS SCRIPT IS
# CREATED AND MAINTAINED BY DAN POLLOCK
# (pollock@theorem.ca), NOT BY THE CREATOR OF
# THIS SCRIPT
#
# For more details on Dan Pollock, please see
# http://someonewhocares.org/. For full credits
# on the domain blacklist, please go to
# http://someonewhocares.org/hosts/ and scroll
# down to the bottom of the page.

# For BIND to actually load the blacklisted domains
# you need to add include "/etc/bind/blacklisted.zones";
# to /etc/bind/named.conf.local

# What this script basically does is this:
# 1: Grab a fresh list of nasty domains from
#    someonewhocares.org (the 0.0.0.0 version)
# 2: (Optional) Skip the Windows10 section of
#     the list since it causes problems with
#     Windows Update
# 3: Pull the domain names only from the list
#    of unwanted domains, sort them and remove
#    duplicates
# 4: Create the necessary .zones and .db files
#    for BIND to load the blacklisted domains
#
# Once this is done, BIND will return 127.0.0.1 as
# the IP address for any blacklisted domain.

# Clean up old hosts file and BIND blacklist files
rm hosts
rm /etc/bind/blacklisted.zones
rm /etc/bind/blacklist/*

# Get the list of unwanted domains from someonewhocares.org
wget http://someonewhocares.org/hosts/zero/hosts

# Skip the Windows10 section, since as of 2016-03-13 it
# causes problems with Windows Update
#
# If you want to skip more than one section you should
# probably expand this part of the script so that it
# can take array of unwanted sections or load them from
# a file or something.
mapfile -t domains < hosts

cleanedDomains=""

for i in "${domains[@]}"
do
  if [ "$i" == "#<Windows10>" ]
  then
    skipUntil="#</Windows10>"
    echo "# Skipping section $i"
  fi
  if [ "$skipUntil" != "" ]
  then
    if [ "$i" == "$skipUntil" ]
    then
      skipUntil=""
      echo "# Done skipping section $i"
    fi
  else
    cleanedDomains+="$i\n"
  fi
done

echo -e $cleanedDomains > hosts
# End skip Windows10 section

# Grab the domain names only from lines starting with 0.0.0.0,
# sort them and remove duplicates.
domains=`grep -Po '(?<=0\.0\.0\.0 )(?:[-A-Za-z0-9]+\.)+[A-Za-z]{2,6}' hosts | sort | uniq -iu`

# Create an entry in blacklisted.zones and a db-file for each blacklisted domain
for domain in `echo $domains`;
do
  echo "zone \"$domain\" {type master; file \"/etc/bind/blacklist/$domain.db\";};" >> /etc/bind/blacklisted.zones
  dbline=""
  dbline+="\$TTL 3600\n"
  dbline+="@ IN SOA $domain. info.$domain. (2014052101 7200 120 2419200 3600)\n"
  dbline+="   NS      ns.$domain.\n"
  dbline+="   A       127.0.0.1\n"
  dbline+="*  A       127.0.0.1\n"
  echo -e $dbline >> /etc/bind/blacklist/$domain.db
done

# Remove the hosts file that we used to temporarily
# store blacklisted domains
rm hosts

# Restart the BIND service
service bind9 restart

##############################################################################