Azure AD MyApps Portal

Introduction

Have you made the move to consolidating user access to a single sign-on (SSO) portal yet? If Active Directory is your primary source for user access, the Azure AD MyApps portal is a great place to start consolidating your access. For the sake of time I’m going to jump right into some ways to customize this portal, if you need more information on moving to SSO, take a quick read here.

Azure AD MyApps Portal

The new portal released general availability in 2020-Q1, it has a nice new feel and the Microsoft AzureAD Identity team has boasted a lot more features to come. To start, update to the new MyApps experience and try to create collections of apps. This could be a great way to group them together based on a security group for Client Success, Development, Sales, etc. I sure hope more features keep coming for it like Compact View, Pinned Apps, or a Frequently Used tab. You can go to their UserVoice page to submit new ideas or vote on current ones.

Clean up the portal

One big issue I’ve seen with Azure AD MyApps Portal is that it will start adding icons for apps you don’t want to see. For example, if you deploy an Outlook Add-In or oAuth for an app service it will now show for your users in their portal. When you click on it there will be an error or take you to a unexpected location. Well let’s clean that up! Here’s a few steps to do it:

  1. We’re going to take a look at this VidYard app – click the 3 stacked dots and then Copy link
  2. Now paste that link somewhere to inspect it. You will see a long string, you want the Enterprise App ID found after the name and before the Tenant ID. Use that ID to search for the app in Enterprise Apps in Azure AD.
  3. Now go to Properties and switch the Visible to users to No
  4. That’s it! Users can still authenticate to this app but won’t clutter up their MyApps portal. (I’ve seen it take about 10 minutes to be hidden)

Powershell process

So now that we went over the easy way to do it, let’s take a deeper dive into a way to do this in a bulk method. Also, if the app doesn’t show in your portal doesn’t mean it’s not showing for others. You can use the method for all apps in Azure AD. One disclaimer, some apps can not be hidden (specifically Microsoft apps). Microsoft has documentation on hiding applications here.

  1. First connect to Azure AD > then get all Service Principal Names
  2. Or if you want to search for a specific one use -SearchString zoom
  3. What you need is the ObjectID (you can also get this from the UI version of the portal for any Enterprise Application)
  4. Now use the last few lines to actually hide the app – a great example are the “App for Outlook” add-ins you can deploy to all users. There is no reason to have this show in the MyApps portal – clean that up for your users after you deploy it!
Connect-AzureAD
Get-AzureADServicePrincipal | Sort DisplayName 

ObjectId                             AppId                                DisplayName                       
--------                             -----                                -----------                       
01c9b439-a0c4-4e5b-a4c9-XXX123XXX456 f0ae4899-d877-4d3c-ae25-XXX123XXX456 AAD App Management                
0bd5a26c-8889-44b6-870a-XXX123XXX456 4e9b8b9a-1001-4017-8dd1-XXX123XXX456 Adobe Acrobat                     
20446487-87cf-4ddf-bed9-XXX123XXX456 00000013-0000-0000-c000-XXX123XXX456 Azure Classic Portal

Get-AzureADServicePrincipal -SearchString zoom

ObjectId                             AppId                                DisplayName     
--------                             -----                                -----------     
e3d65048-e393-48ff-9ac9-XXX123XXX456 fc108d3f-543d-4374-bbff-XXX123XXX456 Zoom            
1e5366dd-39d4-44ea-XXX123XXX456 d835d24c-a73d-44fe-af63-XXX123XXX456 Zoom            
eb61dc02-64e1-4b8a-XXX123XXX456 15151540-1838-48ac-bb91-XXX123XXX456 Zoom for Outlook 

$objectId = "eb61dc02-64e1-4b8a-XXX123XXX456"
$servicePrincipal = Get-AzureADServicePrincipal -ObjectId $objectId
$tags = $servicePrincipal.tags
$tags.Add("HideApp")
Set-AzureADServicePrincipal -ObjectId $objectId -Tags $tags

Conclusion

Keep your Azure AD MyApps portal cleaned up for your users before they go crazy with so many icons. It would be great if Microsoft would start adding new features to keep down on the clutter, but until then you can do your part. If you’re moving your users to the MyApps portal for all your SaaS apps, this is a must keep their sanity. Check out more features of Office 365 and Azure Active Directory with these links.

Schedule a Task to Cleanup a Log Folder

Introduction

Have you been alerted about a drive filling up over the weekend during your monthly patching schedule? What a bad moment to get a warning like this and have to deal with before the server locks up by Monday morning. Expanding a drive can be your first reaction, but after it fills up again a few months later you dive into it by analyzing disk space only to find it’s a pesky Log folder filling up for years now. Say no more, let’s schedule a task to cleanup a log folder!

How To Schedule a Task

Here is some light reading on using forfiles – a way to select and execute a command on a file or set of files. We are going to use it to clean up a folder on a Network Policy Server.

  1. Open Task Scheduler – Create a basic task
  2. Give it a Name and Description
  3. Trigger – how ever often you would like to clean it up
  4. Action – Start a program. These are the specific details I have used:
    Program/script: Forfiles.exe
    Add arguments: /p C:\Windows\System32\LogFiles\NPSLogs /m *.log /d -30 /c “Cmd.exe /c del @file”
    Start in: C:\Windows\System32
  5. Once complete Run Now to see if it works – backup the folder first!

Tips

Here are a few more thoughts to keep in mind:

  • If you are concerned about the data be sure to copy the entire log folder somewhere else while you test out this process.
  • Run the task as a local Admin account or a service account where the password won’t change. Otherwise the script will stop running after you change your password.
  • You can delete more than just log files, look above in the argument for the *.log parameter for file type. You can change this up to a different file type if your software uses a different kind.

Conclusion

Hope this helps you schedule a task to cleanup a log folder. I’ve found it’s better to be proactive about this, before you know it years have passed since you setup the server and you wished you would have taken the 15 minutes to have a scheduled task. See more posts about IT Operations here.

Remove all Office 365 licenses for a user

Introduction to Licensing

A common task for Microsoft Office 365 Administrators is to remove all Office 365 licenses for a user. There is no “one click” button in the Admin Center to do this. It’s also very time consuming if you have a list of users you need to do this for. I’m going to go over a few pre-requisites you will want to review, then show you a quick way to do this with PowerShell.

There are a few ways to connect to Office 365 from PowerShell, I’m going to use the Azure Active Directory Module. Let’s review what licenses you have access to, and also the services associated with each license.

#Connect
Connect-MsolService

#Get all licenses
Get-MsolAccountSku

#Get specific service details for a license
(Get-MsolAccountSku | where {$_.AccountSkuId -eq "litwareinc:ENTERPRISEPACK"}).ServiceStatus


Review User’s Current Licenses

#Create a CSV formatted file with the following in the first row:
userPrincipalName
user1@litwareinc.com
user2@litwareinc.com
user3@litwareinc.com

#Import the users and find out what they're licensed for
Import-Csv C:\Scripts\_Import_UPN.csv | %{get-msoluser -userprincipalname $_.userprincipalname } | FT DisplayName,*licenses* -AutoSize


Remove Licenses

So now that we have some information about our users let’s understand what will happen when a license is removed. Since Office 365 is a service related subscription when a license is removed they will lose access completely. Also as an Admin, or if another licensed user had access in some way will also be lost. The data will be complete removed after so many days Please review Microsoft’s documentation on Retention. You will want to backup the data before removing the license to ensure the data is not lost. When a license is removed the mailbox will be soft deleted for 30 days, then removed completely. For OneDrive, you can configure the maximum value up to 10 years so you have a little more time for cleanup. So for the fun part, here is a quick script to clean up all the licenses for a list of users:

#This requires a CSV of your user's as detailed previously
$csvFileLocation = "C:\Scripts\_Import_UPN.csv"
$users = Import-Csv -Path $csvFileLocation
foreach ($user in $users) {
$upn = $user.'UserPrincipalName'
(get-MsolUser -UserPrincipalName $upn).licenses.AccountSkuId |
foreach{
Set-MsolUserLicense -UserPrincipalName $upn -RemoveLicenses $_}}


There you have it, when you remove all licenses for a user it will really help keep things up to date. Now run the script to get all the user’s licenses again to review if they have been cleaned up. Hope this helps keeps your access cleaned up and costs down.

Archive Channels in Slack with Powershell

So my problem is that we’ve controlled the permissions in our account so only Admins can archive channels in Slack. Slack allows all users to create channels, great way to get things going but can get messy real QUICK. Our company has hundreds of abandoned channels and I needed a bulk method to archive them all. I haven’t worked with Slack’s API before but after about an hour with a developer at our company I could do some basics. Since I am most literate in PowerShell we set this up as a way to accomplish it. More details from Slack can be found at channels.archive

You can install the PowerShell module for the Slack API with this:

Install-Module PSSlack -Confirm:$False

Next up is then to setup all your variables, I’ll give a brief explanation of each:
$Token: Slack Legacy Tokens
$AllChannels: We’re going to get all channels that aren’t already archived
$InactiveChannels: Now were going to only get the channels where the Members are zero
$InactiveChannelsID: Finally we need to get the unique identifier for each channel called the ID

First let’s just get comfortable with getting all the channels so you can understand what you will archive. This will allow you to output how many channels, then also export all of the details to a CSV so you can review.

$Token = "xoxp-########-########-########-########"
$AllChannels = Get-SlackChannel -Token $Token -Paging -ExcludeArchived
$InactiveChannels = $AllChannels | Where-Object {$_.MemberCount -eq 0}
$InactiveChannels.count
$AllChannels | Where-Object {$_.MemberCount -eq 0} | Export-Csv C:\Scripts\Slack\InactiveChannels.csv -NoTypeInformation

Once you’re comfortable with all of these results and you are ready to take action on them use this to archive each of the channels with zero members. Archiving a channel can be reversed, you select any archived channel and make it active again.

$Token = "xoxp-########-########-########-########"
$AllChannels = Get-SlackChannel -Token $Token -Paging -ExcludeArchived
$InactiveChannels = $AllChannels | Where-Object {$_.MemberCount -eq 0}
$InactiveChannelsID = $InactiveChannels | Select -ExpandProperty ID

ForEach ($ID in $InactiveChannelsID) 
{
    $SlackURL = "https://slack.com/api/channels.archive?token=$Token&channel=$ID&pretty=1"
    Invoke-WebRequest -Uri $SlackURL -Headers @{"Authorization"="Bearer $Token"}
}

Let me know how it goes! There’s a ton you can do with Slack’s API so I’m just getting started. Hope this is a practical example of something that could be useful to you.