<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Hi, I'm Nicola 👋 on Nicola Suter</title><link>https://tech.nicolonsky.ch/</link><description>Recent content in Hi, I'm Nicola 👋 on Nicola Suter</description><generator>Hugo -- gohugo.io</generator><language>en-US</language><copyright>© 2026 Nicola Suter</copyright><lastBuildDate>Mon, 11 May 2026 06:00:03 +0000</lastBuildDate><atom:link href="https://tech.nicolonsky.ch/rss.xml" rel="self" type="application/rss+xml"/><item><title>Finally native SOAR in Sentinel?</title><link>https://tech.nicolonsky.ch/sentinel-native-soar/</link><pubDate>Mon, 11 May 2026 06:00:03 +0000</pubDate><guid>https://tech.nicolonsky.ch/sentinel-native-soar/</guid><description>&lt;p&gt;The Microsoft Sentinel SOAR playbook generator has mostly flown under the radar since it entered public preview, so let&amp;rsquo;s look at what it can do and whether it can replace Logic Apps with something more native.
In SecOps conversations, I often hear the same view: Logic Apps are fine, but if you already script or code, they can feel like overhead rather than a productivity boost. Many MSSPs also rely on more flexible tooling such as Azure Functions or compiled code for incident automation.&lt;/p&gt;
&lt;p&gt;The new Sentinel playbook generator feels more native for Defender XDR and Sentinel integration, and it adds AI on top. Let&amp;rsquo;s see whether that actually helps.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Playbook Generator in Action
 &lt;div id="playbook-generator-in-action" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#playbook-generator-in-action" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;You can find the playbook generator in the Unified Security Operations Platform (USOP) under the Sentinel automation blade, via the &amp;lsquo;Playbook Generator ✨&amp;rsquo; option.&lt;/p&gt;
&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Wizard"
 src="https://tech.nicolonsky.ch/content/images/2026/sentinel-soar/create-playbook.png"
 &gt;&lt;/figure&gt;
&lt;p&gt;It opens a Visual Studio Code or GitHub Codespaces-style editor with &lt;a href="https://cline.bot/" target="_blank" rel="noreferrer"&gt;Cline&lt;/a&gt; preinstalled for building Python playbooks.&lt;/p&gt;
&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Editor"
 src="https://tech.nicolonsky.ch/content/images/2026/sentinel-soar/editor.png"
 &gt;&lt;/figure&gt;
&lt;p&gt;Creating a playbook with natural language is straightforward. Cline uses a plan-and-act flow: you describe what you want, then it tests and builds the playbook.&lt;/p&gt;
&lt;p&gt;For my initial tests, I used the following prompt:&lt;/p&gt;</description></item><item><title>Don't let Entra ID Protection miss your next breach!</title><link>https://tech.nicolonsky.ch/entra-id-protection-stop-account-breach/</link><pubDate>Sun, 22 Mar 2026 10:00:03 +0000</pubDate><guid>https://tech.nicolonsky.ch/entra-id-protection-stop-account-breach/</guid><description>&lt;p&gt;All too often, my baseVISION (IR) colleagues and I find compromised cloud accounts where many security &amp;lsquo;signals&amp;rsquo; were missed—both from a prevention and detection perspective. In this blog post, I want to share some motivation and tips to help you adopt Entra ID Protection risk-based Conditional Access policies to increase your tenant&amp;rsquo;s security posture, and ensure you don&amp;rsquo;t miss the next obvious account breach.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Real-world motivation
 &lt;div id="real-world-motivation" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#real-world-motivation" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;Anyone who has seen an AiTM campaign in the wild will probably notice the following details from the Entra ID sign-in logs of a compromised account:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ResourceDisplayName: &lt;code&gt;OfficeHome&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;UserAgent: &lt;code&gt;axios/1.13.2&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Entra ID Protection - High - AiTM"
 src="https://tech.nicolonsky.ch/content/images/2026/eidp/id-protection-high.png"
 &gt;&lt;/figure&gt;
&lt;p&gt;The problem? Even though Entra ID Protection flagged the sign-in as &amp;lsquo;High&amp;rsquo; risk, the user could still sign in because MFA automatically remediated the sign-in risk (&lt;code&gt;userPassedMfaDrivenByRiskBasedPolicy&lt;/code&gt;).&lt;/p&gt;

&lt;h3 class="relative group"&gt;The bummer?
 &lt;div id="the-bummer" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#the-bummer" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Report Only ID Protection Policy"
 src="https://tech.nicolonsky.ch/content/images/2026/eidp/id-protection-report-only.png"
 &gt;&lt;/figure&gt;
&lt;p&gt;The environment had a Conditional Access policy in place that would have blocked users with high sign-in risk, but the policy was only in &lt;em&gt;report-only&lt;/em&gt; mode, so the user could sign in without any issues.&lt;/p&gt;</description></item><item><title>CEO impersonation with Microsoft Booking</title><link>https://tech.nicolonsky.ch/microsoft-booking-phish/</link><pubDate>Wed, 18 Mar 2026 20:00:03 +0000</pubDate><guid>https://tech.nicolonsky.ch/microsoft-booking-phish/</guid><description>&lt;p&gt;Recently I observed an interesting behavior after setting up a Microsoft Booking page. After creating the booking page, I suddenly got an e-mail to an automatically created mail alias with the same name as the booking page. This made me curious and I wanted to understand the behavior behind this, and if this could be abused by attackers to impersonate users in Exchange online. In this blog post, I want to share my findings and some tips on how to detect and prevent this kind of abuse in your environment.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Microsoft Booking
 &lt;div id="microsoft-booking" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#microsoft-booking" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;Microsoft describes the Bookings capabilities as part of Microsoft 365:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&amp;ldquo;A simpler way to organize schedules and manage appointments.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Microsoft Booking"
 src="https://tech.nicolonsky.ch/content/images/2026/bookingp/bookings-landing.png"
 &gt;&lt;/figure&gt;
&lt;p&gt;Booking pages can be either of type &amp;lsquo;personal&amp;rsquo; or &amp;lsquo;shared&amp;rsquo;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Personal booking pages provide a handy option for users to create their own booking page, which is automatically linked to their calendar and allows others to book appointments with them. This is a great feature for users who want to share their availability and allow others to easily schedule meetings.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The shared booking pages allow teams to provide a booking experience for services hosted by a team and come with a special mailbox and calendar.&lt;/p&gt;</description></item><item><title>Defender XDR Unified Detections Meet Sentinel Data Lake</title><link>https://tech.nicolonsky.ch/defender-xdr-unified-detections-sentinel-data-lake/</link><pubDate>Tue, 24 Feb 2026 22:00:03 +0000</pubDate><guid>https://tech.nicolonsky.ch/defender-xdr-unified-detections-sentinel-data-lake/</guid><description>&lt;p&gt;With the Unified Security Operations Platform (USOP), Microsoft introduces Unified Detections - a single detection framework spanning both Sentinel and Defender XDR data. Pair this with native Sentinel Data Lake ingestion for XDR tables, and you have a compelling cost-optimization story. But is it ready for prime time? Let&amp;rsquo;s dive into the capabilities, current limitations, and what it means for your detection strategy.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Architecture Overview
 &lt;div id="architecture-overview" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#architecture-overview" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;Previous Detection Architecture
 &lt;div id="previous-detection-architecture" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#previous-detection-architecture" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;In the &amp;lsquo;previous&amp;rsquo; architecture, detections were created and managed separately for Microsoft Sentinel and Microsoft Defender XDR. This often led to overhead in terms of &amp;lsquo;where to create the detection&amp;rsquo;. Let&amp;rsquo;s take the use-case of IoC (Indicators of Compromise) based detections. Previously, if a security team wanted to create a detection based on IoCs imported via TAXII into Sentinel and the &lt;code&gt;DeviceNetworkEvents&lt;/code&gt; table, they would need to ingest the &lt;code&gt;DeviceNetworkEvents&lt;/code&gt; data into Sentinel as well and create the detection rule there. Furthermore, many MSSPs leveraged this pattern to create custom detections for their customers across Defender Advanced Hunting Data.&lt;/p&gt;
&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Existing Detection Architecture"
 src="https://tech.nicolonsky.ch/content/images/2026/unifieddetections/arch_prev.png"
 &gt;&lt;/figure&gt;
&lt;p&gt;As part of the USOP onboarding, the following effects come into play, marked with an asterisk above:&lt;/p&gt;</description></item><item><title>AI just solved a CTF for me!</title><link>https://tech.nicolonsky.ch/ai-solved-ctf/</link><pubDate>Fri, 16 Jan 2026 21:00:03 +0000</pubDate><guid>https://tech.nicolonsky.ch/ai-solved-ctf/</guid><description>&lt;p&gt;At this year&amp;rsquo;s YellowHat conference in Almere, the Dutch security community had the chance to participate in a Capture The Flag (CTF) competition organized by one of the conference sponsors - &lt;a href="https://academy.bluraven.io/" target="_blank" rel="noreferrer"&gt;Blu Raven&lt;/a&gt;. Mehmet from Blu Raven did a great job setting up a CTF with realistic scenarios and datasets, which made it a lot of fun to solve the challenges.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Foreword
 &lt;div id="foreword" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#foreword" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;Being a big fan of CTFs and digital forensics and incident response (DFIR) in general, I couldn&amp;rsquo;t resist the temptation to participate. After numerous attempts to solve the first challenge and an enlightening tip from a colleague, I made some progress and solved the first 12 challenges.&lt;/p&gt;
&lt;p&gt;To avoid running out of time, I decided to try something unconventional for the remaining challenges - I used AI to help me solve them. Professor Smoke aka Henning Rauch teased the new Microsoft Fabric Real-Time Intelligence (RTI) capabilities during his talk at YellowHat&lt;sup&gt;1&lt;/sup&gt;, so I thought this would be a great opportunity to test these out in a real-world scenario. Little did I know that the outcome would be surprising!&lt;/p&gt;

&lt;h2 class="relative group"&gt;Preconditions
 &lt;div id="preconditions" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#preconditions" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;Azure Data Explorer
 &lt;div id="azure-data-explorer" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#azure-data-explorer" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;Because the CTF data was stored in an Azure Data Explorer (ADX) cluster, the prerequisite for using the Fabric RTI MCP server was already met, because we can query data in Eventhouse &lt;strong&gt;and ADX&lt;/strong&gt;.
Besides that I had already set up &lt;a href="https://learn.microsoft.com/en-us/visualstudio/ide/copilot-agent-mode?view=visualstudio" target="_blank" rel="noreferrer"&gt;GitHub Copilot within Visual Studio Code in agent mode&lt;/a&gt; from previous AI ramblings.&lt;/p&gt;</description></item><item><title>Did you hear that maester supports Intune?</title><link>https://tech.nicolonsky.ch/maester-tests-intune/</link><pubDate>Thu, 04 Dec 2025 20:00:07 +0000</pubDate><guid>https://tech.nicolonsky.ch/maester-tests-intune/</guid><description>&lt;p&gt;Did you know that the &lt;a href="https://maester.dev/" target="_blank" rel="noreferrer"&gt;maester&lt;/a&gt; framework now supports Microsoft Intune checks? In this blog post, I&amp;rsquo;ll give you a quick overview of the new capabilities and how to get started.&lt;/p&gt;

&lt;h2 class="relative group"&gt;About Maester
 &lt;div id="about-maester" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#about-maester" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;Maester is an open-source security assessment framework that helps you evaluate the security posture of your Microsoft Entra ID and Microsoft 365 environments. It provides a collection of tests that can be run against your tenant to identify potential misconfigurations and security risks.&lt;/p&gt;
&lt;p&gt;After executing the tests, maester generates a detailed report that highlights the findings and provides recommendations for remediation:&lt;/p&gt;
&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Maester Example"
 src="https://tech.nicolonsky.ch/content/images/2025/maester-demo.jpeg"
 &gt;&lt;/figure&gt;

&lt;h2 class="relative group"&gt;Intune Related Checks
 &lt;div id="intune-related-checks" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#intune-related-checks" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;The great thing about maester is that it&amp;rsquo;s highly extensible, allowing you to add custom tests and checks based on your specific requirements. To share some Intune best practices with the community, I contributed a set of Intune related checks to the maester framework.&lt;/p&gt;
&lt;p&gt;The following Intune checks are now available in maester:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;MT.1090 - Global administrator role should not be added as local administrator on the device during Microsoft Entra join&lt;/li&gt;
&lt;li&gt;MT.1091 - Registering user should not be added as local administrator on the device during Microsoft Entra join&lt;/li&gt;
&lt;li&gt;MT.1092 - Intune APNS certificate should be valid for more than 30 days&lt;/li&gt;
&lt;li&gt;MT.1093 - Apple Automated Device Enrollment Tokens should be valid for more than 30 days&lt;/li&gt;
&lt;li&gt;MT.1094 - Apple Volume Purchase Program Tokens should be valid for more than 30 days&lt;/li&gt;
&lt;li&gt;MT.1095 - Android Enterprise account connection should be healthy&lt;/li&gt;
&lt;li&gt;MT.1096 - Ensure at least one Intune Multi Admin Approval policy is configured&lt;/li&gt;
&lt;li&gt;MT.1097 - Ensure all Intune Certificate Connectors are healthy and running supported versions&lt;/li&gt;
&lt;li&gt;MT.1098 - Mobile Threat Defense Connectors should be healthy&lt;/li&gt;
&lt;li&gt;MT.1099 - Windows Diagnostic Data Processing should be enabled&lt;/li&gt;
&lt;li&gt;MT.1100 - Intune Diagnostic Settings should include Audit Logs&lt;/li&gt;
&lt;li&gt;MT.1101 - Default Branding Profile should be customized&lt;/li&gt;
&lt;li&gt;MT.1102 - Windows Feature Update Policy Settings should not reference end of support builds&lt;/li&gt;
&lt;li&gt;MT.1103 - Ensure Intune RBAC groups are protected by Restricted Management Administrative Units or Role Assignable groups&lt;/li&gt;
&lt;li&gt;MT.1105 - Ensure MDM Authority is set to Intune&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;Example
 &lt;div id="example" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#example" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;To run the tests you can simply run:&lt;/p&gt;</description></item><item><title>Mai 2024 KQL Café Recap</title><link>https://tech.nicolonsky.ch/mai-2024-kql-cafe-recap/</link><pubDate>Mon, 01 Jul 2024 20:07:46 +0000</pubDate><guid>https://tech.nicolonsky.ch/mai-2024-kql-cafe-recap/</guid><description>&lt;p&gt;In May I had the pleasure to be invited to the &lt;a href="https://kqlcafe.github.io/website/" target="_blank" rel="noreferrer"&gt;KQL Café&lt;/a&gt; which is hosted by &lt;a href="https://twitter.com/castello_johnny" target="_blank" rel="noreferrer"&gt;Gianni Castaldi&lt;/a&gt; &amp;amp; &lt;a href="https://twitter.com/alexverboon" target="_blank" rel="noreferrer"&gt;Alex Verboon&lt;/a&gt;. Within this format they empower people to work with KQL and share various tips and tricks. So this is not a usual blogpost but rather a summary and resource hub for the things I presented within the KQL Café.&lt;/p&gt;

&lt;h1 class="relative group"&gt;Summary
 &lt;div id="summary" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#summary" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h1&gt;
&lt;p&gt;To make the content of my talk more accessible, you can find a summary of the individual topics, including the leveraged KQL queries and further resources as part of this post. The KQL queries were mostly consuming the Entra ID Sign-In and Audit Logs. You can forward them to your Microsoft Sentinel or Log Analytics workspace.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Recording
 &lt;div id="recording" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#recording" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;You can find the full recording of the KQL Café on YoutTube.&lt;/p&gt;
&lt;iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/lKB1sfZuDio?si=HgXMFWTI21ypES3g" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen&gt;&lt;/iframe&gt;

&lt;h2 class="relative group"&gt;What the heck is ITDR?!
 &lt;div id="what-the-heck-isitdr" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#what-the-heck-isitdr" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;Identity Threat Detection and Response (ITDR) is currently one of my favourite topics. It’s basically a combination of the disciplines Identity and Access Management (IAM) and the cyber security disciplines detection and response. Similar to other cybersecurity topics there’s a rule of thumb: The more you invest on the preventive side to increase your identity security posture — the less effort you (hopefully) have on the detection and response side 🤞🤞. Within my talk for the KQL Café I addressed various of those ITDR topics that help you on the preventive side.&lt;/p&gt;</description></item><item><title>AiTM Phishing with Azure Functions</title><link>https://tech.nicolonsky.ch/aitm-phishing-with-azure-functions/</link><pubDate>Mon, 01 Apr 2024 18:23:49 +0000</pubDate><guid>https://tech.nicolonsky.ch/aitm-phishing-with-azure-functions/</guid><description>&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt=""
 src="https://cdn-images-1.medium.com/max/800/1*2rGHexNlD4iRO2hqP2zfAg.png"
 &gt;&lt;/figure&gt;
&lt;p&gt;Recently I stumbled over a nice &lt;a href="https://zolder.io/aitm-attacks-using-cloudflare-workers/" target="_blank" rel="noreferrer"&gt;post from Wesly Neelen&lt;/a&gt; who built an AiTM phishing toolkit based on a cloudflare worker. Although ‘prooven’ AitM phishing toolkits such as evilginx provide more capabilities in terms of flexibility and robustness I wanted to setup my own phishing toolkit that runs serverless on Azure — based on Azure Functions to phish some Entra ID credentials and cookies.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Advantages of serverless phishing toolkits
 &lt;div id="advantages-of-serverless-phishingtoolkits" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#advantages-of-serverless-phishingtoolkits" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;Serverless platform solutions such as Cloudflare workers, AWS lambda and Azure functions provide some advantages to phishing toolkits that are server-based:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;No Infrastructure as a Service (IaaS) resources like virtual machines and public IP addresses are required, this allows faster deployments, easier scaling and comes with low costs&lt;/li&gt;
&lt;li&gt;Serverless platforms often have pooled outbound IP addresses that are dynamically assigned by the cloud provider&lt;/li&gt;
&lt;li&gt;No DNS domain name or name server entries are required as the cloud provider assigns URLs to the serverless functions&lt;/li&gt;
&lt;li&gt;As the domain names, IP addresses and certificates are issued and managed by the cloud provider, this goes usually hand-in-hand with better reputation&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;Let’s do AiTM Phishing with Azure Functions
 &lt;div id="lets-do-aitm-phishing-with-azure-functions" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#lets-do-aitm-phishing-with-azure-functions" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;Demo
 &lt;div id="demo" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#demo" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;The following demo provides a quick overview about the Azure AiTM Function and the replay of the cookies in an incognito browser window:&lt;/p&gt;</description></item><item><title>Have you heard about passkeys and AAGuids?</title><link>https://tech.nicolonsky.ch/have-you-heard-about-passkeys-and-aaguids/</link><pubDate>Fri, 01 Dec 2023 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/have-you-heard-about-passkeys-and-aaguids/</guid><description>&lt;p&gt;With the availability of passkeys the FIDO2 standards become more accessible in the form of password managers, web-browsers and (mobile) operating systems — without the need for dedicated hardware such as FIDO2 keys.&lt;/p&gt;
&lt;p&gt;Microsoft is currently in the process of developing support for passkeys and shipping the public preview in Q1 2024:&lt;/p&gt;
&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt=""
 src="https://tech.nicolonsky.ch/content/images/1__pwNnOdcgBQPCEwZRTpGKNg.png"
 &gt;&lt;/figure&gt;
&lt;p&gt;While this is a very welcome addition to make passwordless authentication easily accessible without dedicated hardware such as FIDO2 security keys this also introduces new risks, especially for high value accounts — But why’s that?&lt;/p&gt;
&lt;p&gt;Let’s imagine a fictive scenario (that might become reality in the future) of a user registering a passkey with his password manager app for a Microsoft Entra account. The security of this passkey is now determined by the security measures on the password manager app.&lt;/p&gt;
&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt=""
 src="https://tech.nicolonsky.ch/content/images/0__7Mdx6OFRnIJ__wVbJ.jpg"
 &gt;&lt;/figure&gt;
&lt;p&gt;For the Microsoft roadmap this scenario is not (yet) applicable as Entra will only support device-bound passkeys. At the end of the day it is a similar situation as the security of the passkey depends on the device with the authenticator (passkey) on it and that’s not necessarily under the umbrella of IT security measures.&lt;/p&gt;
&lt;p&gt;Fortunately there is hope and the FIDO alliance included that critical aspect of distinguishing authenticators in their standards as we’ll find out below.&lt;/p&gt;</description></item><item><title>Enriching Microsoft Sentinel tables with eligible Entra directory roles</title><link>https://tech.nicolonsky.ch/enriching-microsoft-sentinel-tables-with-eligible-entra-directory-roles/</link><pubDate>Fri, 17 Nov 2023 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/enriching-microsoft-sentinel-tables-with-eligible-entra-directory-roles/</guid><description>&lt;p&gt;Microsoft 365 Defender and Sentinel provide an &lt;em&gt;IdentityInfo&lt;/em&gt; table that contains various information that is helpful for threat hunting and detections. One key piece are also the assigned Entra directory roles for a specific identity. Unfortunately only permanently assigned permissions are covered and in times of Entra Privileged Identity Management (PIM) we should have standing permissions only for non-privileged roles and break-glass accounts.&lt;/p&gt;
&lt;p&gt;Within this blog post I want to share a few tips and tricks to answer the following questions with Sentinel and a little bit of scripting and KQL:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How can we enrich the &lt;em&gt;IdentityInfo&lt;/em&gt; table to include eligible assigned directory roles?&lt;/li&gt;
&lt;li&gt;Which synchronized user accounts have permanent or eligible directory roles assigned? (Spoiler: this should be avoided at all cost)&lt;/li&gt;
&lt;li&gt;Were eligible directory role assignments not used within the last couple of days and can therefore be removed?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As a bonus I also prepared an analytics rule for mass unassignment of highly privileged Entra roles, as this tactic was used for example by the LAPSUS$ group.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Gathering PIM eligible Entra Directory Roles
 &lt;div id="gathering-pim-eligible-entra-directory-roles" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#gathering-pim-eligible-entra-directory-roles" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;As the &lt;em&gt;IdentityInfo&lt;/em&gt; and other available built-in data sources do not include eligible role assignments we need a way to gather the existing role assignments. Fortunately, we can query the following Microsoft Graph endpoint to get the eligible permission assignments:&lt;/p&gt;</description></item><item><title>Maintaining Microsoft Sentinel Analytic Rules in JSON and YAML with GitHub Actions</title><link>https://tech.nicolonsky.ch/maintaining-microsoft-sentinel-analytic-rules-in-json-and-yaml-with-github-actions/</link><pubDate>Mon, 13 Nov 2023 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/maintaining-microsoft-sentinel-analytic-rules-in-json-and-yaml-with-github-actions/</guid><description>&lt;p&gt;Microsoft Sentinel Analytic Rules can be shared in both the YAML and ARM format, whereas the ARM format leverages JSON as file type. Within…&lt;/p&gt;
&lt;p&gt;Microsoft Sentinel Analytic Rules can be shared in both the YAML and ARM format, whereas the ARM format leverages JSON as file type. Within this short post I want to demonstrate an approach that leverages a GitHub Action to automatically build and update the rules in YAML format — so you can just export and update existing rules without any manual conversion effort.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://twitter.com/fabian_bader" target="_blank" rel="noreferrer"&gt;Fabian Bader&lt;/a&gt; built a cool solution called &lt;a href="https://cloudbrothers.info/convert-sentinel-analytics-rules/" target="_blank" rel="noreferrer"&gt;SentinelARConverter&lt;/a&gt; that allows conversion of exported Sentinel Analctic rules from ARM/JSON to YAML (and vice-versa). To emphasize sharing of analytic rules I wanted to adopt also the YAML format without the need to always manually convert the rules. Therefore I incorporated his solution into a GitHub Action.&lt;/p&gt;
&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt=""
 src="https://tech.nicolonsky.ch/content/images/1__epyol1VOFkyQ9BI2j7__Agg.png"
 &gt;&lt;/figure&gt;

&lt;h3 class="relative group"&gt;Building a GitHub Action
 &lt;div id="building-a-githubaction" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#building-a-githubaction" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;The automation of this task is fairly simple if you are already familiar with GitHub actions. In case you want to directly see the full pipeline, you can find it &lt;a href="https://github.com/nicolonsky/ITDR/blob/main/.github/workflows/build-yaml-rules.yml" target="_blank" rel="noreferrer"&gt;here&lt;/a&gt;. Otherwise keep on reading.&lt;/p&gt;
&lt;p&gt;The GitHub action should be triggered as soon as I upload a new Export of an Analytics Rule to the repository. For that, we need to define a folder structure. I maintain the rules within a folder called &lt;code&gt;AnalyticRules&lt;/code&gt;. Based on that we can define the triggers for the workflow and filter only for the analytic rules path. This will only run the Action, when a file within that folder get’s changed. Additionally, I added a &lt;code&gt;workflow_dispatch&lt;/code&gt; trigger, this allows manual execution of the pipeline.&lt;/p&gt;</description></item><item><title>Have you heard of workload identity access token replay?</title><link>https://tech.nicolonsky.ch/have-you-heard-of-workload-identity-access-token-replay/</link><pubDate>Wed, 08 Nov 2023 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/have-you-heard-of-workload-identity-access-token-replay/</guid><description>&lt;p&gt;Microsoft recently made the Microsoft Graph Activity Logs available as part of the Microsoft Entra ID diagnostic settings. This means we can use the &lt;em&gt;MicrosoftGraphActivityLogs&lt;/em&gt; Table to enrich custom detections and analytic rules.&lt;/p&gt;
&lt;p&gt;Within this post I want to elaborate closer on an attack scenario for workload identities that leverage workload identity federation and don’t have any persistent credentials or long lived secrets. But one type of credential artefacts is still theft-able — the short lived access tokens.&lt;/p&gt;
&lt;p&gt;Adversaries can try to exfiltrate the access token from the CI/CD environment such as a GitHub action and replay the token within another system to access Entra ID protected resources.&lt;/p&gt;
&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt=""
 src="https://tech.nicolonsky.ch/content/images/1__iTbbTvAIBrAQsd2KErnBGg.png"
 &gt;&lt;/figure&gt;
&lt;p&gt;This tactic could also be used in scenarios with App Registrations that leverage certificates or clients secrets where adversaries don’t have access to the credentials but get possession of the access token due to exposure in cleartext such as in log files or decrypted TLS traffic.&lt;/p&gt;

&lt;h3 class="relative group"&gt;Stealing and replaying workload identity access tokens
 &lt;div id="stealing-and-replaying-workload-identity-accesstokens" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#stealing-and-replaying-workload-identity-accesstokens" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;To demonstrate a scenario to steal and replay an access token of a workload identity, I prepared a demo scenario with a GitHub action that acquires access tokens for the Microsoft Graph API and the Azure Resource Manager API. The pipeline leverages federated credentials (also referred to as workload identity federation).&lt;/p&gt;</description></item><item><title>Microsoft Entra Connect Sync Hardening</title><link>https://tech.nicolonsky.ch/entra-connect-hardening/</link><pubDate>Sun, 24 Sep 2023 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/entra-connect-hardening/</guid><description>&lt;p&gt;Microsoft Entra Connect Sync (aka Azure AD Connect) allows establishing hybrid identity scenarios by interconnecting on-premises Active Directory and Entra ID (aka Azure AD) and leveraging synchronisation features in both directions. As you might already know, this brings potential for abuse of the assigned permissions to the involved service accounts and permissions of this service.&lt;/p&gt;
&lt;p&gt;On the internet are already some posts with subset of this information but I wanted to provide an actionable post with individual measures to implement. Of course should we do MFA for all admins and AD tiering but some of those steps involve more complex measures to implement and I will try to provide some individual building blocks you can use to harden the configuration of your Entra Connect service accounts.&lt;/p&gt;

&lt;h3 class="relative group"&gt;Understanding the scope
 &lt;div id="understanding-thescope" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#understanding-thescope" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;To understand the scope of hardening we need to have an overview of the inner workings of that service. Entra Connect uses three different kind of service accounts for the different systems:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Entra: For the connected Entra tenant, per each Entra Connect installation a cloud only account is created by the wizard: &lt;em&gt;Sync_EIDC02_bba3d8efb72a@nicoladev.onmicrosoft.com&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Active Directory: The active directory account is used to connect a forest and allows both reading and depending on the leveraged synchronisation options also modifying the objects for password reset or group write-back scenarios&lt;/li&gt;
&lt;li&gt;Synchronisation Service: Under this principal, the actual Entra Connect service is running on the server&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each kind of service account has various interesting privileges that can be abused by attackers. While the security of the server running Entra connect is also an important aspect I want to focus more on the leveraged user accounts as they are subject to multiple well-known attack scenarios.&lt;/p&gt;</description></item><item><title>Why you should use Entra Workload Identity Federation</title><link>https://tech.nicolonsky.ch/why-you-should-use-entra-workload-identity-federation/</link><pubDate>Thu, 07 Sep 2023 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/why-you-should-use-entra-workload-identity-federation/</guid><description>&lt;p&gt;Microsoft Entra Workload Identity Federation is a hidden gem when dealing with app registrations and service principals because it will significantly improve the security posture of your workload identities. While I already blogged about the more technical and implementation specific details in my &lt;a href="https://nicolasuter.medium.com/github-action-with-azure-ad-workload-identity-federation-fb4e9d8bbf5c" target="_blank" rel="noreferrer"&gt;GitHub Actions with Entra Workload Identity Federation&lt;/a&gt; post, I want to highlight the benefits and scenarios where you can use Workload Identity Federation to access Entra ID protected resources.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Quick recap on Workload Identities
 &lt;div id="quick-recap-on-workload-identities" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#quick-recap-on-workload-identities" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;Should you read this post and wonder what a Workload Identity is, here a quick recap:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A workload identity (can be either a managed identity or service principal) is &lt;strong&gt;used to access resources protected by Entra ID&lt;/strong&gt; (Azure AD) from a service or automation&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;service principal is an instance&lt;/strong&gt; of an &lt;strong&gt;app registration&lt;/strong&gt;. To leverage a service principal authentication with either a client secret, certificate, or federated credential is required.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;managed identity&lt;/strong&gt; is a Microsoft managed identity of a resource such as a Logic App, Automation Account or VM. Microsoft manages the credentials of those managed identities. This allows for secure access as the credentials are not exposed to other services.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Managed Identity is the recommended type for workload identities for workloads that live in the Microsoft Azure ecosystem. For services and automations outside of Azure, service principals (app registrations) are the only option. The usage and credential configuration is unfortunately not a simple process.&lt;/p&gt;</description></item><item><title>Retrieving Windows LAPS Azure AD Passwords with PowerShell</title><link>https://tech.nicolonsky.ch/retrieving-windows-laps-azure-ad-passwords-with-powershell/</link><pubDate>Wed, 10 May 2023 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/retrieving-windows-laps-azure-ad-passwords-with-powershell/</guid><description>&lt;p&gt;Did you know that for the new Windows LAPS Azure AD is also maintaining the password history? The built in PowerShell commandlet relies on the Microsoft Graph PowerShell SDK and within this post I want to show you how to work with the &lt;code&gt;Get-LapsAADPassword&lt;/code&gt; cmdlet.&lt;/p&gt;
&lt;p&gt;Kudos to &lt;a href="https://medium.com/u/b214ce59ec84" target="_blank" rel="noreferrer"&gt;Niklas Tinner&lt;/a&gt; as he brought this to my attention while working together.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Where is this command originating from?
 &lt;div id="where-is-this-command-originating-from" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#where-is-this-command-originating-from" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;Get-LapsAADPassword&lt;/code&gt; cmdlet is part of the &lt;code&gt;LAPS&lt;/code&gt; PowerShell module that was baked into the Windows Operating system with the April 2023 quality updates.&lt;/p&gt;
&lt;p&gt;The module is maintained as part of the Operating System and builds the Interface to interact with Windows LAPS locally on a device. The module binaries reside within &lt;code&gt;C:\Windows\system32\WindowsPowerShell\v1.0\Modules\LAPS&lt;/code&gt; and consist of DLLs and PowerShell files:&lt;/p&gt;
&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt=""
 src="static/content/images/1__qcPzW4MPs441N6xsGkF2sA.png"
 &gt;&lt;/figure&gt;

&lt;h3 class="relative group"&gt;Let’s retrieve some passwords
 &lt;div id="lets-retrieve-some-passwords" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#lets-retrieve-some-passwords" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;Before we can start retrieving passwords we need to make sure, that we have the appropriate &lt;a href="https://github.com/microsoftgraph/msgraph-sdk-powershell" target="_blank" rel="noreferrer"&gt;Microsoft Graph PowerShell SDK&lt;/a&gt; module present.&lt;/p&gt;
&lt;p&gt;We can easily check this with the following PowerShell command:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;Get-Module&lt;/span&gt; &lt;span class="n"&gt;-Name&lt;/span&gt; &lt;span class="n"&gt;Microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Graph&lt;/span&gt; &lt;span class="n"&gt;-ListAvailable&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;If you do not retrieve any output, you need to install the module with local Administrator privileges with:&lt;/p&gt;</description></item><item><title>Let's have a tête-à-tête with the new Windows LAPS for Azure AD joined devices</title><link>https://tech.nicolonsky.ch/meeting-windows-laps/</link><pubDate>Fri, 21 Apr 2023 18:56:24 +0000</pubDate><guid>https://tech.nicolonsky.ch/meeting-windows-laps/</guid><description>&lt;p&gt;Loooooong awaited and it&amp;rsquo;s finally here - the new Windows LAPS. With the previous announcement(s) of the integration into the native Windows operating system and support for Azure AD join this was a long-awaited feature. With the recent patch Tuesday the binaries were backed and delivered natively into the current Windows client and Server OS and today they also launched the Azure AD backend that can serve as the backup source for passwords. Within this post, I want to give you a quick impression of what the deployment experience currently looks like and where I needed some adjustments to get the expected result.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Setup
 &lt;div id="setup" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#setup" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;Prerequisites
 &lt;div id="prerequisites" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#prerequisites" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;To deploy LAPS with Azure AD password backup and Intune you need licenses/access to those tools and Windows 10/11 devices with the latest April patches installed. A full list of prerequisites is provided &lt;a href="https://learn.microsoft.com/en-us/windows-server/identity/laps/laps-overview#windows-laps-supported-platforms-and-azure-ad-laps-preview-status" target="_blank" rel="noreferrer"&gt;by Microsoft here&lt;/a&gt;.&lt;/p&gt;

&lt;h3 class="relative group"&gt;Azure AD enablement
 &lt;div id="azure-ad-enablement" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#azure-ad-enablement" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;Unlike the on-premises AD LAPS enablement we do not need any schema extensions and can simply enable the following toggle within our Azure AD device settings:&lt;/p&gt;</description></item><item><title>Provoking Defender for Identity suspicious certificate usage alerts</title><link>https://tech.nicolonsky.ch/provoking-defender-for-identity-suspicious-certificate-usage-alerts/</link><pubDate>Tue, 11 Apr 2023 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/provoking-defender-for-identity-suspicious-certificate-usage-alerts/</guid><description>&lt;p&gt;Microsoft Defender for Identity (MDI) has announced a new capability back in February to detect suspicious certificate usage for Kerberos authentication. It is already well-known, that Active Directory Certificate Services (ADCS) is a lucrative target for adversaries to achieve persistence in Active Directory as ADCS can be easily misconfigured resulting in an easy way to exploit those misconfigurations. In this post I want to show you how easy those misconfigurations can be abused and how and when such an attempt is detected by Microsoft Defender for Identity new detection capabilities for suspicious certificate usage.&lt;/p&gt;

&lt;h2 class="relative group"&gt;What makes a vulnerable environment
 &lt;div id="what-makes-a-vulnerable-environment" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#what-makes-a-vulnerable-environment" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;To be vulnerable for the certificate abuse scenario I will demonstrate an environment needs to have the following conditions present:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ADCS Enterprise Certification Authority (CA)&lt;/li&gt;
&lt;li&gt;CA certificate must be present in NTAuth store (default behaviour when an enterprise ADCS CA is installed)&lt;/li&gt;
&lt;li&gt;At least one domain controller needs to have a kerberos authentication certificate enrolled&lt;/li&gt;
&lt;li&gt;At least one vulnerable certificate template that meets one of the following criteria&amp;rsquo;s:&lt;br&gt;
– “specify subject name in the request” flag enabled AND granting enroll permissions to low privileged principals like domain users or domain computers (or equivalent)&lt;br&gt;
– grants modify permissions to low privileged principals like domain users or computers (or equivalent)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The first three conditions are usually present in a standard Active Directory deployment and provide key functionality for other services. Certificate templates are also a standard thing, but there it really comes down to the (mis)configuration and hardening. Specterops documents those very well and provides tools to check for potential misconfigurations¹.&lt;/p&gt;</description></item><item><title>You must not touch my endpoint security settings!</title><link>https://tech.nicolonsky.ch/you-must-not-touch-my-endpoint-security-settings/</link><pubDate>Sun, 12 Mar 2023 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/you-must-not-touch-my-endpoint-security-settings/</guid><description>&lt;p&gt;Intune Endpoint Security Configuration Settings have become the way to go for configuring security features on various platforms. What did start with Microsoft Defender for Endpoint settings for Windows clients has evolved to settings for macOS, Windows Servers and is treated like a first class citizen. So it is important to guard those sensitive configurations as they control (and can potentially disable) vital security features on endpoints such as defender tamper protection, attack surface reduction rules, firewall and many more.&lt;/p&gt;
&lt;p&gt;Within this post I want to show you an approach to monitor changes to Intune Endpoint security settings with Microsoft Sentinel and watchlists that can be easily customised based on your environment and needs. My main idea is to classify the sensitive configurations in the environment and only creating incidents for those. Of course you could alert on every Intune configuration change but for most of the environments this would lead to many alerts without providing value.&lt;/p&gt;

&lt;h3 class="relative group"&gt;Prerequisites
 &lt;div id="prerequisites" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#prerequisites" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;Changes to the Intune Endpoint security settings area are visible like other changes within the Intune Audit Logs.&lt;/p&gt;
&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt=""
 src="https://tech.nicolonsky.ch/content/images/1__S01x0aIYMgr7n9fchKevyg.png"
 &gt;&lt;/figure&gt;
&lt;p&gt;To have the audit events within our Sentinel workspace we need to enable the forwarding for at least &lt;em&gt;AuditLogs&lt;/em&gt;. This can be done within the Intune Tenant Administration &amp;gt; Diagnostic Settings blade.&lt;/p&gt;</description></item><item><title>Optimising Microsoft Graph PowerShell scripts</title><link>https://tech.nicolonsky.ch/optimising-microsoft-graph-powershell-scripts/</link><pubDate>Wed, 22 Feb 2023 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/optimising-microsoft-graph-powershell-scripts/</guid><description>&lt;p&gt;We all have probably been there and developed a PowerShell script that took some fair amount of time until the execution completed, weren’t we? Of course one could argue and say that as long a script ‘works’ it is good enough but depending on the use case and environment a PowerShell script that runs 30 to 60 minutes exceeds the patience of most (IT) people and can also lead to increased costs. But what makes those kinds of scripts that awfully slow and can’t we just tweak them to run faster?&lt;/p&gt;
&lt;p&gt;The following examples and script will be related to PowerShell and the Microsoft Graph API but the mentioned approaches can be adapted for any kind of RESTful API and scripting language. For all interactions with the Graph API I use the &lt;a href="https://github.com/microsoftgraph/msgraph-sdk-powershell" target="_blank" rel="noreferrer"&gt;Microsoft Graph PowerShell SDK&lt;/a&gt; which is available as a PowerShell module from the PowerShell gallery.&lt;/p&gt;

&lt;h3 class="relative group"&gt;Reasons why your script is slow
 &lt;div id="reasons-why-your-script-isslow" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#reasons-why-your-script-isslow" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;I would say I have already read and (tried to) understand hundreds of PowerShell scripts out there and I often notice the following flaws which lead to poor performance:&lt;/p&gt;

&lt;h4 class="relative group"&gt;&lt;strong&gt;Slow algorithms and wrong data structures&lt;/strong&gt;
 &lt;div id="slow-algorithms-and-wrong-data-structures" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#slow-algorithms-and-wrong-data-structures" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h4&gt;
&lt;p&gt;Slow algorithms are extricably linked to the understanding of data structures when it comes to PowerShell scripting. Here the top two cases I often observe:&lt;/p&gt;</description></item><item><title>Migrating to the new Windows Store experience</title><link>https://tech.nicolonsky.ch/migrating-to-the-new-windows-store-experience/</link><pubDate>Mon, 30 Jan 2023 18:56:24 +0000</pubDate><guid>https://tech.nicolonsky.ch/migrating-to-the-new-windows-store-experience/</guid><description>&lt;p&gt;The Microsoft Store for Business will be discontinued mid 2023 and Intune recently introduced the new Windows Store experience backed by winget to distribute apps to your Intune managed endpoints.&lt;/p&gt;
&lt;p&gt;To simplify the migration to the new Windows Store experience I created a PowerShell Script that migrates all currently assigned Windows Store for Business apps to the new Windows Store experience.&lt;/p&gt;
&lt;p&gt;Kudos to &lt;a href="https://www.rozemuller.com/add-microsoft-store-app-with-icon-into-intune-automated/" target="_blank" rel="noreferrer"&gt;Sander Rozemuller&lt;/a&gt; for providing detailed instructions about creating winget apps as PowerShell code samples.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Challenges
 &lt;div id="challenges" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#challenges" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;While scripting and extracting the existing Windows Store for Business (WSfB) apps I encountered the following issues:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Not all apps in WSfB have valid privacy and information URLs, therefore I added a check whether the URL starts with http(s).&lt;/li&gt;
&lt;li&gt;Some apps have characters present (äöüë….) that require UTF-8 encoding. So I explicitly set the HTTP &lt;em&gt;content-type&lt;/em&gt; header to UTF8.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;Script prerequisites
 &lt;div id="script-prerequisites" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#script-prerequisites" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;To run the script you need to have the Microsoft Graph PowerShell SDK modules installed on your machine. You can install them with the following command:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;Install-Module&lt;/span&gt; &lt;span class="n"&gt;Microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Authentication&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Devices&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;CorporateManagement&lt;/span&gt; &lt;span class="n"&gt;-Scope&lt;/span&gt; &lt;span class="n"&gt;CurrentUser&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;From a permissions perspective you need an Azure AD Application Administrator for the initial OAuth permission consent and for regular execution the Intune Administrator role.&lt;/p&gt;</description></item><item><title>GitHub Actions with Entra Workload Identity Federation</title><link>https://tech.nicolonsky.ch/github-actions-entra-workload-identity-federation/</link><pubDate>Mon, 23 Jan 2023 17:03:47 +0000</pubDate><guid>https://tech.nicolonsky.ch/github-actions-entra-workload-identity-federation/</guid><description>&lt;p&gt;Workload Identity Federation (let’s just call this WIF) allows app principals not residing within Azure to request short lived access tokens. This removes the need of storing client secrets or certificates within GitHub as Action secrets. One drawback ist that currently only the Azure modules support the usage of WIF.&lt;/p&gt;

&lt;h2 class="relative group"&gt;How it works
 &lt;div id="how-itworks" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#how-itworks" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;WIF relies on trust. This trust is directly configured on the Azure AD app registration and scoped to an individual GitHub repository and optionally fine grained by limiting the usage to single git refs, specifically branches and tags. By trusting GitHub as external identity provider (IdP), a GitHub Action can request an identity token from the GitHub IdP and exchange this one against an access token within Azure AD.&lt;/p&gt;
&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Entra Workload Identity Federation"
 src="https://cdn-images-1.medium.com/max/800/1*r7XrBMrGtQ1M-Kd0biGjVA.png"
 &gt;&lt;/figure&gt;
&lt;p&gt;A GitHub IdP issued token (decoded) contains the following information:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;jti&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;1a9fe224-c936-46f6-a38b-3300e76251b0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;sub&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;repo:nicolonsky/musical-octo-telegram:ref:refs/heads/main&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;aud&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;api://AzureADTokenExchange&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;ref&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;refs/heads/main&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;sha&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;9f112c0b82547e35b10250d7f3165789bf97862f&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;repository&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;nicolonsky/musical-octo-telegram&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;repository_owner&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;nicolonsky&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;repository_owner_id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;32899754&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;run_id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;3986560796&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;run_number&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;run_attempt&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;2&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;repository_visibility&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;private&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;repository_id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;592303002&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;actor_id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;32899754&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;actor&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;nicolonsky&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;workflow&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;.github/workflows/wif.yaml&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;head_ref&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;base_ref&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;event_name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;push&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;ref_type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;branch&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;workflow_ref&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;nicolonsky/musical-octo-telegram/.github/workflows/wif.yaml@refs/heads/main&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;workflow_sha&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;9f112c0b82547e35b10250d7f3165789bf97862f&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;job_workflow_ref&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;nicolonsky/musical-octo-telegram/.github/workflows/wif.yaml@refs/heads/main&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;job_workflow_sha&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;9f112c0b82547e35b10250d7f3165789bf97862f&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;iss&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://token.actions.githubusercontent.com&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;nbf&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1674486850&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;exp&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1674487750&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;iat&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1674487450&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Did you recognize the matching &lt;code&gt;sub&lt;/code&gt; attribute within the GitHub issued token and the Azure AD configuration? For a successful authentication the:&lt;/p&gt;</description></item><item><title>Inside Windows package manager (winget)</title><link>https://tech.nicolonsky.ch/inside-windows-package-manager/</link><pubDate>Fri, 30 Dec 2022 23:11:03 +0000</pubDate><guid>https://tech.nicolonsky.ch/inside-windows-package-manager/</guid><description>&lt;p&gt;Windows Package Manager (winget) provides exciting features to install and upgrade apps on Windows devices. But how does winget actually work and how are new packages integrated? Within this post I want to elaborate on some questions I had when having a closer look into winget.&lt;/p&gt;

&lt;h4 class="relative group"&gt;How does winget find sources?
 &lt;div id="how-does-winget-findsources" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#how-does-winget-findsources" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h4&gt;
&lt;p&gt;By default, winget has the following sources configured:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;msstore: Microsoft Store (public)&lt;/li&gt;
&lt;li&gt;winget: Winget Content Delivery Network (CDN)&lt;/li&gt;
&lt;/ol&gt;
&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt=""
 src="https://cdn-images-1.medium.com/max/800/1*A7BC1sZg0P8h43LvLkvIpw.png"
 &gt;&lt;/figure&gt;
&lt;p&gt;When searching for a particular package, e.g: &lt;code&gt;winget search wireshark&lt;/code&gt; all configured sources are searched for a match.&lt;/p&gt;
&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt=""
 src="https://cdn-images-1.medium.com/max/800/1*Kck4GHmNrkEWRLfkASY39g.png"
 &gt;&lt;/figure&gt;
&lt;p&gt;lesson learned: winget can install packages from the public Microsoft store and the winget CDN.&lt;/p&gt;

&lt;h4 class="relative group"&gt;How are winget CDN packages provided?
 &lt;div id="how-are-winget-cdn-packages-provided" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#how-are-winget-cdn-packages-provided" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h4&gt;
&lt;p&gt;Winget CDN packages reside within a public git repository hosted on &lt;a href="https://github.com/microsoft/winget-pkgs" target="_blank" rel="noreferrer"&gt;GitHub&lt;/a&gt;. The repository contains an alphabetic folder structure by vendor and product name holding manifests in YAML format that describe the app details.&lt;/p&gt;
&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt=""
 src="https://cdn-images-1.medium.com/max/800/1*UY1wLURvUmrb-FKFa-Uapw.png"
 &gt;&lt;/figure&gt;
&lt;p&gt;The &lt;code&gt;manifests&lt;/code&gt; folder within the repo is grouped by the app vendor and app name and YAML contents of a manifest look like this:&lt;/p&gt;</description></item><item><title>Setting up a radius server for Azure AD joined devices and 802.1x</title><link>https://tech.nicolonsky.ch/radius-aad-joined-devices/</link><pubDate>Sun, 25 Sep 2022 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/radius-aad-joined-devices/</guid><description>&lt;p&gt;A common pitfall in environments where Windows server is used for radius authentication is that Microsoft network policy server (NPS) does currently not support device based authentication for Azure AD joined devices. NPS always checks for the existence of a corresponding computer object in AD. For my home setup and lab I wanted to build a radius solution to enable 802.1x authentication on my Wi-Fi network.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Disclaimer
 &lt;div id="disclaimer" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#disclaimer" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;This post describes my setup and does not cover prerequisites like certification authority, certificate revocation and client certificate deployment via SCEP. Furthermore you should be familiar with docker, network topics, dns and Intune.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Available solutions
 &lt;div id="available-solutions" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#available-solutions" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;Well known commercial Network Access Control (NAC) solutions like CISCO ISE or Aruba Clearpass often ship with an integrated RADIUS server and the possibility to configure wheter LDAP lookups for computer accounts should happen. Important is, that the solution supports certificate revocation checks either via CRLs or OCSP to ensure network access is blocked when a client certificate is revoked.&lt;/p&gt;
&lt;p&gt;For my home and lab setup I wanted to leverage a free or open source solution and decided to use freeRADIUS, probably the most popular open source radius server. freeRADIUS supports EAP-TLS for 802.1x authentication out of the box and is well documented.
Additionally, I was looking for a solution that can be deployed to both locallly in my network (e.g. on a raspberry pi) and also to PaaS offerings like Azure.&lt;/p&gt;</description></item><item><title>Android dedicated devices managed home screen and system apps</title><link>https://tech.nicolonsky.ch/android-kiosk-system-apps/</link><pubDate>Tue, 20 Sep 2022 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/android-kiosk-system-apps/</guid><description>&lt;p&gt;Android enterprise dedicated devices with the Microsoft Managed Homescreen app are a conenient way to provide devices with restricted functionality and customized look and feel to end users. Because the Managed Homescreen app acts as an overlay to the underlying Android certain prompts and features are not enabled by default unless you allow-list them by deploying the corresponding Android System App and add the app to the kiosk device restrictions.&lt;/p&gt;

&lt;h2 class="relative group"&gt;System Apps
 &lt;div id="system-apps" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#system-apps" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;System apps can be added as separate app type within MEM:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://tech.nicolonsky.ch/content/images/2022/08/MEM-Android-System-Apps.png" &gt;&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="System Apps"
 src="https://tech.nicolonsky.ch/content/images/2022/08/MEM-Android-System-Apps.png"
 &gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It is important to deploy the desired system apps as required to your devices and also adding them within the kiosk configuration:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://tech.nicolonsky.ch/content/images/2022/09/mem-kiosk-apps-android.png" &gt;&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Kiosk config"
 src="https://tech.nicolonsky.ch/content/images/2022/09/mem-kiosk-apps-android.png"
 &gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;h2 class="relative group"&gt;List of commonly used System apps for Samsung devices
 &lt;div id="list-of-commonly-used-system-apps-for-samsung-devices" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#list-of-commonly-used-system-apps-for-samsung-devices" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;Based on a recent project where we had Samsung devices in place we allow-listed the following system apps within the kiosk configuration:&lt;/p&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Description&lt;/th&gt;
 &lt;th&gt;App Bundle ID&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;USB File Transfer Prompt Android Version &amp;lt; 12&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;com.samsung.android.MtpApplication&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;USB File Transfer Prompt Android Version &amp;gt;= 12&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;com.android.mtp&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Android System UI (used for a variety of prompts)&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;com.android.systemui&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Service Mode App (USB prompts)&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;com.sec.android.app.servicemodeapp&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Knox license prompts&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;com.samsung.android.knox.pushmanager&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Samsung Android update prompts&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;com.wssyncmldm&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Knox smdms&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;com.sec.enterprise.knox.cloudmdm.smdms&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Knox container core&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;com.samsung.android.knox.containercore&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Knox attestation&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;com.sec.enterprise.knox.attestation&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;Keyboard changes&lt;/td&gt;
 &lt;td&gt;&lt;code&gt;com.samsung.android.honeyboard&lt;/code&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;An indicator to decide wheter you need to add an app to the list is always when you can see the prompts outside of the managed homescreen app after leaving the kiosk mode.
{: .notice&amp;ndash;info}&lt;/p&gt;</description></item><item><title>The easiest way to work with the Microsoft Graph PowerShell SDK</title><link>https://tech.nicolonsky.ch/graph-powershell-sdk-kickstart/</link><pubDate>Fri, 09 Sep 2022 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/graph-powershell-sdk-kickstart/</guid><description>&lt;p&gt;When you are new to RESTful APIs and want to start with Microsoft Graph to automate tasks in your Endpoint Manager tenant all the stuff about app registrations, access tokens, pagination and request headers can be quite confusing. In this post I want to show you a quick tip to kickstart your Microsoft Graph API experience.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Requirements
 &lt;div id="requirements" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#requirements" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Cloud admin account with Intune Administrator role assigned&lt;/li&gt;
&lt;li&gt;Ability to install Modules from the PowerShell gallery&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;JWT
 &lt;div id="jwt" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#jwt" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;Just because you can&amp;rsquo;t see it&amp;hellip; doesn&amp;rsquo;t mean it isn&amp;rsquo;t there: Due to the naturality of OAuth 2.0 and OpenID connect (these are the protocols involved for authorization and authentication in a cloud environment) we can capture short lived access tokens, also called Json Web Tokens (JWTs) directly from a browser. Tokens are usually valid between 50 and 60 minutes - just what we need to get some hands on with Microsoft Graph API and MEM automation.&lt;/p&gt;
&lt;p&gt;The cool thing is actually that we don&amp;rsquo;t need any kind of app registration or additional permissions which can be quite some blocker in certain restricted environments (or staff unfamiliar with those technologies 😉).&lt;/p&gt;</description></item><item><title>Intune app protection policy report</title><link>https://tech.nicolonsky.ch/app-protection-policy-report/</link><pubDate>Mon, 13 Dec 2021 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/app-protection-policy-report/</guid><description>&lt;p&gt;App protection (also called MAM) policies have been around for a couple of years within MEM and I already used them in various projects to protect company data on unmanaged iOS and Android devices. One of the drawbacks with this approach is that we do not have full visibility about the usage and I tried to shed some light about this with a PowerShel reporting script that pulls data from the Microsoft Graph API.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Information visible within the portal
 &lt;div id="information-visible-within-the-portal" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#information-visible-within-the-portal" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;In the MEM portal we can find report data about the number of users that have checked-in to any MAM policy grouped by the respective app.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://tech.nicolonsky.ch/content/images/2021/12/Intune_MAM_Report_Portal_View.png" &gt;&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Intune MAM insights"
 src="https://tech.nicolonsky.ch/content/images/2021/12/Intune_MAM_Report_Portal_View.png"
 &gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If we want to perform a wipe we will also be able to see the devices a user has registered:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://tech.nicolonsky.ch/content/images/2021/12/Intune_MAM_Report_Wipe_Request.png" &gt;&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="MAM wipe"
 src="https://tech.nicolonsky.ch/content/images/2021/12/Intune_MAM_Report_Wipe_Request.png"
 &gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Of course I was curious which additional data is available on the Microsoft Graph API and found the following resource storing app protection policy check in details: &lt;code&gt;/users/{ID}/managedAppRegistrations&lt;/code&gt;.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Script
 &lt;div id="script" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#script" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;The script uses the &lt;code&gt;Intune PowerShell SDK&lt;/code&gt; (could easily be ported to MSAL.PS because I wrote it already a couple of months ago) to enumerate all internal users within the tenant and will check the above mentioned &lt;code&gt;managedAppRegistrations&lt;/code&gt; resource.
At the end you are presented a flattened CSV report containig the following details:&lt;/p&gt;</description></item><item><title>Have you considered TPM key attestation?</title><link>https://tech.nicolonsky.ch/adcs-tpm-key-attestation/</link><pubDate>Sat, 28 Aug 2021 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/adcs-tpm-key-attestation/</guid><description>&lt;p&gt;Device and user-based certificates are commonly used for secure authentication for services like: MECM in HTTPS mode, Always On VPN, 802.1x for (wireless) LAN and so on. Mostly these certificates are deployed from an internal PKI and the certificate templates are somewhat outdated because everybody is afraid of touching these settings. As with any type of credentials - credential theft is also applicable for certificates and the corresponding private keys. So let&amp;rsquo;s dive in and learn the risk and how to reduce the attack surface.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Understanding cryptography providers
 &lt;div id="understanding-cryptography-providers" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#understanding-cryptography-providers" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;Before we start with the actual theft we need to know how certificates and the corresponding private keys are stored on Windows devices. Microsoft operating systems implement various cryptographic providers which can be either software or hardware based. The two most important ones are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Microsoft Software Key Storage Provider
&lt;ul&gt;
&lt;li&gt;&amp;ldquo;Standard&amp;rdquo; provider which stores keys software based and supports CNG (Crypto-Next Generation)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Microsoft Platform Crypto Provider
&lt;ul&gt;
&lt;li&gt;Hardware based which stores keys on a TPM (trusted platform module) and supports CNG as well&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When a client is requesting a new certificate from a CA he generates a key pair consisting of a private and public key with such a crpytographic provider.&lt;/p&gt;</description></item><item><title>Automatically sign your PowerShell scripts with GitHub actions</title><link>https://tech.nicolonsky.ch/github-actions-powershell-signing/</link><pubDate>Fri, 09 Jul 2021 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/github-actions-powershell-signing/</guid><description>&lt;p&gt;Based on one of my older posts about &lt;a href="https://tech.nicolonsky.ch/sign-powershell-az-devops" &gt;PowerShell script signing with Azure DevOps&lt;/a&gt; I recently implemented a PowerShell script signing workflow with GitHub actions I wanted to share with the community.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Prerequisites
 &lt;div id="prerequisites" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#prerequisites" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;For this post the following prerequisites are required:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Code signing certificate in PFX format&lt;/li&gt;
&lt;li&gt;GitHub account&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;Add variables to GitHub actions
 &lt;div id="add-variables-to-github-actions" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#add-variables-to-github-actions" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;Because GitHub variables can only be of string content we need to get the contents of the pfx file as base64 encoded string:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$pfxCertFilePath = &amp;#34;~\Downloads\CodeSigningCertificate.pfx&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$pfxContent = Get-Content $pfxCertFilePath -Encoding Byte
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[System.Convert]::ToBase64String($pfxContent) | Set-Clipboard&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 class="relative group"&gt;GitHub action variables
 &lt;div id="github-action-variables" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#github-action-variables" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;Add two variables as actions secrets:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;BASE64_PFX&lt;/code&gt;: Base 64 encoded string of the PFX (automatically copied into your clipboard with the above commands)
&lt;code&gt;PFX_PASSWORD&lt;/code&gt;: Password for the private key of the pfx file&lt;/p&gt;
&lt;p&gt;&lt;a href="https://user-images.githubusercontent.com/32899754/120798485-b6791e80-c53d-11eb-851f-dcb27a08b567.png" target="_blank" rel="noreferrer"&gt;&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt=""
 src="https://user-images.githubusercontent.com/32899754/120798485-b6791e80-c53d-11eb-851f-dcb27a08b567.png"
 &gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;h3 class="relative group"&gt;GitHub action workflow
 &lt;div id="github-action-workflow" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#github-action-workflow" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;Place the following workflow file within your git repository:
&lt;code&gt;.github/workflows/SignPowerShell.yaml&lt;/code&gt; whereas the name of the YAML file can be freely chosen.&lt;/p&gt;</description></item><item><title>Securely sending emails from PowerShell scripts with modern authentication enforced</title><link>https://tech.nicolonsky.ch/sending-emails-with-modern-auth/</link><pubDate>Fri, 19 Mar 2021 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/sending-emails-with-modern-auth/</guid><description>&lt;p&gt;The &lt;code&gt;Send-MailMessage&lt;/code&gt; cmdlet has been around for a couple of years and is mostly used to send email messages from PowerShell. But with the deprecation and security flaws of legacy authentication it&amp;rsquo;s time for a better option which actually supports modern authentication. For this purpose we can use the Microsoft Graph API and the Microsoft Graph PowerShell SDK. The best thing is that this solution works without any service account and does not need any exclusions from conditional access.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Microsoft Graph resource
 &lt;div id="microsoft-graph-resource" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#microsoft-graph-resource" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;To send a mail we simply specify the user account from which we want to send the email:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;POST: https://graph.microsoft.com/v1.0/users/sean.connery@dev.nicolonsky.ch/sendMail&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 class="relative group"&gt;Create an app registration
 &lt;div id="create-an-app-registration" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#create-an-app-registration" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;Simply create a new app registration with the &lt;code&gt;Mail.Send&lt;/code&gt; permissions and use a certificate for the authentication.&lt;/p&gt;
&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="New App registration"
 src="https://tech.nicolonsky.ch/content/images/2021/03/App-Permissions.png"
 &gt;&lt;/figure&gt;
&lt;p&gt;We need to take additional steps to limit the permissions of the app registration. Otherwise the app can send mails on behalf of &lt;strong&gt;any user&lt;/strong&gt; in your tenant. To limit the permissions we leverage &lt;a href="https://docs.microsoft.com/en-us/powershell/module/exchange/new-applicationaccesspolicy?view=exchange-ps" target="_blank" rel="noreferrer"&gt;exchange application access policies&lt;/a&gt;.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Connect to Exchange Online with the ExchangeOnlineManagement PowerShell module
&lt;code&gt;Connect-ExchangeOnline&lt;/code&gt;&lt;/p&gt;</description></item><item><title>Dealing with Intune OMA-URI encoding and applocker rules</title><link>https://tech.nicolonsky.ch/intune-oma-uri-encoding/</link><pubDate>Tue, 16 Feb 2021 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/intune-oma-uri-encoding/</guid><description>&lt;p&gt;While fine-tuning and adjusting applocker policies for co-managed Windows 10 clients I got really annoyed by special characters commonly used in the German/Swiss language. The Intune portal seemed to use different encoding and didn&amp;rsquo;t allow me to just copy/paste the currently deployed policy and extend it with a new rule. I needed to request the original file that was uploaded to the tenant in order to adjust the rule. Instead of just accepting this I decided that it is time for an easier approach which I will share with you.&lt;/p&gt;

&lt;h2 class="relative group"&gt;The actual issue
 &lt;div id="the-actual-issue" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#the-actual-issue" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;After uploading the XML with the applocker policies (in my case EXE rules), special characters like &amp;lsquo;ö&amp;rsquo; or &amp;lsquo;ü&amp;rsquo; have a weird encoding displayed in the portal. The next person that wants to edit the policy needs to take care to fix the unrecognized characters otherwise the publisher rule won&amp;rsquo;t work anymore.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://tech.nicolonsky.ch/content/images/2021/02/Applocker-OMA-URI.png" &gt;&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="OMA-URI"
 src="https://tech.nicolonsky.ch/content/images/2021/02/Applocker-OMA-URI.png"
 &gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Top: Portal view of the special characters, bottom: original file.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://tech.nicolonsky.ch/content/images/2021/02/Encoding-Issue.png" &gt;&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Encoding issue"
 src="https://tech.nicolonsky.ch/content/images/2021/02/Encoding-Issue.png"
 &gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;h2 class="relative group"&gt;Fixing things
 &lt;div id="fixing-things" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#fixing-things" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;Save file with UTF-8 encoding
 &lt;div id="save-file-with-utf-8-encoding" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#save-file-with-utf-8-encoding" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;First, make sure that you saved an uploaded the file with UTF-8 encoding as this introduces support for most character sets. You can do this by selecting the encoding box in the right bottom of Visual Studio Code:&lt;/p&gt;</description></item><item><title>Microsoft Graph Access Token Acquisition with PowerShell explained in depth</title><link>https://tech.nicolonsky.ch/explaining-microsoft-graph-access-token-acquisition/</link><pubDate>Mon, 04 Jan 2021 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/explaining-microsoft-graph-access-token-acquisition/</guid><description>&lt;p&gt;When working with the Microsoft Graph API or introducing the API to colleagues I often get asked about the steps required to obtain an access token for the API with PowerShell. Out in the wild, I&amp;rsquo;ve spotted many different ways and lots of implementations still relying on the ADAL (Active Directory Authentication Library) despite the fact that this client library is superseded by MSAL (Microsoft Authentication Library). So let&amp;rsquo;s talk about acquiring access token &amp;ldquo;in stile&amp;rdquo; with the most simple method available.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Why do we need an access token?
 &lt;div id="why-do-we-need-an-access-token" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#why-do-we-need-an-access-token" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;When talking about the Microsoft Graph API an access token fulfills two roles, first: prove authentication (proof of identity) second prove authorization (permissions). Each request needs to submit a request-header that contains the access token.&lt;/p&gt;
&lt;p&gt;For an API it&amp;rsquo;s crucial to validate the authentication and authorization for every request. Otherwise, requests could be made to resources the actor has no access to.&lt;/p&gt;

&lt;h2 class="relative group"&gt;What&amp;rsquo;s inside the access token
 &lt;div id="whats-inside-the-access-token" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#whats-inside-the-access-token" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;You did probably stumble over the terms &amp;ldquo;bearer authentication&amp;rdquo; or &amp;ldquo;bearer token&amp;rdquo; these describe a mechanism within the OAuth 2.0 Authorization framework to authenticate requests with access tokens. Tokens are issued by the authorization server (Azure AD) and contain a server-generated string in the format of a JSON Web Token (JWT) with the following information (the list is not exhaustive and truncated to only contain the most interesting parts):&lt;/p&gt;</description></item><item><title>Android Enterprise Enrollment: Page Not Found</title><link>https://tech.nicolonsky.ch/android-enterprise-enrollment-failure-dem/</link><pubDate>Sat, 19 Dec 2020 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/android-enterprise-enrollment-failure-dem/</guid><description>&lt;p&gt;While doing some Android Enterprise enrollment tests for corporate-owned devices with work profiles I stumbled over the following issue after signing-in with the work account: &amp;ldquo;Page not found&amp;rdquo;.&lt;/p&gt;
&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="fdgdfg"
 src="https://tech.nicolonsky.ch/content/images/2020/12/AE-DEM-Error.png"
 &gt;&lt;/figure&gt;
&lt;p&gt;The solution is fairly simple, just double check that your user does not have the device enrollment manager role assigned, which can be found under the device enrollment pane: &lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="srtg"
 src="https://tech.nicolonsky.ch/content/images/2020/12/AE-DEM.png"
 &gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;The docs tell us:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;If you&amp;rsquo;re enrolling Android Enterprise personally-owned work profile or corporate-owned work profile devices by using a DEM account, there is a limit of 10 devices that can be enrolled per account.
&lt;a href="https://docs.microsoft.com/en-us/mem/intune/enrollment/device-enrollment-manager-enroll" target="_blank" rel="noreferrer"&gt;Microsoft Docs&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;In my case, I wasn&amp;rsquo;t exceeding that limit because it was the first enrollment with that account so I&amp;rsquo;m not sure if the docs are accurate.&lt;/p&gt;
&lt;p&gt;Updated 21.12.2020:&lt;/p&gt;
&lt;p&gt;&lt;del&gt;I already opened an &lt;a href="https://github.com/MicrosoftDocs/memdocs/issues/1150" target="_blank" rel="noreferrer"&gt;issue on GitHub&lt;/a&gt; about the doc contents.&lt;/del&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;@nicolonsky Good question. Using a DEM account isn&amp;rsquo;t available to enroll COPE devices. We fixed the article. The changes should be live later today. Thanks for bringing this to our attention.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;Hope this helps.&lt;/p&gt;</description></item><item><title>Housekeeping for stale MEM profiles</title><link>https://tech.nicolonsky.ch/cleanup-mem-profiles/</link><pubDate>Wed, 16 Dec 2020 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/cleanup-mem-profiles/</guid><description>&lt;p&gt;When involved in new projects I often find a bunch of old profiles in the Microsoft Endpoint Management Console.
Before going ahead with a new implementation it&amp;rsquo;s the best time to clean-up all the leftovers from past ramblings.&lt;/p&gt;

&lt;h2 class="relative group"&gt;How to identify stale profiles
 &lt;div id="how-to-identify-stale-profiles" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#how-to-identify-stale-profiles" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;If one or multiple statements are met for a profile it is very likely to be a stale profile:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;No assignments, assignments to a group without members&lt;/li&gt;
&lt;li&gt;&amp;ldquo;Test&amp;rdquo; included within the profile name or description&lt;/li&gt;
&lt;li&gt;Last modified points back in time for more than a year&lt;/li&gt;
&lt;li&gt;No devices reported success/failure status for the given profile type&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;What to do with stale profiles
 &lt;div id="what-to-do-with-stale-profiles" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#what-to-do-with-stale-profiles" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;So let&amp;rsquo;s be brave and &lt;strong&gt;delete&lt;/strong&gt; them. But Intune doesn&amp;rsquo;t offer any [CTRL] + [Z] or recycle bin possibilities so we might want to have some kind of archive, just in case?&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s agree that we:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Check the points from the list above&lt;/li&gt;
&lt;li&gt;Ask our colleagues if they know something about the profiles and their usage&lt;/li&gt;
&lt;li&gt;Take a backup&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;deleting them afterward is a reasonable action which is probably beneficial for everyone.&lt;/p&gt;</description></item><item><title>Windows Terminal and SSH - the most beautiful SSH client?</title><link>https://tech.nicolonsky.ch/windows-terminal-ssh/</link><pubDate>Wed, 16 Dec 2020 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/windows-terminal-ssh/</guid><description>&lt;p&gt;I like to have a linux machine for some lab stuff which I can access from multiple machines prefereably over SSH. Because Windows 10 ships with an integrated SSH client and Windows Terminal looks just awesome I wanted to use Windows Terminal to access my linux machine running on Azure over SSH. Today I&amp;rsquo;d like to show you my setup.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://tech.nicolonsky.ch/content/images/2020/10/SSH-Windows-Terminal.png" &gt;&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt=""
 src="https://tech.nicolonsky.ch/content/images/2020/10/SSH-Windows-Terminal.png"
 &gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;h1 class="relative group"&gt;Generate a Key Pair
 &lt;div id="generate-a-key-pair" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#generate-a-key-pair" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h1&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ssh-keygen
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Generating public/private rsa key pair.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Enter file in which to save the key (C:\Users\NicolaSuter/.ssh/id_rsa):
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Created directory &amp;#39;C:\Users\NicolaSuter/.ssh&amp;#39;.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Enter passphrase (empty for no passphrase):
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Enter same passphrase again:
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Your identification has been saved in C:\Users\NicolaSuter/.ssh/id_rsa.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Your public key has been saved in C:\Users\NicolaSuter/.ssh/id_rsa.pub.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 class="relative group"&gt;Add SSH config file
 &lt;div id="add-ssh-config-file" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#add-ssh-config-file" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;C:\Users\%USERNAME%\.ssh\config&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Host horus
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Hostname horus.nicolonsky.ch
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Port 22
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;User azureuser
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;IdentityFile ~/.ssh/id_rsa&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 class="relative group"&gt;Test the SSH connection
 &lt;div id="test-the-ssh-connection" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#test-the-ssh-connection" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;ssh horus&lt;/code&gt;&lt;/p&gt;

&lt;h2 class="relative group"&gt;Windows Terminal Configuration
 &lt;div id="windows-terminal-configuration" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#windows-terminal-configuration" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;Create a new GUID with Powershell and the command: &lt;code&gt;(New-Guid).Guid&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;guid&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;{67d39a21-70ff-4bdd-af09-fd68b29c1716}&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Horus&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;commandline&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;ssh horus&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;hidden&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;icon&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://image.flaticon.com/icons/png/512/119/119423.png&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 class="relative group"&gt;Sync Windows Terminal Settings with OneDrive
 &lt;div id="sync-windows-terminal-settings-with-onedrive" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#sync-windows-terminal-settings-with-onedrive" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;We can setup a symlink to use the Windows Terminal Config stored in OneDrive:&lt;/p&gt;</description></item><item><title>Export and import MEM Endpoint Security Profiles</title><link>https://tech.nicolonsky.ch/endpoint-security-profiles/</link><pubDate>Thu, 19 Nov 2020 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/endpoint-security-profiles/</guid><description>&lt;p&gt;Recently I got a DM on Twitter with a question about how to export and import Endpoint Security profiles with Microsoft Graph. Besides a technical answer which might be of interest for you, I&amp;rsquo;d like to show you the workflow I used to give a proper reply.&lt;/p&gt;
&lt;p&gt;Original question:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Hi &lt;a href="https://twitter.com/nicolonsky" target="_blank" rel="noreferrer"&gt;@nicolonsky&lt;/a&gt;, I was advised on the MS Elite Partner focus groups team (MEM Automation) to reach out to you regarding my question about export/import policies from Endpoint Security in Intune. I&amp;rsquo;ve been able to export the Disk Encryption policy (via graph explorer), but haven&amp;rsquo;t been able to find the correct format to use to upload/import it. I was hoping that you would be able to advise on how to go about achieving this.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 class="relative group"&gt;Workflow
 &lt;div id="workflow" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#workflow" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;Discover request URL&amp;rsquo;s and payload
 &lt;div id="discover-request-urls-and-payload" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#discover-request-urls-and-payload" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;To discover the request URLs and payloads I used the methodology I explained in the &lt;a href="https://tech.nicolonsky.ch/discover-mem-graph-urls/" &gt;this post&lt;/a&gt; a while ago.
Basically, I tracked the network activity and used a filter to only include requests made to the Graph API while doing the following activities:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://tech.nicolonsky.ch/content/images/2020/11/Examine-Request-Urls-And-Payload.png" &gt;&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="examine microsoft graph request urls with your browsers dev tools"
 src="https://tech.nicolonsky.ch/content/images/2020/11/Examine-Request-Urls-And-Payload.png"
 &gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Shut up Surface Pro 7 fan noise!</title><link>https://tech.nicolonsky.ch/shut-up-surface-pro/</link><pubDate>Mon, 16 Nov 2020 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/shut-up-surface-pro/</guid><description>&lt;p&gt;I recently bought a Surface Pro 7 with an Intel Core i7 and 256 GB SSD and it was a quite good deal. I&amp;rsquo;m using it primarily for my studies in computer sciences which involves lots of development with Java, Python, C, Linux and so on. Furthermore, I&amp;rsquo;m using it to write blog posts for this blog.&lt;/p&gt;
&lt;p&gt;One thing which annoyed me since day 1 was the fan going absolutely crazy when plugged to AC power. Having only OneNote open and a couple of browser tabs and maybe teams the noise was way too loud and even heard by other participants in meetings.&lt;/p&gt;
&lt;p&gt;On Reddit I found a &lt;a href="https://www.reddit.com/r/Surface/comments/e7b8tu/surface_pro_7_fan_noise/" target="_blank" rel="noreferrer"&gt;hint&lt;/a&gt; to a setting which indeed solved my solution.&lt;/p&gt;
&lt;p&gt;We need to adjust the &amp;ldquo;max. processor power state&amp;rdquo; setting which is not visible by default on surface devices. To show the setting add this reg key with PowerShell:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;Set-ItemProperty&lt;/span&gt; &lt;span class="n"&gt;-Path&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;HKLM:\SYSTEM\CurrentControlSet\Control\Power\PowerSettings\54533251-82be-4824-96c1-47b60b740d00\bc5038f7-23e0-4960-96da-33abaf5935ec&amp;#34;&lt;/span&gt; &lt;span class="n"&gt;-Name&lt;/span&gt; &lt;span class="n"&gt;Attributes&lt;/span&gt; &lt;span class="n"&gt;-Value&lt;/span&gt; &lt;span class="mf"&gt;2&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Afterwards, we can change the &amp;ldquo;max. processor power state&amp;rdquo; setting within the power settings in the control panel:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://tech.nicolonsky.ch/content/images/2020/11/shut-up-surface.png" &gt;&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Power settings"
 src="https://tech.nicolonsky.ch/content/images/2020/11/shut-up-surface.png"
 &gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Hope this helps you as well to enjoy your Surface Pro 7 with a much quieter fan. 🐱‍💻&lt;/p&gt;</description></item><item><title>Build an Azure DevOps pipeline to automatically sign your PowerShell scripts</title><link>https://tech.nicolonsky.ch/sign-powershell-az-devops/</link><pubDate>Thu, 01 Oct 2020 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/sign-powershell-az-devops/</guid><description>&lt;p&gt;Too lazy to sign your PowerShell scripts? Yes of course it provides security benefits but performing the steps manually can be easily forgotten and re-signing needs to happen after every script change. Because I like CI/CD topics and have not found a solution on the internet I decided to build a solution based on Azure capabilities. Furthermore, I wanted a solution which does not require to hand out the code signing certificate to the respective script author which can be useful if you have a bunch of people writing PowerShell scripts.&lt;/p&gt;
&lt;p&gt;From a personal perspective, I would also recommend signing scripts you hand over to customers to ensure the integrity of the scripts because as soon as the script gets changed the signature is invalid.&lt;/p&gt;
&lt;p&gt;You can find more general recommendations about script signing in the &lt;a href="https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_signing" target="_blank" rel="noreferrer"&gt;PowerShell docs&lt;/a&gt;.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Solution overview
 &lt;div id="solution-overview" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#solution-overview" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;The key vault will store the code signing certificate with an access policy that allows access from the Azure DevOps pipeline.&lt;/p&gt;
&lt;p&gt;The pipeline consists of the following steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Import code signing certificate
&lt;ul&gt;
&lt;li&gt;The certificate is supplied as secret in a variable group which is linked to the key vault&lt;/li&gt;
&lt;li&gt;Access to the key vault is granted with a service connection (service principal)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Sign PowerShell scripts which contain a &amp;ldquo;magic token&amp;rdquo;
&lt;ul&gt;
&lt;li&gt;All &lt;code&gt;*.ps1&lt;/code&gt; within the attached repository will be enumerated&lt;/li&gt;
&lt;li&gt;To control which scripts will be signed only those with the &amp;ldquo;magic token&amp;rdquo; get processed&lt;/li&gt;
&lt;li&gt;The &amp;ldquo;magic token&amp;rdquo; gets removed before signing the script&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Publish signed PowerShell scripts as pipeline artifacts
&lt;ul&gt;
&lt;li&gt;To make them available for download&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="https://tech.nicolonsky.ch/content/images/2020/10/PoshSigning_DevOps.png" &gt;&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Solution overview"
 src="https://tech.nicolonsky.ch/content/images/2020/10/PoshSigning_DevOps.png"
 &gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Ensuring regular Defender Quick scans with Microsoft Endpoint Manager proactive remediations</title><link>https://tech.nicolonsky.ch/defender-scan-endpoint-analytics/</link><pubDate>Mon, 28 Sep 2020 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/defender-scan-endpoint-analytics/</guid><description>&lt;p&gt;While looking into the new Microsoft Defender Antivirus report available in MEM (Intune) I discovered some machines which did not report any recent Defender antimalware scans, despite configured via configuration profile. Of course, AV scans are kinda old-fashioned against rapidly evolving threats but a regular quick scan won&amp;rsquo;t hurt anyone. Instead of having a look at every single machine affected, I decided to try out the new proactive remediations feature which went globally available last week and let endpoint analytics do the detection and remediation work for me. As a reference, I used the &lt;a href="https://docs.microsoft.com/en-us/mem/analytics/proactive-remediations" target="_blank" rel="noreferrer"&gt;Tutorial: Proactive remediations&lt;/a&gt; from Microsoft which covers the process quite well.&lt;/p&gt;

&lt;h2 class="relative group"&gt;PowerShell scrips
 &lt;div id="powershell-scrips" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#powershell-scrips" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;For Endpoint analytics / Proactive remediations we need two PowerShell scripts. The first script is used as a detection script and determines whether remediation is necessary based on the exit code. Exit code &lt;code&gt;0&lt;/code&gt; indicates a healthy status and exit code &lt;code&gt;1&lt;/code&gt; indicates remediation necessary. Remediation occurs with a second PowerShell script.&lt;/p&gt;
&lt;p&gt;To detect the most recent Defender scan I used the Windows Eventlog. Event ID&amp;rsquo;s are documented &lt;a href="https://docs.microsoft.com/en-us/windows/security/threat-protection/microsoft-defender-antivirus/troubleshoot-microsoft-defender-antivirus#to-view-a-microsoft-defender-antivirus-event" target="_blank" rel="noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3 class="relative group"&gt;Detection script
 &lt;div id="detection-script" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#detection-script" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;script src="https://gist.github.com/nicolonsky/ac80d1cc89c9b42c2ed8099592e5c2bc.js"&gt;&lt;/script&gt;

&lt;h3 class="relative group"&gt;Remediation script
 &lt;div id="remediation-script" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#remediation-script" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;The remediation script is just about a one-liner to trigger a quick scan. You can extend this based on your requirements and respective to your Intune settings. E.g. triggering a signature update for a scan or adding additional steps.&lt;/p&gt;</description></item><item><title>Discover the Microsoft Graph API with the Microsoft Endpoint Manager Portal</title><link>https://tech.nicolonsky.ch/discover-mem-graph-urls/</link><pubDate>Tue, 08 Sep 2020 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/discover-mem-graph-urls/</guid><description>&lt;p&gt;You always wanted to automate a specific action within Intune / the Microsoft Endpoint Manager Portal (MEM) but were afraid of the complexity? The Microsoft Graph API docs deliver you more questions instead of answers? Automating tasks within the MEM portal could be very easy, couldn&amp;rsquo;t it? I promise it will be much simpler with this magician trick.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Microsoft Endpoint Manager Portal
 &lt;div id="microsoft-endpoint-manager-portal" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#microsoft-endpoint-manager-portal" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;The MEM Portal UI relies on the Microsoft Graph API. This means that the UI where you create new settings and policies and the Intune backend are encapsulated with different layers. Communication between the UI and the backend happens with the Microsoft Graph API. With the developer tools we can trace network traffic and discover the request URLs and request body payload which are required to interact with the API.&lt;/p&gt;
&lt;p&gt;&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Architecture"
 src="https://tech.nicolonsky.ch/content/images/2020/09/MEM-Portal-Automation.svg"
 &gt;&lt;/figure&gt;
{: .align-center}&lt;/p&gt;

&lt;h2 class="relative group"&gt;Example about how to capture URLs and build a PowerShell script
 &lt;div id="example-about-how-to-capture-urls-and-build-a-powershell-script" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#example-about-how-to-capture-urls-and-build-a-powershell-script" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;"&gt;
 &lt;iframe allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" loading="eager" referrerpolicy="strict-origin-when-cross-origin" src="https://www.youtube.com/embed/k6ZCSJVXaOI?autoplay=0&amp;amp;controls=1&amp;amp;end=0&amp;amp;loop=0&amp;amp;mute=0&amp;amp;start=0" style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;" title="YouTube video"&gt;&lt;/iframe&gt;
 &lt;/div&gt;

&lt;p&gt;Original request body:&lt;/p&gt;</description></item><item><title>Access has been blocked by Conditional Access policies when using device code flow</title><link>https://tech.nicolonsky.ch/device-code-auth-ca/</link><pubDate>Thu, 03 Sep 2020 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/device-code-auth-ca/</guid><description>&lt;p&gt;When using device code authentication for PowerShell modules with conditional access you might receive prompts like: &amp;ldquo;&lt;code&gt;Access has been blocked by Conditional Access policies. The access policy does not allow token issuance&lt;/code&gt;&amp;rdquo; or &amp;ldquo;&lt;code&gt;AADSTS50097: Device authentication is required&lt;/code&gt;&amp;rdquo;. But what&amp;rsquo;s the reason for this error and is there a solution available?&lt;/p&gt;

&lt;h2 class="relative group"&gt;Examples from the field
 &lt;div id="examples-from-the-field" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#examples-from-the-field" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;Device code flow is quite a convenient way to sign-in for an app within the web browser - at least if it works. If not you have to consider other options and that&amp;rsquo;s probably the reason why you&amp;rsquo;re reading this blog article.&lt;/p&gt;
&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Device Code Auth"
 src="https://tech.nicolonsky.ch/content/images/2020/09/device-code-auth-conditional-access.png"
 &gt;&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;Az PowerShell&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Running the Az PowerShell module on PowerShell 7 uses device code flow to authenticate against your Azure tenant and might fail:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Connect-AzAccount: AADSTS50097: Device authentication is required.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Timestamp: 2020-08-17 13:36:31Z: Response status code does not indicate success: 401 (Unauthorized).&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The sign-in to Azure is tied to the &amp;ldquo;Microsoft Azure Management&amp;rdquo; app that you can select within Conditional Access.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Microsoft Graph PowerShell&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The same applies for the new Microsoft.Graph PowerShell modules - but here we receive a more detailed error message:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Connect-Graph: AADSTS53003: Access has been blocked by Conditional Access policies. The access policy does not allow token issuance.
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Timestamp: 2020-08-17 13:37:12Z&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The sign-in to the new Microsoft Graph Modules is tied to the &amp;ldquo;Microsoft Graph PowerShell (Preview)&amp;rdquo; app and some more apps I couldn&amp;rsquo;t determine.&lt;/p&gt;</description></item><item><title>Bulk create Intune mobile app deployment groups and assignments</title><link>https://tech.nicolonsky.ch/intune-mobile-app-assignment-bulk/</link><pubDate>Wed, 19 Aug 2020 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/intune-mobile-app-assignment-bulk/</guid><description>&lt;p&gt;Creating assignments and software deployment groups for Intune mobile apps is quite a repetitive and manual task. Because of that, I want to share a PowerShell script with you which allows you to automatically create software deployment groups in Azure AD and the assignments for various intents.&lt;/p&gt;
&lt;p&gt;The script allows you to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create Azure AD groups (install uninstall purpose)
&lt;ul&gt;
&lt;li&gt;Pick existing groups based on displayName&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Assign Intune mobile apps (tested for Win32 and MSI LOB apps)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="https://tech.nicolonsky.ch/content/images/2020/08/intune-mobile-app-assignment-bulk.gif" &gt;&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Script in Action"
 src="https://tech.nicolonsky.ch/content/images/2020/08/intune-mobile-app-assignment-bulk.gif"
 &gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/nicolonsky/Techblog/tree/master/IntuneMobileAppAssignment" target="_blank" rel="noreferrer"&gt;You can find the script on my techblog GitHub repository&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Because of the &lt;a href="https://github.com/nicolonsky/Techblog/blob/master/IntuneMobileAppAssignment/New-IntuneAppAssignment.ps1#L220" target="_blank" rel="noreferrer"&gt;configurable group prefixes&lt;/a&gt; the script helps you to keep your Intune environment clean and implement a standard app assignment configuration.&lt;/p&gt;
&lt;p&gt;The script uses the Microsoft Graph API and the following resources&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;https://graph.microsoft.com/beta/deviceAppmanagement/mobileApps&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;https://graph.microsoft.com/beta/deviceAppmanagement/mobileApps/{AppID}/Assignments&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;https://graph.microsoft.com/beta/groups&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It uses the preregistered app &amp;ldquo;Microsoft Intune PowerShell&amp;rdquo; which exists by default in all tenants. If you want to run the Script with PowerShell 7 you need to create an adjust the MSAL token section with the &lt;code&gt;-DeviceCode&lt;/code&gt; parameter.&lt;/p&gt;
&lt;p&gt;You can bulk select the apps you want to create the assignment and AAD deployment groups:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://tech.nicolonsky.ch/content/images/2020/08/intune-mobile-app-assignment-bulk-select.png" &gt;&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="App assignment"
 src="https://tech.nicolonsky.ch/content/images/2020/08/intune-mobile-app-assignment-bulk-select.png"
 &gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Hope this saves you some time.&lt;/p&gt;</description></item><item><title>Add PowerShell modules to Azure functions</title><link>https://tech.nicolonsky.ch/azure-functions-powershell-modules/</link><pubDate>Mon, 17 Aug 2020 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/azure-functions-powershell-modules/</guid><description>&lt;p&gt;Azure functions for PowerShell natively ship without additional cmdlets or PowerShell modules. In this post, I will show you how to add both public modules from the PowerShell gallery with automatic dependency management and custom modules.&lt;/p&gt;
&lt;p&gt;For both options, we use the Kudu tools to adjust the configuration of our function app. You can launch them from the &lt;em&gt;&amp;ldquo;Advanced Tools&amp;rdquo;&lt;/em&gt; section of your function app:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://tech.nicolonsky.ch/content/images/2020/08/add-powershell-modules-to-azure-functions-kudu.png" &gt;&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Kudu tools"
 src="https://tech.nicolonsky.ch/content/images/2020/08/add-powershell-modules-to-azure-functions-kudu.png"
 &gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Afterwards, launch the PowerShell debug console and navigate to the &lt;code&gt;wwwroot&lt;/code&gt; folder of your app:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://tech.nicolonsky.ch/content/images/2020/08/add-powershell-modules-to-azure-functions-kudu.gif" &gt;&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Kudu debug console"
 src="https://tech.nicolonsky.ch/content/images/2020/08/add-powershell-modules-to-azure-functions-kudu.gif"
 &gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;h2 class="relative group"&gt;Option 1: Automatic dependency management
 &lt;div id="option-1-automatic-dependency-management" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#option-1-automatic-dependency-management" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Installing modules which require license acceptance (e.g. the MSAL.PS module) currently cannot be installed with automatic dependency management.
You can track the issue status &lt;a href="https://github.com/Azure/azure-functions-powershell-worker/issues/417" target="_blank" rel="noreferrer"&gt;here&lt;/a&gt; and &lt;a href="https://github.com/MicrosoftDocs/azure-docs/issues/60701" target="_blank" rel="noreferrer"&gt;here&lt;/a&gt;.
{: .notice&amp;ndash;warning}&lt;/p&gt;
&lt;p&gt;Azure function apps running PowerShell come with a nice feature called managed dependencies. You can specify the modules you want to import from the PowerShell Gallery and the function app host will automatically process the dependencies.&lt;/p&gt;
&lt;p&gt;In the &lt;code&gt;requirements.psd1&lt;/code&gt; add the module details:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# This file enables modules to be automatically managed by the Functions service.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;# See https://aka.ms/functionsmanageddependency for additional information.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="vm"&gt;@&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c"&gt;# For latest supported version, go to &amp;#39;https://www.powershellgallery.com/packages/Az&amp;#39;.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;Az&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;4.*&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;Microsoft.Graph.Authentication&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;0.*&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;You can either specify an exact version available from the PowerShell Gallery or specify the major version with a wildcard. With the wildcard option it will use the latest version available.&lt;/p&gt;</description></item><item><title>Playing around with the Office 365 Service Communications API</title><link>https://tech.nicolonsky.ch/microsoft365-service-status/</link><pubDate>Mon, 10 Aug 2020 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/microsoft365-service-status/</guid><description>&lt;p&gt;The Office 365 Service Communications API provides information about Microsoft 365 service status for your tenant including service messages. I built a little PowerShell module to access the API with PowerShell cmdlets. In this post I want to show you some examples which help you to use the API.&lt;/p&gt;

&lt;h2 class="relative group"&gt;PowerShell Module
 &lt;div id="powershell-module" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#powershell-module" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;I built a PowerShell module to access Microsoft 365 service status details natively with PowerShell. The PowerShell module and documentation is available on the &lt;a href="https://www.powershellgallery.com/packages/Microsoft365ServiceStatus" target="_blank" rel="noreferrer"&gt;PowerShell Gallery&lt;/a&gt; and on &lt;a href="https://github.com/nicolonsky/Microsoft365ServiceStatus" target="_blank" rel="noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Before using the module an app registration is required. Setup instructions are also provided on GitHub.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://user-images.githubusercontent.com/32899754/89341042-fe6eb100-d6a0-11ea-80a7-e7357f9717c5.gif" target="_blank" rel="noreferrer"&gt;&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Module"
 src="https://user-images.githubusercontent.com/32899754/89341042-fe6eb100-d6a0-11ea-80a7-e7357f9717c5.gif"
 &gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;h3 class="relative group"&gt;CI/CD
 &lt;div id="cicd" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#cicd" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;By leveraging Azure DevOps I created a build and release pipeline which automatically builds the PowerShell module with Plaster.&lt;/p&gt;
&lt;p&gt;Builds are only created if the commit on GitHub includes a version tag. This version tag gets automatically populated to the module manifest.&lt;/p&gt;
&lt;p&gt;The build artifact gets then automatically published to the PowerShell Gallery as a new version. Furthermore, a new GitHub release including the module artifact is added to the project.&lt;/p&gt;
&lt;p&gt;This process fully automates the publishing and build process for the module. For local development and maintenance, the module can also be built with &lt;a href="https://github.com/nightroman/Invoke-Build" target="_blank" rel="noreferrer"&gt;&lt;code&gt;Invoke-Build&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Intune scope tags and role-based access control explained</title><link>https://tech.nicolonsky.ch/intune-scope-tags-rbac-explained/</link><pubDate>Mon, 03 Aug 2020 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/intune-scope-tags-rbac-explained/</guid><description>&lt;p&gt;For larger Intune environments a solid role-based access implementation becomes crucial to ensure a secure administration. But how does Intune role-based access control (RBAC) work in combination with scope tags and how to get started? This post gets you covered with explanations and practical examples.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Role-based access control within the Microsoft 365 ecosystem
 &lt;div id="role-based-access-control-within-the-microsoft-365-ecosystem" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#role-based-access-control-within-the-microsoft-365-ecosystem" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;Within the Microsoft 365 ecosystem, Microsoft provides Azure AD administrative roles to administrate services like Exchange (Exchange administrator), SharePoint (SharePoint administrator), Intune (Intune administrator) and so on.&lt;/p&gt;
&lt;p&gt;As you can see Azure AD provides (usually) only one role which grants full administrative access over a service. You can configure more fine-grained controls within the service itself - that&amp;rsquo;s where the RBAC controls of the respective service kick in.&lt;/p&gt;
&lt;p&gt;To give you another example: You might have a 1&lt;sup&gt;st&lt;/sup&gt; or 2&lt;sup&gt;nd&lt;/sup&gt; level support department which needs permissions to perform remote actions on Intune managed devices. Instead of assigning them the Azure AD Intune Administrator role, it&amp;rsquo;s more convenient to assign them a fine-grained Intune RBAC role which delegates exactly the permissions needed.&lt;/p&gt;
&lt;p&gt;As the name already indicates Intune related roles only live within the Intune tenant and cannot be managed from AAD and vice-versa:&lt;/p&gt;</description></item><item><title>Azure AD guest user review solution</title><link>https://tech.nicolonsky.ch/azure-ad-guest-user-review-solution/</link><pubDate>Tue, 14 Jul 2020 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/azure-ad-guest-user-review-solution/</guid><description>&lt;p&gt;Azure Active Directory guest users really simplify the process to collaborate with external users. Although keeping a good governance on guest accounts can become quite a challenge.
The two biggest challenges I often observe are: &lt;em&gt;&amp;ldquo;Who invited that guest user?&amp;rdquo;&lt;/em&gt; and &lt;em&gt;&amp;ldquo;Does this guest user still need access to our infrastructure?&amp;rdquo;&lt;/em&gt;. Inspired by a recent post of Thomas Kurth regarding &lt;a href="https://www.wpninjas.ch/2020/06/azure-ad-guest-account-governance-and-cleanup/" target="_blank" rel="noreferrer"&gt;Azure AD Guest Account - Governance and Cleanup&lt;/a&gt; I also developed a solution which comes quite close to an &amp;ldquo;Azure AD Access review&amp;rdquo; like user experience.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Notable features
 &lt;div id="notable-features" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#notable-features" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;The &amp;lsquo;Manager&amp;rsquo; attribute of your guest users get&amp;rsquo;s automatically populated with the identity of the inviter&lt;/li&gt;
&lt;li&gt;All Azure AD app registration information is stored in Azure Key Vault&lt;/li&gt;
&lt;li&gt;Almost zero touch deployment with ARM templates&lt;/li&gt;
&lt;li&gt;You can integrate existing guest users into this solution by populating the manager attribute in Azure AD&lt;/li&gt;
&lt;li&gt;You can configure the approval frequency for guest accounts&lt;/li&gt;
&lt;li&gt;Approval frequency respects last approval date for each guest account&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;Architecture
 &lt;div id="architecture" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#architecture" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://tech.nicolonsky.ch/content/images/2020/07/AzureADGuestReview-AzScheme.png" &gt;&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Azure AD Guest User Review"
 src="https://tech.nicolonsky.ch/content/images/2020/07/AzureADGuestReview-AzScheme.png"
 &gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The solution leverages function of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Azure Logic App&lt;/p&gt;</description></item><item><title>Who invited this Azure AD guest user?</title><link>https://tech.nicolonsky.ch/who-invited-azure-ad-guest/</link><pubDate>Tue, 14 Jul 2020 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/who-invited-azure-ad-guest/</guid><description>&lt;p&gt;Who invited this Azure AD guest user? Examining who invited a specific a guest account can be quite a challenging question if you don&amp;rsquo;t have a log analytics workspace in place with Azure AD Audit log forwarding configured.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Kusto queries for your log analytics workspace
 &lt;div id="kusto-queries-for-your-log-analytics-workspace" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#kusto-queries-for-your-log-analytics-workspace" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;The following queries help you to identify who invited a guest. If you haven&amp;rsquo;t set-up Azure AD audit log forwarding it&amp;rsquo;s the right time to do it now &lt;a href="https://tech.nicolonsky.ch/conditional-access-and-azure-log-analytics-in-harmony/#forward-aad-logs-to-log-analytics" &gt;as described in one of my previous blogs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To find all guest invitations:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="no"&gt;AuditLogs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt; &lt;span class="no"&gt;OperationName&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Invite external user&amp;#39;&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="no"&gt;Result&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;success&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;To find all accepted invitations:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-ruby" data-lang="ruby"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="no"&gt;AuditLogs&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt; &lt;span class="no"&gt;OperationName&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Invite external user&amp;#39;&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="no"&gt;Result&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;success&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kp"&gt;extend&lt;/span&gt; &lt;span class="no"&gt;InvitationId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tostring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;AdditionalDetails&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;join&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 	&lt;span class="no"&gt;AuditLogs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt; &lt;span class="no"&gt;OperationName&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Redeem external user invite&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;parse&lt;/span&gt; &lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;regex&lt;/span&gt; &lt;span class="no"&gt;TargetResources&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;].&lt;/span&gt;&lt;span class="n"&gt;displayName&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;InvitationId: &amp;#34;&lt;/span&gt; &lt;span class="ss"&gt;InvitationId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;,&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="vg"&gt;$left&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InvitationId&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="vg"&gt;$right&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;InvitationId&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 class="relative group"&gt;Improving your guest user governance
 &lt;div id="improving-your-guest-user-governance" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#improving-your-guest-user-governance" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;To simplify the guest user review and management process I developed a solution which fully automates this process. Additionally the solution populates the user who invited a guest as the guest&amp;rsquo;s manager which allows you to easily examine the question &lt;em&gt;&amp;ldquo;Who invited this Azure AD Guest Account?&amp;rdquo;&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://tech.nicolonsky.ch/azure-ad-guest-user-review-solution/" &gt;Azure AD guest user review solution&lt;/a&gt;&lt;/p&gt;</description></item><item><title>10 suggestions to improve your next PowerShell script</title><link>https://tech.nicolonsky.ch/10-suggestions-to-improve-your-next-powershell-script/</link><pubDate>Wed, 08 Jul 2020 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/10-suggestions-to-improve-your-next-powershell-script/</guid><description>&lt;p&gt;Most of the time PowerShell is my favourite choice to automate processes and tasks. In order to improve the maintainability of my scripts I usually try to focus on some standards combined with a clean scripting style. In this post I want to show you 10 suggestions to improve your next PowerShell script. I&amp;rsquo;ve tried to order the suggestions according to an actual PowerShell starting from the very first line till the last line.&lt;/p&gt;

&lt;h2 class="relative group"&gt;1. Script prerequisites
 &lt;div id="1-script-prerequisites" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#1-script-prerequisites" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;Your PowerShell script might need specific modules or elevated user rights to run. The &lt;code&gt;#Requires&lt;/code&gt; statement ensures that these prerequisites are met before the actual script get&amp;rsquo;s executed. So you don&amp;rsquo;t need to implement your own checks to verify prerequisites.&lt;/p&gt;
&lt;p&gt;Simply use the &lt;code&gt;#Requires&lt;/code&gt; statement at the very first line of your script. &lt;a href="https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_requires" target="_blank" rel="noreferrer"&gt;Find out more about #Requires statement&lt;/a&gt;.&lt;/p&gt;

&lt;h3 class="relative group"&gt;Modules
 &lt;div id="modules" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#modules" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;Another benefit of specifying the modules within the requires statement is that scripts hosted on the PowerShell Gallery automatically install the modules mentioned in the &lt;code&gt;#Requires&lt;/code&gt; list.&lt;/p&gt;
&lt;p&gt;To make sure a specific module is installed use:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;#&lt;/span&gt;&lt;span class="k"&gt;Requires&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;-module&lt;/span&gt;&lt;span class="na"&gt; &amp;#34;Microsoft.Graph.Intune&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;To ensure a module with a specific version is available:&lt;/p&gt;</description></item><item><title>Remove Azure AD direct License Assignments with PowerShell</title><link>https://tech.nicolonsky.ch/remove-azure-ad-direct-license-assignments-with-powershell/</link><pubDate>Wed, 08 Jul 2020 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/remove-azure-ad-direct-license-assignments-with-powershell/</guid><description>&lt;p&gt;Who doesn&amp;rsquo;t love a clean and tidy environment, do you? This also applies for your license assignments in Office 365 and Azure AD. As time passess it is likely to have users with direct license assignments or users which still have old trial licenses assigned. To get rid of those assignments I created a PowerShell script with removal and reporting functionality.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/nicolonsky/Techblog/tree/master/CleanupAzureADLicensing" target="_blank" rel="noreferrer"&gt;Direct link to the script&lt;/a&gt;.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Identify direct license assignments
 &lt;div id="identify-direct-license-assignments" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#identify-direct-license-assignments" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;In the Azure Portal we recognize direct license assignments on a user account by viewing the &amp;ldquo;Assignment Paths&amp;rdquo;:
&lt;a href="https://tech.nicolonsky.ch/content/images/2020/07/Remove-Azure-AD-direct-License-Assignments-with-PowerShell-Portal-View.png" &gt;&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Azure AD Direct License Assignment Portal View"
 src="https://tech.nicolonsky.ch/content/images/2020/07/Remove-Azure-AD-direct-License-Assignments-with-PowerShell-Portal-View.png"
 &gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;With the MSOnline PowerShell module we can view the &lt;code&gt;Licenses&lt;/code&gt; property of a user and retrieve a nested property called: &lt;code&gt;GroupsAssigningLicense&lt;/code&gt;. The &lt;code&gt;GroupsAssigningLicense&lt;/code&gt; property contains either:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An empty array if the license was not inherited from a group -&amp;gt; direct assignment&lt;/li&gt;
&lt;li&gt;An array with objectId&amp;rsquo;s
&lt;ul&gt;
&lt;li&gt;If the array contains the user&amp;rsquo;s objectId -&amp;gt; direct assignment&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Example 1: User with objectId &lt;code&gt;36c9b091-fe88-4dc2-a9e1-2662020b4bab&lt;/code&gt; has group based license assignment and direct assignment:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;AccountSkuId : nicolasuter:SPE_E5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;GroupsAssigningLicense : {0a918505-d0d5-4078-9891-0e8bec67cb65, 36c9b091-fe88-4dc2-a9e1-2662020b4bab}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Example 2: User has no inherited licenses from a group:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;AccountSkuId : nicolasuter:SPE_E5
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;GroupsAssigningLicense : {}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 class="relative group"&gt;PowerShell Script
 &lt;div id="powershell-script" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#powershell-script" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;You find the PowerShell script &lt;a href="https://github.com/nicolonsky/Techblog/tree/master/CleanupAzureADLicensing" target="_blank" rel="noreferrer"&gt;on my techblog GitHub repository&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>How I migrated my Ghost blog to Jekyll</title><link>https://tech.nicolonsky.ch/migrate-ghost-blog-to-jekyll/</link><pubDate>Sat, 27 Jun 2020 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/migrate-ghost-blog-to-jekyll/</guid><description>&lt;p&gt;Another migration of my blog? After running it for almost three years I thought it&amp;rsquo;s time for another change. The Ghost platform introduced a lot of changes and updates (with features that I don&amp;rsquo;t need) and caused me quite some expenses on my Azure subscription (around 50$ each month). Furthermore I wanted someting looking more clean with more focus on the writing part without a lot of fancy add-ons and functionalities. But it still had to cover features like tag summaries, yearly archive and a site search (Ghost doesn&amp;rsquo;t ship with those features out of the box). Because static sites seem to be a thing now I thought let&amp;rsquo;s hop onto the static site generator train.&lt;/p&gt;
&lt;p&gt;I did some subjective research and decided that it will be &lt;a href="https://jekyllrb.com/" target="_blank" rel="noreferrer"&gt;Jekyll&lt;/a&gt;. I&amp;rsquo;ve chosen Jekyll because it&amp;rsquo;s quite easy to understand compared to hugo. Although hugo offers GraphQL which allows you to generate blog posts basically from any source including a REST API and Ghost has such an API in place which provides access to all posts.&lt;/p&gt;
&lt;p&gt;To sum up the evolution of my blog:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;2017 - 2018: Wordpress (hosted on a free hoster)&lt;/li&gt;
&lt;li&gt;2018 - 2020: Ghost (hosted on Azure)&lt;/li&gt;
&lt;li&gt;2020 - 20xx: Jekyll (hosted on GitHub Pages)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Since the beginning of my blog I had my DNS zones running on Cloudflare including CDN features.
When I migrated from Wordpress to Ghost I also migrated the comments to Disqus -&amp;gt; so for this migration I didn&amp;rsquo;t need to change anything regarding comments.&lt;/p&gt;</description></item><item><title>Exploring the new Microsoft Graph PowerShell Module(s)</title><link>https://tech.nicolonsky.ch/exploring-the-new-microsoft-graph-powershell-modules/</link><pubDate>Tue, 12 May 2020 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/exploring-the-new-microsoft-graph-powershell-modules/</guid><description>&lt;p&gt;Microsoft is working on a new set of PowerShell modules grouped under the umbrella of &lt;a href="https://github.com/microsoftgraph/msgraph-sdk-powershell" target="_blank" rel="noreferrer"&gt;Microsoft.Graph&lt;/a&gt; that will (hopefully) cover all the Microsoft Graph resources available. I&amp;rsquo;ve already used some of them for my &lt;a href="https://github.com/nicolonsky/ConditionalAccessDocumentation" target="_blank" rel="noreferrer"&gt;Conditional Access Documentation Script&lt;/a&gt; and thought they have some notable features worth sharing.&lt;/p&gt;

&lt;h3 class="relative group"&gt;Advantages and changes
 &lt;div id="advantages-and-changes" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#advantages-and-changes" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;The Microsoft Graph modules use the new Microsoft Authentication Library (MSAL) instead of the old Azure AD Authentication Library (ADAL). The MSAL library in the modules implements a token cache which persists the access and refresh tokens.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;MSAL caches a token after it has been acquired. Application code should try to get a token silently (from the cache), first, before acquiring a token by other means. - &lt;a href="https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-acquire-cache-tokens" target="_blank" rel="noreferrer"&gt;Microsoft docs&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;The token cache persists system reboots and re-opening PowerShell sessions. The module allows you to obtain tokens either for authentication via &lt;a href="https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-authentication-flows#client-credentials" target="_blank" rel="noreferrer"&gt;client credentials&lt;/a&gt; (certificate only) or &lt;a href="https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-device-code" target="_blank" rel="noreferrer"&gt;device code flow&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Furthermore, the new modules support a really broad spectrum of available entities on the Graph API. From an EM+S perspective this means for example: groups, users, identity protection, conditional access, and some of the Intune app management commands are also starting to appear.&lt;/p&gt;
&lt;p&gt;Just be aware that the modules are currently published as pre-release. If you encounter any issues share them with the development team on GitHub and submit issues or even better contribute directly to the project.&lt;/p&gt;</description></item><item><title>Validating a GUID with PowerShell</title><link>https://tech.nicolonsky.ch/validating-a-guid-with-powershell/</link><pubDate>Tue, 05 May 2020 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/validating-a-guid-with-powershell/</guid><description>&lt;p&gt;For some recent Microsoft Graph scripts I wanted to translate some Azure AD Object ID / GUID entries to their respective display name. The array with the GUID&amp;rsquo;s contained already some readable text. Of course I only wanted to translate the GUID entries with according Graph API requests. Otherwise the Graph requests would fail. Google offered only some fancy regex functions and helpers but I had that .NET function in my mind which looks much nicer compared to whatever regex pattern that I don&amp;rsquo;t understand.&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;#34;applications&amp;#34;: {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;includeApplications&amp;#34;: [
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;797f4846-ba00-4fd7-ba43-dac1f8f63013&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;Office365&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;So I needed a way to test a string for a valid GUID and only invoking the Graph calls for GUID values.&lt;/p&gt;

&lt;h3 class="relative group"&gt;Matching a GUID with a regex
 &lt;div id="matching-a-guid-with-a-regex" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#matching-a-guid-with-a-regex" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;I found the following regex on &lt;a href="https://pscustomobject.github.io/powershell/functions/PowerShell-Validate-Guid-copy" target="_blank" rel="noreferrer"&gt;this site&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;d815c3bc-9c49-4633-9d16-29808242d063&amp;#34;&lt;/span&gt; &lt;span class="o"&gt;-match&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;(?im)^[{(]?[0-9A-F]{8}[-]?(?:[0-9A-F]{4}[-]?){3}[0-9A-F]{12}[)}]?$&amp;#39;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 class="relative group"&gt;Matching a GUID with the .NET method
 &lt;div id="matching-a-guid-with-the-net-method" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#matching-a-guid-with-the-net-method" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;Instead of the complex regex we can invoke this nice .NET member method which returns true or false based on the input:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;guid&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;TryParse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;d815c3bc-9c49-4633-9d16-29808242d063&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vm"&gt;$&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="no"&gt;ref][guid&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;I guess that&amp;rsquo;s much more convenient.&lt;/p&gt;

&lt;h3 class="relative group"&gt;Helper Function
 &lt;div id="helper-function" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#helper-function" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;Here&amp;rsquo;s a helper function which can be used in PowerShell scripts:&lt;/p&gt;</description></item><item><title>Document Conditional Access Configuration with my Modern Workplace Concierge</title><link>https://tech.nicolonsky.ch/document-conditional-access-configuration/</link><pubDate>Mon, 20 Apr 2020 19:22:33 +0000</pubDate><guid>https://tech.nicolonsky.ch/document-conditional-access-configuration/</guid><description>&lt;p&gt;Documenting things sucks. If it involves a lot of klick(edi klack klack) in portals and copying information around even more. But there&amp;rsquo;s hope. And it&amp;rsquo;s called automation. For the Intune part Thomas Kurt did already an awesome job with his &lt;a href="https://github.com/ThomasKur/IntuneDocumentation" target="_blank" rel="noreferrer"&gt;IntuneDocumentation&lt;/a&gt;.  Now the &lt;a href="https://mwconcierge.azurewebsites.net/" target="_blank" rel="noreferrer"&gt;Modern Workplace Concierge&lt;/a&gt; is ready to help you with documenting your Conditional Access configuration. I promise you: we will get through this within under 15 minutes! Afterwards you can make an impression on your fellow Enterprise Mobility teammates.&lt;/p&gt;

&lt;h3 class="relative group"&gt;What&amp;rsquo;s inside?
 &lt;div id="whats-inside" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#whats-inside" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;A Conditional Access policy is returned by the Microsoft Graph API in the following JSON representation:&lt;/p&gt;
&lt;pre&gt;
&lt;code&gt;
{
 "id": "714b5737-5f13-415e-bf96-d659f3a5928e",
 "displayName": "PROD - Admin protection - Azure management: Require MFA",
 "createdDateTime": null,
 "modifiedDateTime": null,
 "state": "enabled",
 "grantControls": {
 "operator": "OR",
 "builtInControls": [
 "mfa"
 ],
 "customAuthenticationFactors": [],
 "termsOfUse": []
 },
 "conditions": {
 "signInRiskLevels": [],
 "clientAppTypes": [],
 "platforms": null,
 "locations": null,
 "deviceStates": null,
 "applications": {
 "includeApplications": [
 "797f4846-ba00-4fd7-ba43-dac1f8f63013"
 ],
 "excludeApplications": [],
 "includeUserActions": []
 },
 "users": {
 "includeUsers": [
 "All"
 ],
 "excludeUsers": [],
 "includeGroups": [],
 "excludeGroups": [
 "04988d96-ad01-4569-9aee-a199a1cb4f8e"
 ],
 "includeRoles": [],
 "excludeRoles": []
 }
 },
 "sessionControls": null
}
&lt;/code&gt;
&lt;/pre&gt;
&lt;p&gt;That&amp;rsquo;s not really human readable. Especially the object id&amp;rsquo;s  (32 character UUIDs) make it difficult to guess to which users or apps a policy is assigned. But an API has definitely other goals than showing pretty formatted reports.&lt;/p&gt;</description></item><item><title>I said Connect-AzureAD and not sign-out and re-sign-in!</title><link>https://tech.nicolonsky.ch/i-said-connect-azuread-and-not-sign-out-and-re-sign-in/</link><pubDate>Wed, 25 Mar 2020 17:21:25 +0000</pubDate><guid>https://tech.nicolonsky.ch/i-said-connect-azuread-and-not-sign-out-and-re-sign-in/</guid><description>&lt;p&gt;If you are using the &amp;ldquo;AzureAD&amp;rdquo; PowerShell module (also applies to the AzureADPreview) you have probably noticed that the &lt;em&gt;Connect-AzureAD&lt;/em&gt; Cmdlet ignores existing access tokens and initiates a new sign in to Azure AD even if you are already signed in.&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://tech.nicolonsky.ch/content/images/2020/03/image.png"&gt;&lt;figcaption&gt;Prompt you get when calling the "Connect-AzureAD" cmdlet&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;Long story short, I got annoyed every time when I accidentally recalled &lt;em&gt;Connect-AzureAD&lt;/em&gt; (mostly when working with Scripts)  until I found this amazing hint on &lt;a href="https://social.msdn.microsoft.com/Forums/sqlserver/en-US/386223c4-8821-415e-acea-68b47586131c/powershell-azuread-check-if-connection-is-established-with-connectazuread?forum=WindowsAzureAD" target="_blank" rel="noreferrer"&gt;technet&lt;/a&gt; and now I want to (re-)share it with you.&lt;/p&gt;
&lt;p&gt;In your PowerShell scripts simply use the following snippet to connect with Azure AD / check your connection and you wont get any sign-in prompts if you are already connected!&lt;/p&gt;
&lt;script src="https://gist.github.com/nicolonsky/798cfc9c0b5543647347cf09de6ef3c8.js"&gt;&lt;/script&gt;

&lt;h3 class="relative group"&gt;Reusing the access token for the MsOnline module
 &lt;div id="reusing-the-access-token-for-the-msonline-module" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#reusing-the-access-token-for-the-msonline-module" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;The Azure AD PowerShell access token which gets stored can also be used to connect to the MsOnline resources (because certain attributes like strong authentication details are not available with the AzureAD modules):&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$token&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;Microsoft.Open.Azure.AD.CommonLibrary.AzureSession&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;AccessTokens&lt;/span&gt; &lt;span class="nb"&gt;Connect-MsolService&lt;/span&gt; &lt;span class="n"&gt;-AccessToken&lt;/span&gt; &lt;span class="nv"&gt;$token&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;AccessToken&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AccessToken&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</description></item><item><title>Generate a report about assigned Azure Active Directory roles</title><link>https://tech.nicolonsky.ch/report-assigned-azure-ad-roles/</link><pubDate>Thu, 19 Mar 2020 20:42:07 +0000</pubDate><guid>https://tech.nicolonsky.ch/report-assigned-azure-ad-roles/</guid><description>&lt;p&gt;The Azure AD portal does not really provide an overview about all directory role assignments in your tenant. If you want to review existing Azure AD Directory roles a csv report will probably better server your needs. Therefore I created a PowerShell script to export the role assignments.&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://tech.nicolonsky.ch/content/images/2020/03/DirectoryRoles.png" class="kg-image"&gt;&lt;figcaption&gt;The Azure AD Portal only displays limited information about the assignments&lt;/figcaption&gt;&lt;/figure&gt;
### PowerShell Script
&lt;p&gt;Find the PowerShell script in my &lt;a href="https://github.com/nicolonsky/Techblog/blob/master/New-AzureADDirectoryRoleReport/New-AzureADDirectoryRoleReport.ps1" target="_blank" rel="noreferrer"&gt;techblog GitHub Repository&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Make sure that you have the AzureAD PowerShell module installed before running the script. You can install it by running &amp;ldquo;&lt;em&gt;Install-Module AzureAD&amp;rdquo;.&lt;/em&gt;&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://tech.nicolonsky.ch/content/images/2020/03/New-AzureADDirectoryRoleReport_RoleReport-2.png"&gt;&lt;figcaption&gt;PowerShell script output&lt;/figcaption&gt;&lt;/figure&gt;

&lt;h3 class="relative group"&gt;Report
 &lt;div id="report" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#report" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;The report contains three columns:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Role&lt;/strong&gt; (name of the directory role)
&lt;ul&gt;
&lt;li&gt;Note that the Global Administrator Role is represented as Company Administrator&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Member&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;If the role is assigned to a user its the UserPrincipalName&lt;/li&gt;
&lt;li&gt;If the role is assigned to a service principal its the display name with the Azure AD application ID in the brackets&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ObjectType&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;Indicates whether the role is assigned to user account or a service principal&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;&lt;img src="https://tech.nicolonsky.ch/content/images/2020/03/RoleReport.png"&gt;&lt;figcaption&gt;CSV file containing all assigned directory roles&lt;/figcaption&gt;&lt;/figure&gt;

&lt;h3 class="relative group"&gt;Comparing reports
 &lt;div id="comparing-reports" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#comparing-reports" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;You can compare two reports with the following PowerShell code:&lt;/p&gt;</description></item><item><title>Detect Deleted User Accounts in Azure Active Directory</title><link>https://tech.nicolonsky.ch/detect-deleted-user-accounts-in-azure-active-directory/</link><pubDate>Thu, 13 Feb 2020 08:30:46 +0000</pubDate><guid>https://tech.nicolonsky.ch/detect-deleted-user-accounts-in-azure-active-directory/</guid><description>&lt;p&gt;An account in your Azure Active Directory got deleted and you want to examine who initiated the delete action? Sounds very simple but if you do not want to search your logs manually things become a little bit trickier.&lt;/p&gt;

&lt;h3 class="relative group"&gt;The challenge
 &lt;div id="the-challenge" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#the-challenge" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;When a user gets deleted and you only remember it&amp;rsquo;s userPrincipalName you wont be able to to search for a match. And I doubt that you memorized the Azure AD object id of that user.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what the Azure AD Audit log shows us:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://tech.nicolonsky.ch/content/images/2020/02/Azure-AD-Deleted-User.png" &gt;&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Azure AD Audit Logs"
 src="https://tech.nicolonsky.ch/content/images/2020/02/Azure-AD-Deleted-User.png"
 &gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The userPrincipalName attribute will get the Azure AD object ID as prefix:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;userPrincipalName before deletion: &lt;a href="mailto:jane.doe@nicolonsky.ch" &gt;jane.doe@nicolonsky.ch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;userPrincipalName after deletion: &lt;a href="mailto:f5d7e17347594a658d124329b9b025abjane.doe@nicolonsky.ch" &gt;f5d7e17347594a658d124329b9b025abjane.doe@nicolonsky.ch&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;By having a closer look to the Azure Active Directory Audit logs you will notice that the filtering or search capabilities are limited in terms of searching for a specific target:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://tech.nicolonsky.ch/content/images/2020/02/Azure-AD-Deleted-User-Audit-Logs-Limited.png" &gt;&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Limited filtering capabilities in Azure AD"
 src="https://tech.nicolonsky.ch/content/images/2020/02/Azure-AD-Deleted-User-Audit-Logs-Limited.png"
 &gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Search is case-sensitive and only supports &amp;lsquo;starts with&amp;rsquo; operator&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;Which means we cannot search for the userPrincipalName. The only option in the Azure AD Audit Logs would be to download the logs and perform a search within a text editor which is not really feasible nor efficient.&lt;/p&gt;</description></item><item><title>Managing the new Microsoft Edge Browser with Intune</title><link>https://tech.nicolonsky.ch/managing-the-new-microsoft-edge-browser-with-intune/</link><pubDate>Mon, 03 Feb 2020 15:40:58 +0000</pubDate><guid>https://tech.nicolonsky.ch/managing-the-new-microsoft-edge-browser-with-intune/</guid><description>&lt;p&gt;With the availability of the new Edge browser based on chromium I gained the first experiences about configuring the browser in an enterprise environment. Of course I want to share those with you. This post hopefully helps you to roll-out and configure the new Edge Browser with Microsoft Intune.&lt;/p&gt;

&lt;h3 class="relative group"&gt;Install the new Edge Chromium with Intune
 &lt;div id="install-the-new-edge-chromium-with-intune" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#install-the-new-edge-chromium-with-intune" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;The installation of Edge is not the main topic of this post. The Edge browser is available in Intune as built-in app type like the Office 365 suite. More information about the installation process is available &lt;a href="https://docs.microsoft.com/en-us/intune/apps/apps-windows-edge" target="_blank" rel="noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;figure class="kg-card kg-image-card"&gt;&lt;img src="https://tech.nicolonsky.ch/content/images/2020/02/image-8.png" class="kg-image"&gt;&lt;/figure&gt;

&lt;h3 class="relative group"&gt;Set Edge Chromium as default browser
 &lt;div id="set-edge-chromium-as-default-browser" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#set-edge-chromium-as-default-browser" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;Default applications are configured on the Windows 10 operating system level via app associations. The current app associations of a device can be exported with dism and the command:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Dism /Online /Export-DefaultAppAssociations:&amp;quot;appassociations.xml&amp;quot;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Which will produce a file containing all associations. For setting Edge as the default browser this one is sufficient:&lt;/p&gt;
&lt;script src="https://gist.github.com/nicolonsky/57527e0344d26aa7a41920f9fbb5cdda.js"&gt;&lt;/script&gt;
&lt;p&gt;To deploy an app associations file with Intune it needs to be base64 encoded. I used the &lt;a href="https://www.base64encode.org" target="_blank" rel="noreferrer"&gt;base64encode online tool&lt;/a&gt;.&lt;/p&gt;
&lt;script src="https://gist.github.com/nicolonsky/9b362a520a98d5cba2871fd1a43a10ba.js"&gt;&lt;/script&gt;

&lt;h4 class="relative group"&gt;Intune configuration
 &lt;div id="intune-configuration" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#intune-configuration" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h4&gt;
&lt;p&gt;To distribute the default app association configure the following OMA-URI in a custom device configuration profile:&lt;/p&gt;</description></item><item><title>Prevent Intune devices from getting the Microsoft search (Bing) plugin</title><link>https://tech.nicolonsky.ch/prevent-intune-devices-from-getting-the-microsoft-search-bing-plugin/</link><pubDate>Fri, 24 Jan 2020 11:19:24 +0000</pubDate><guid>https://tech.nicolonsky.ch/prevent-intune-devices-from-getting-the-microsoft-search-bing-plugin/</guid><description>&lt;p&gt;Microsoft recently announced to install a Bing extension on new and existing Office 365 ProPlus installations which will set Bing as the default search engine starting with the first Office 365 ProPlus release in 2020 - not appreciated Microsoft and definitely not what customers want! The extension will be shipped for new Office installations and existing clients with Office 365 ProPlus installed when they update.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 11.02.2020: &amp;ldquo;&lt;/strong&gt; The Microsoft Search in Bing browser extension will not be automatically deployed with Office 365 ProPlus.&amp;rdquo; - I will keep this post for the archives.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Starting with Version 2002 of Office 365 ProPlus, an extension for Microsoft Search in Bing will be installed that makes Bing the default search engine for the Google Chrome web browser only on devices in certain &lt;a href="https://docs.microsoft.com/en-us/deployoffice/microsoft-search-bing#which-locations-will-receive-microsoft-search-in-bing-with-office-365-proplus" target="_blank" rel="noreferrer"&gt;locations&lt;/a&gt;. This extension will be installed with new installations of Office 365 ProPlus or when existing installations of Office 365 ProPlus are updated. (&lt;a href="https://docs.microsoft.com/en-us/deployoffice/microsoft-search-bing" target="_blank" rel="noreferrer"&gt;Reference&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;As expected date the 2002 release will be rolling out in March for the monthly update channel.&lt;/p&gt;
&lt;p&gt;More details are available under:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/deployoffice/microsoft-search-bing" target="_blank" rel="noreferrer"&gt;Microsoft Search in Bing and Office 365 ProPlus&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/deployoffice/microsoft-search-bing#which-locations-will-receive-microsoft-search-in-bing-with-office-365-proplus" target="_blank" rel="noreferrer"&gt;Affected locations&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;New Office installations
 &lt;div id="new-office-installations" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#new-office-installations" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;To avoid the plugin being installed with new office installations edit your Office 365 Configuration with the &lt;a href="https://config.office.com/officeSettings/configurations" target="_blank" rel="noreferrer"&gt;Office Customization Tool&lt;/a&gt; . Make sure to toggle the switch for &amp;ldquo;Set default search engine to Microsoft Search in Bing&amp;rdquo; to off:&lt;/p&gt;</description></item><item><title>Deploy fonts to Intune managed Windows 10 devices</title><link>https://tech.nicolonsky.ch/deploy-fonts-with-intune/</link><pubDate>Sun, 19 Jan 2020 16:25:21 +0000</pubDate><guid>https://tech.nicolonsky.ch/deploy-fonts-with-intune/</guid><description>&lt;p&gt;Recently a customer using Microsoft Intune requested to deploy a TrueType font required by one of their line of business apps. Because Intune does not offer a native solution to deploy fonts it was quite clear that a PowerShell script or Intune Win32 app should do the trick. Note that the mentioned PowerShell scripts can also be used for app deployments with Configuration Manager (MEMCM).&lt;/p&gt;

&lt;h3 class="relative group"&gt;How to install a font programmatically?
 &lt;div id="how-to-install-a-font-programmatically" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#how-to-install-a-font-programmatically" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;There seem to be &lt;a href="https://eddiejackson.net/wp/?p=16137" target="_blank" rel="noreferrer"&gt;multiple options&lt;/a&gt; depending on the operating system version. I&amp;rsquo;ve tested this with Windows 10 1909. And broke it down to the following steps:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Copy the font to the &amp;ldquo;C:\Windows\Fonts&amp;rdquo; folder&lt;/li&gt;
&lt;li&gt;Create a registry key which points to the filename of the *.ttf or *.otf font copied to the Windows font path&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;How to install a font with Intune?
 &lt;div id="how-to-install-a-font-with-intune" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#how-to-install-a-font-with-intune" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;To get the font to Windows 10 devices I created a PowerShell script which copies the font files to the windows-fonts folder and creates the required registry key.&lt;/p&gt;
&lt;p&gt;Deploying the PowerShell script as Intune Win32 app has the advantage that we can link the font as a dependency if any app requires a specific font. Additionally we can detect and uninstall the font if needed.&lt;/p&gt;</description></item><item><title>Connecting to foreign Intune tenants with Microsoft Graph and PowerShell</title><link>https://tech.nicolonsky.ch/connecting-to-foreign-intune-tenants-with-microsoft-graph-and-powershell/</link><pubDate>Thu, 09 Jan 2020 13:25:02 +0000</pubDate><guid>https://tech.nicolonsky.ch/connecting-to-foreign-intune-tenants-with-microsoft-graph-and-powershell/</guid><description>&lt;p&gt;If you manage multiple Intune tenants with your Azure AD account (invited as guest in the foreign tenant) we need a way to specify the tenant id we want to connect. Otherwise you will land in your home-tenant every time. This posts shows you how to accomplish that with the &lt;a href="https://github.com/microsoft/Intune-PowerShell-SDK" target="_blank" rel="noreferrer"&gt;Intune PowerShell SDK&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If we have a look at the default Graph settings in a PowerShell session with the Intune PowerShell SDK you will notice that all authentication requests will land on the /common endpoint.&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;Get-MSGraphEnvironment&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;AuthUrl&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="p"&gt;//&lt;/span&gt;&lt;span class="n"&gt;login&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;microsoftonline&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="n"&gt;common&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ResourceId&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="p"&gt;//&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;GraphBaseAddress&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="p"&gt;//&lt;/span&gt;&lt;span class="n"&gt;graph&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;com&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;AppId&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;d1ddf0e4-d672&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;4dae-b554&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;9d5bdfd93547&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;RedirectLink&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="n"&gt;urn&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ietf&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="n"&gt;wg&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="n"&gt;oauth&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="n"&gt;oob&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;SchemaVersion&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;To connect to a specific tenant we need to update the AuthUrl to contain the tenant id or any registered domain name of the target tenant before connecting:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;Update-MSGraphEnvironment&lt;/span&gt; &lt;span class="n"&gt;-AuthUrl&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://login.microsoftonline.com/nicolonsky.ch&amp;#34;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Afterewards you can connect to Microsoft Graph as usual:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;Connect-MSGraph&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;```&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Happy&lt;/span&gt; &lt;span class="n"&gt;Microsoft&lt;/span&gt; &lt;span class="nb"&gt;Graph-ing&lt;/span&gt; &lt;span class="n"&gt;with&lt;/span&gt; &lt;span class="n"&gt;multiple&lt;/span&gt; &lt;span class="n"&gt;tenants&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</description></item><item><title>Monitor Apple token expiration in Intune</title><link>https://tech.nicolonsky.ch/monitor-apple-token-expiration-in-intune/</link><pubDate>Sat, 04 Jan 2020 14:55:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/monitor-apple-token-expiration-in-intune/</guid><description>&lt;p&gt;Apple tokens for Mobile Device Management like APNS certificates, DEP and VPP tokens need a renewal every 365 days. When an APNS certificate has expired you are forced to re-enroll all of your MDM managed apple devices. To avoid any headaches I put together a few lines of PowerShell which monitor the expiration with Azure automation and send a notification to Microsoft teams or email.&lt;/p&gt;

&lt;h3 class="relative group"&gt;Script
 &lt;div id="script" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#script" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;The script is intended to run recurring on Azure automation. And I recommend to setup a schedule which runs the script once a week. The script checks the following apple tokens and triggers the teams notification if it expires in less than the configured number of days:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Push Notification certificate&lt;/li&gt;
&lt;li&gt;DEP (Device Enrollment Program) tokens&lt;/li&gt;
&lt;li&gt;VPP (Volume Purchase Program) tokens&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Hint&lt;/strong&gt; : You can setup multiple DEP and VPP tokens in your Intune tenant.&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://tech.nicolonsky.ch/content/images/2019/12/MessageCard-17.png"&gt;&lt;figcaption&gt;The triggered notification is delivered to Microsoft Teams as message card with some details about the token&lt;/figcaption&gt;&lt;/figure&gt;

&lt;h3 class="relative group"&gt;Prerequisites
 &lt;div id="prerequisites" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#prerequisites" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;In order to get the monitoring up and running you need at least:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Azure automation account (ideally with a service principal), &lt;a href="https://docs.microsoft.com/en-us/azure/automation/automation-quickstart-create-account" target="_blank" rel="noreferrer"&gt;if you need a guide to set up an automation account read follow this article&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;An incoming webhook for your Microsoft Teams team which will receive the notifications OR an email account to send mails&lt;/li&gt;
&lt;li&gt;The script from my &lt;a href="https://github.com/nicolonsky/Techblog/tree/master/IntuneMonitorAppleTokens" target="_blank" rel="noreferrer"&gt;Github techblog repository&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;Create a Microsoft Teams Webhook
 &lt;div id="create-a-microsoft-teams-webhook" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#create-a-microsoft-teams-webhook" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;Navigate to your desired teams channel which should receive the notifications and add a new incoming webhook:&lt;/p&gt;</description></item><item><title>Blogging year 2019 in numbers</title><link>https://tech.nicolonsky.ch/a-few-numbers-from-the-last-decade/</link><pubDate>Sat, 04 Jan 2020 14:53:14 +0000</pubDate><guid>https://tech.nicolonsky.ch/a-few-numbers-from-the-last-decade/</guid><description>&lt;p&gt;Most of the people out there blogging have recently published numbers and figures about 2019. Starting the new decade I also want to publish some figures about 2019 and wish you a happy and successful start into 2020.&lt;/p&gt;

&lt;h3 class="relative group"&gt;Blog
 &lt;div id="blog" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#blog" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;On my blog I tried to focus mainly on Enterprise Mobility + Security topics and shared some experiences and how-to&amp;rsquo;s about the modern workplace.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;28 blog posts published&lt;/li&gt;
&lt;li&gt;101'074 page visits&lt;/li&gt;
&lt;li&gt;04:08 (mm:ss) is the average time users spent on my site&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;Tools
 &lt;div id="tools" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#tools" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;I published two open source tools in 2019, both are available on GitHub and both of them support your Microsoft 365 based workplace:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The Modern Workplace Concierge is a helper tool to simplify Microsoft 365 configuration allowing bulk import and export operations. &lt;a href="https://github.com/nicolonsky/ModernWorkplaceConcierge" target="_blank" rel="noreferrer"&gt;Project URL&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The Intune Drive Mapping Generator creates PowerShell scripts to map your on premises file shares to Intune MDM managed devices. &lt;a href="https://github.com/nicolonsky/IntuneDriveMapping" target="_blank" rel="noreferrer"&gt;Project URL&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;More numbers
 &lt;div id="more-numbers" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#more-numbers" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;2 sessions on community events&lt;/li&gt;
&lt;li&gt;254 new followers on twitter&lt;/li&gt;
&lt;li&gt;423 commits on GitHub&lt;/li&gt;
&lt;li&gt;802 generated network drive mapping configurations (Intune Drive Mapping Generator)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;Final words
 &lt;div id="final-words" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#final-words" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;I really appreciate all the feedback and support I received from you and fellow readers. Also in 2020 I will try to blog as much as possible and giving the community something back while representing the message that even at a young age you can contribute to the community, share your knowledge end especially learn a lot because this is a lifelong and ongoing process.&lt;/p&gt;</description></item><item><title>Have you already started with Intune automation and Microsoft Graph?</title><link>https://tech.nicolonsky.ch/getting-started-with-workplace-automation/</link><pubDate>Thu, 19 Dec 2019 21:16:47 +0000</pubDate><guid>https://tech.nicolonsky.ch/getting-started-with-workplace-automation/</guid><description>&lt;p&gt;This post has the intention to give you an overview and starting point to automate things with the Microsoft Graph API and PowerShell. While having the focus on Intune and EM+S but the basics are also valid for other Microsoft services.&lt;/p&gt;

&lt;h3 class="relative group"&gt;The world is changing and so are you?
 &lt;div id="the-world-is-changing-and-so-are-you" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#the-world-is-changing-and-so-are-you" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;When talking about automation most people only think about some PowerShell code and scheduled tasks running on whatever box in an environment. But technology regarding Microsoft services and it&amp;rsquo;s automation possibilities have definitely evolved quickly. Automation can now be done with basically any scripting or programming language because Microsoft offers us the Microsoft Graph API. Although API (application program interface) sounds more like a developer term engineers should better get used to consuming API&amp;rsquo;s. As more and more services can be consumed as SaaS API&amp;rsquo;s are mostly offered for further data processing and automation.&lt;/p&gt;

&lt;h3 class="relative group"&gt;Microsoft Graph API
 &lt;div id="microsoft-graph-api" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#microsoft-graph-api" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;Microsoft describes it&amp;rsquo;s own Graph API as &amp;ldquo;Microsoft Graph is the gateway to data and intelligence in Microsoft 365&amp;rdquo;. Most of the API&amp;rsquo;s out there are built according the RESTful definition. A RESTful, also called REST API should implement the following operations (HTTP methods) to work with data:&lt;/p&gt;</description></item><item><title>Application based authentication with the Intune PowerShell SDK using a certificate</title><link>https://tech.nicolonsky.ch/azure-ad-application-based-authentication-with-intune-using-certificate/</link><pubDate>Tue, 10 Dec 2019 15:43:58 +0000</pubDate><guid>https://tech.nicolonsky.ch/azure-ad-application-based-authentication-with-intune-using-certificate/</guid><description>&lt;p&gt;As you might have noticed I have been doing quite a lot of automation stuff with Microsoft Graph for Intune and Azure AD. My preferred way to run PowerShell scripts which need to run on a regular basis is to use Azure automation. Unfortunately the official &amp;ldquo;Intune-PowerShell-SDK&amp;rdquo; does not support authentication with a client certificate. Therefore I updated the module and will show you how to use it with Azure automation.&lt;/p&gt;

&lt;h3 class="relative group"&gt;Why I don&amp;rsquo;t like client secrets
 &lt;div id="why-i-dont-like-client-secrets" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#why-i-dont-like-client-secrets" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;Azure automation brings us service principals (run as accounts) which simplify the access to Azure resources by providing an Azure AD app registration and certificates to authenticate against Azure AD. This provides more security and prevents the risk from having client secrets stored as plain text in scripts. Going with a client secret when having a nice certificate based authentication solution in place feels like making a step-backwards for me. This was the main reason why I decided to &amp;ldquo;upgrade&amp;rdquo; the Intune-PowerShell-SDK to support certificate based authentication.&lt;/p&gt;

&lt;h3 class="relative group"&gt;Why I love the Intune-PowerShell-SDK
 &lt;div id="why-i-love-the-intune-powershell-sdk" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#why-i-love-the-intune-powershell-sdk" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;This PowerShell SDK provides nice Cmdlets to do any kind of automation with Microsoft Graph, not only limited to Intune because it offers a helper cmdlets like:&lt;/p&gt;</description></item><item><title>Manage Azure AD group based licensing with PowerShell</title><link>https://tech.nicolonsky.ch/manage-azure-ad-group-based-licensing-with-powershell/</link><pubDate>Wed, 04 Dec 2019 14:39:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/manage-azure-ad-group-based-licensing-with-powershell/</guid><description>&lt;p&gt;Recently I needed to assign a lot of Microsoft licenses to different Azure AD groups. Unfortunately Microsoft does currently not offer a solution to do this (yet). Instead of giving up on this I decided to analyze what actually happens when you assign a license to a group in the Azure portal and found some actions going on within the hidden portal API. As an outcome I built a PowerShell module to manage Azure AD group based licensing assignments.&lt;/p&gt;
&lt;!--kg-card-begin: markdown--&gt;
&lt;blockquote&gt;&lt;p&gt;Full functionality for group-based licensing is available through the Azure portal, and currently PowerShell and Microsoft Graph support is limited to read-only operations.&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/azure/active-directory/users-groups-roles/licensing-ps-examples" target="_blank" rel="noreferrer"&gt;PowerShell and Graph examples for group-based licensing in Azure AD&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;&lt;!--kg-card-end: markdown--&gt;

&lt;h2 class="relative group"&gt;The PowerShell module
 &lt;div id="the-powershell-module" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#the-powershell-module" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;The PowerShell module uses the &amp;ldquo;main.iam.ad.ext.azure&amp;rdquo; API for the license operations and the AzureRM module to get an access token for the API. &lt;strong&gt;Please note that the mentioned API is not officially supported or documented&lt;/strong&gt;. Although the API is being used by the Azure Portal for settings you configure via the portal.&lt;/p&gt;
&lt;p&gt;Kudos to &lt;a href="https://www.lieben.nu/liebensraum/2018/03/set-intune-mdm-user-scope-to-all-using-powershell-and-hidden-api/" target="_blank" rel="noreferrer"&gt;Jos Lieben&lt;/a&gt; for his &amp;ldquo;pioneer work&amp;rdquo; documenting on how to get an access token for the API.&lt;/p&gt;</description></item><item><title>Export and import Intune and Conditional Access configuration</title><link>https://tech.nicolonsky.ch/export-and-import-intune-and-conditional-access-configuration/</link><pubDate>Tue, 03 Dec 2019 07:28:18 +0000</pubDate><guid>https://tech.nicolonsky.ch/export-and-import-intune-and-conditional-access-configuration/</guid><description>&lt;p&gt;With Microsoft Graph we have powerful automation and configuration management capabilities. To further simplify this process I built the &amp;ldquo;&lt;a href="https://mwconcierge.azurewebsites.net/" target="_blank" rel="noreferrer"&gt;Modern Workplace Concierge&amp;rdquo;&lt;/a&gt;.  It is an ASP.NET application which uses an Azure AD multi tenant app to access the Microsoft Graph API on behalf to perform export and import tasks. The project uses the Microsoft Graph Beta API to access your tenant&amp;rsquo;s data.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Modern Workplace Concierge
 &lt;div id="modern-workplace-concierge" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#modern-workplace-concierge" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;The &lt;a href="https://mwconcierge.azurewebsites.net/" target="_blank" rel="noreferrer"&gt;Modern Workplace Concierge&lt;/a&gt; allows you to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Import and export Intune configuration and settings&lt;/li&gt;
&lt;li&gt;Import and export Conditional Access policies&lt;/li&gt;
&lt;li&gt;Download OSD ready offline Autopilot profiles&lt;/li&gt;
&lt;li&gt;Download stored PowerShell scripts in Intune (as PowerShell)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This allows you to import your existing Intune and Conditional Access configuration in new tenants or demo tenants. The files in JSON format can be used for further processing or documentation.&lt;/p&gt;
&lt;p&gt;And this all via web browser no client side prerequisites or PowerShell code is required!&lt;/p&gt;
&lt;figure class="kg-card kg-image-card kg-card-hascaption"&gt;&lt;img src="https://tech.nicolonsky.ch/content/images/2019/12/MwConcierge.png" class="kg-image"&gt;&lt;figcaption&gt;The Modern Workplace Concierge&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;The project and more information is &lt;a href="https://github.com/nicolonsky/ModernWorkplaceConcierge" target="_blank" rel="noreferrer"&gt;available on GitHub&lt;/a&gt; feel free to provide feedback there.&lt;/p&gt;
&lt;figure class="kg-card kg-embed-card"&gt;&lt;blockquote class="twitter-tweet"&gt;
&lt;p lang="en" dir="ltr"&gt;That's how I backup my Intune configuration with the &lt;a href="https://twitter.com/hashtag/ModernWorkplaceConcierge?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#ModernWorkplaceConcierge&lt;/a&gt;. Curious? Give it a try. Of course also supporting imports .&lt;a href="https://t.co/30H8b0olLn"&gt;https://t.co/30H8b0olLn&lt;/a&gt; &lt;a href="https://t.co/g5X58l1e1i"&gt;pic.twitter.com/g5X58l1e1i&lt;/a&gt;&lt;/p&gt;— Nicola Suter (@nicolonsky) &lt;a href="https://twitter.com/nicolonsky/status/1201745635545952256?ref_src=twsrc%5Etfw"&gt;December 3, 2019&lt;/a&gt;
&lt;/blockquote&gt;
&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;/figure&gt;
&lt;p&gt;More Information:&lt;/p&gt;</description></item><item><title>Bulk update Windows Autopilot groupTags</title><link>https://tech.nicolonsky.ch/bulk-update-windows-autopilot/</link><pubDate>Sun, 01 Dec 2019 11:21:58 +0000</pubDate><guid>https://tech.nicolonsky.ch/bulk-update-windows-autopilot/</guid><description>&lt;p&gt;Recently I needed to change a couple of groupTags on existing Windows Autopilot devices. Because Windows Autopilot profiles have been assigned based on the groupTag. Of course I could have done this with the portal (check out the &lt;a href="https://devicemanagement.microsoft.com" target="_blank" rel="noreferrer"&gt;devicemanagement.microsoft.com&lt;/a&gt; portal if not done yet!) but I am definitely an automation fan when I need to do repetitive work.&lt;/p&gt;

&lt;h3 class="relative group"&gt;Portal view and property mapping
 &lt;div id="portal-view-and-property-mapping" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#portal-view-and-property-mapping" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;In the Intune portal the Group Tag field on an Autopilot device maps to the Azure AD device property &amp;ldquo;OrderID&amp;rdquo;.&lt;br&gt;
Dynamic Azure AD Groups to assign Autopilot profiles to devices can be built with the following membership rule:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(device.devicePhysicalIds -any _ -eq &amp;quot;[OrderID]:mOSD&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;img src="https://tech.nicolonsky.ch/content/images/2019/11/image.png" alt="Windows Autopilot Device"&gt;
&lt;p&gt;The &amp;ldquo;Order Identifier&amp;rdquo; field on an Autopilot device maps to the Azure AD device property &amp;ldquo;PurchaseOrderId&amp;rdquo;.&lt;br&gt;
Dynamic Azure AD Groups to assign Autopilot profiles to devices can be built with the following membership rule:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(device.devicePhysicalIds -any _ -eq &amp;quot;[PurchaseOrderId]:1234&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 class="relative group"&gt;PowerShell script to update groupTags
 &lt;div id="powershell-script-to-update-grouptags" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#powershell-script-to-update-grouptags" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;The following script updates the groupTag of one or multiple selected Autopilot devices. Selection is done with a PowerShell GridView.&lt;/p&gt;
&lt;p&gt;Please note:&lt;/p&gt;</description></item><item><title>Conditional Access and Azure Log Analytics in Harmony</title><link>https://tech.nicolonsky.ch/conditional-access-and-azure-log-analytics-in-harmony/</link><pubDate>Fri, 18 Oct 2019 22:06:04 +0000</pubDate><guid>https://tech.nicolonsky.ch/conditional-access-and-azure-log-analytics-in-harmony/</guid><description>&lt;p&gt;Auditing Conditional Access events and changes is crucial regarding your hygiene in Azure AD for your modern workplace. With the goal that we receive appropriate notifications and alerts if special events occur. Thanks to Azure Log Analytics (also referred to as Azure Monitor) we can easily filter and create alerts based on events. This post starts where most of the others end - giving you practical examples of KUSTO queries to search your Azure AD Audit logs with Log Analytics.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Default log retention in AAD
 &lt;div id="default-log-retention-in-aad" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#default-log-retention-in-aad" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;A point which get&amp;rsquo;s raised often is the default log retention in Azure Active Directory (AAD). Azure Active Directory stores all activity reports depending on your license for 7 or 30 days:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Azure AD Free and Basic: 7 days&lt;/li&gt;
&lt;li&gt;Azure AD Premium P1  and P2: 30 days&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="https://docs.microsoft.com/en-us/azure/active-directory/reports-monitoring/reference-reports-data-retention#how-long-does-azure-ad-store-the-data" target="_blank" rel="noreferrer"&gt;Source, more Information.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To retain and further process Azure Active Directory Audit Logs for a longer time period (because a 30 day audit trail is likely too short for most organizations) we can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Stream to an &lt;a href="https://azure.microsoft.com/en-in/services/event-hubs/" target="_blank" rel="noreferrer"&gt;Azure Event Hub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Archive to Blob Storage&lt;/li&gt;
&lt;li&gt;Forward them to Azure Log Analytics&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With Log Analytics the KUSTO query language can be used to query the forwarded log entries and we can create alert rules based on custom queries.&lt;/p&gt;</description></item><item><title>Unable to reset Windows Hello for Business PIN</title><link>https://tech.nicolonsky.ch/unable-to-reset-windows-hello-for-business-pin/</link><pubDate>Fri, 11 Oct 2019 16:12:14 +0000</pubDate><guid>https://tech.nicolonsky.ch/unable-to-reset-windows-hello-for-business-pin/</guid><description>&lt;p&gt;Recently I have been troubleshooting a nasty Windows Hello for Business problem which prevented all users in a tenant from resetting their Windows Hello for Business PIN&amp;rsquo;s on Azure AD joined devices while getting the error &lt;em&gt;CAA20004&lt;/em&gt;.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Issue
 &lt;div id="issue" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#issue" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;When clicking on &amp;ldquo;I forgot my PIN&amp;rdquo;:&lt;/p&gt;
&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="WHFB PIN RESET"
 src="https://tech.nicolonsky.ch/content/images/2019/10/Windows-Hello-forBusiness-ForgotPin.png"
 &gt;&lt;/figure&gt;
&lt;p&gt;After completing the account sign-in and MFA challenge the Error CAA20004 came up:&lt;/p&gt;
&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Windows Hello for Business Error CAA20004"
 src="https://tech.nicolonsky.ch/content/images/2019/10/Windows-Hello-forBusiness-PIN-Reset-Error.png"
 &gt;&lt;/figure&gt;

&lt;h2 class="relative group"&gt;Troubleshooting
 &lt;div id="troubleshooting" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#troubleshooting" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;The Azure AD Portal shows us &amp;ldquo;Failure reason: other&amp;rdquo;.&lt;/p&gt;
&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt=""
 src="https://tech.nicolonsky.ch/content/images/2019/10/Error-AAD.png"
 &gt;&lt;/figure&gt;
&lt;p&gt;While recording all the https traffic to Microsofts oauth2 endpoint with Fiddler this finally unveils usable information:&lt;/p&gt;
&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt=""
 src="https://tech.nicolonsky.ch/content/images/2019/10/Fiddler.png"
 &gt;&lt;/figure&gt;
&lt;blockquote&gt;&lt;p&gt;AADSTS65001: The user or administrator has not consented to use the application with ID &amp;rsquo; &lt;strong&gt;9115dd05-fad5-4f9c-acc7-305d08b1b04e&lt;/strong&gt;&amp;rsquo; named &amp;rsquo; &lt;strong&gt;Microsoft Pin Reset Client Production&lt;/strong&gt;&amp;rsquo;. Send an interactive authorization request for this user and resource.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;The error indicates that an application registration is missing in the tenant for the application &amp;ldquo;Microsoft Pin Reset Client Production&amp;rdquo;&lt;/p&gt;

&lt;h2 class="relative group"&gt;Solution
 &lt;div id="solution" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#solution" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;After a short search I found a matching &lt;a href="https://docs.microsoft.com/en-us/intune/remote-actions/device-windows-pin-reset" target="_blank" rel="noreferrer"&gt;Microsoft docs article&lt;/a&gt;. Instead of reading through the whole article the only thing I needed to do was consenthing to the: &lt;a href="https://login.windows.net/common/oauth2/authorize?response_type=code&amp;amp;client_id=b8456c59-1230-44c7-a4a2-99b085333e84&amp;amp;resource=https%3A%2F%2Fgraph.windows.net&amp;amp;redirect_uri=https%3A%2F%2Fcred.microsoft.com&amp;amp;state=e9191523-6c2f-4f1d-a4f9-c36f26f89df0&amp;amp;prompt=admin_consent" target="_blank" rel="noreferrer"&gt;Microsoft PIN Reset Service production&lt;/a&gt; application and also for the &lt;a href="https://login.windows.net/common/oauth2/authorize?response_type=code&amp;amp;client_id=9115dd05-fad5-4f9c-acc7-305d08b1b04e&amp;amp;resource=https%3A%2F%2Fcred.microsoft.com%2F&amp;amp;redirect_uri=ms-appx-web%3A%2F%2FMicrosoft.AAD.BrokerPlugin%2F9115dd05-fad5-4f9c-acc7-305d08b1b04e&amp;amp;state=6765f8c5-f4a7-4029-b667-46a6776ad611&amp;amp;prompt=admin_consent" target="_blank" rel="noreferrer"&gt;Microsoft PIN Reset Client production&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Intune export uploaded PowerShell scripts</title><link>https://tech.nicolonsky.ch/view-and-export-uploaded-intune-powershell-scripts/</link><pubDate>Wed, 09 Oct 2019 16:36:57 +0000</pubDate><guid>https://tech.nicolonsky.ch/view-and-export-uploaded-intune-powershell-scripts/</guid><description>&lt;p&gt;After you have uploaded a PowerShell script to the Intune portal you won&amp;rsquo;t be able to view the script or its content. Therefore things become complicated when an Intune tenant is managed by multiple admins and someone wants to update or review a script. In addition to the unknown script content things can go from bad to worse if you can&amp;rsquo;t find the script anymore. Fortunately we can recollect our PowerShell scripts directly from the Microsoft Graph API.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Taking advantage of the Intune-PowerShell-SDK
 &lt;div id="taking-advantage-of-the-intune-powershell-sdk" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#taking-advantage-of-the-intune-powershell-sdk" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://github.com/microsoft/Intune-PowerShell-SDK#one-time-setup-powershell-gallery" target="_blank" rel="noreferrer"&gt;Install the Intune-PowerShell-SDK&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/microsoft/Intune-PowerShell-SDK#before-this-module-is-used-in-your-organization" target="_blank" rel="noreferrer"&gt;Consent MS Graph App registration&lt;/a&gt; if not done yet (uses default Microsoft Intune PowerShell App with ID: d1ddf0e4-d672-4dae-b554-9d5bdfd93547 )&lt;/li&gt;
&lt;li&gt;Execute the snippet below&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 class="relative group"&gt;Retrieve device configuration - PowerShell scripts
 &lt;div id="retrieve-device-configuration---powershell-scripts" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#retrieve-device-configuration---powershell-scripts" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;!--kg-card-begin: markdown--&gt;&lt;script src="https://gist.github.com/nicolonsky/80c4d36d29999a15dd79ddb271ebd48f.js"&gt;&lt;/script&gt;&lt;!--kg-card-end: markdown--&gt;

&lt;h2 class="relative group"&gt;Final words
 &lt;div id="final-words" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#final-words" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;This was more a minimalistic self-serving post instead of a good explained one but it hopefully helps you if in need to export your PowerShell scripts in Intune without reinventing the wheel.&lt;/p&gt;</description></item><item><title>The Enrollment Status Page (ESP) and shared devices</title><link>https://tech.nicolonsky.ch/the-enrollment-status-page-and-shared-devices/</link><pubDate>Fri, 04 Oct 2019 14:44:10 +0000</pubDate><guid>https://tech.nicolonsky.ch/the-enrollment-status-page-and-shared-devices/</guid><description>&lt;p&gt;If you use the Enrollment Status Page (ESP) on your (Autopilot) devices in blocking mode (Block device use until all apps and profiles are installed) things can get ugly and complicated if you sign-in with another user account on that machine. So it might be better to disable the Enrollment Status Page for all users who sign-in after the initial device enrollment.&lt;/p&gt;

&lt;h2 class="relative group"&gt;ESP behaviour
 &lt;div id="esp-behaviour" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#esp-behaviour" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;I was not aware of the fact that only one ESP gets applied to a device and the first one applied will also remain on that device nevertheless if you configure additional ESP settings for different groups of users. In addition the ESP gets displayed for every account even if the account has no Intune license assigned and causing the ESP therefore to fail.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;The Enrollment Status Page can only be targeted to a user who belongs to an assigned group and the policy is set on the device at the time of enrollment for all users that use the device. &lt;a href="https://docs.microsoft.com/en-us/intune/windows-enrollment-status" target="_blank" rel="noreferrer"&gt;https://docs.microsoft.com/en-us/intune/windows-enrollment-status&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 class="relative group"&gt;Use cases from the field
 &lt;div id="use-cases-from-the-field" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#use-cases-from-the-field" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;I have came past the following use cases where you would want to disable the ESP after the initial enrollment:&lt;/p&gt;</description></item><item><title>Windows Autopilot failed to delete device records</title><link>https://tech.nicolonsky.ch/windows-autopilot-failed-to-delete-device-records/</link><pubDate>Sun, 29 Sep 2019 20:16:03 +0000</pubDate><guid>https://tech.nicolonsky.ch/windows-autopilot-failed-to-delete-device-records/</guid><description>&lt;p&gt;Recently I needed to delete a desktop machine from the Windows Autopilot service in order to use the machine in another tenant.  But the problem was that the Intune and Azure AD device objects were already deleted. All attempts taken within the Microsoft 365 Device Management and Intune Portal were unsuccessful.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Issue
 &lt;div id="issue" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#issue" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;Usually the autopilot device shows the associated Azure AD and Intune objects but here they were shown as N/A (not available) because they were already deleted.&lt;/p&gt;
&lt;img src="https://tech.nicolonsky.ch/content/images/2019/09/Stale-Autopilot-Device.png"&gt;
&lt;p&gt;Every attempt to delete the device produced the following error:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Device 8CC9082ZVE deletion failed. Please delete the associated Intune device before deleting this Autopilot device record.&lt;/p&gt;
&lt;/blockquote&gt;&lt;img src="https://tech.nicolonsky.ch/content/images/2019/09/Intune_AutoPilot_Device_Deletion_Failure---Copy.png"&gt;

&lt;h2 class="relative group"&gt;Solution
 &lt;div id="solution" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#solution" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;A quick visit to the Microsoft Store for Business resolved things because there I could delete the device without any issue. &lt;a href="https://businessstore.microsoft.com/" target="_blank" rel="noreferrer"&gt;Direct URL to the Microsoft Store for Business.&lt;/a&gt; After a sync in the Intune Autopilot Devices pane the device had also gone from the Intune portal.&lt;/p&gt;
&lt;img src="https://tech.nicolonsky.ch/content/images/2019/09/Autopilot-Microsoft-Store-for-business-1.png"&gt;

&lt;h2 class="relative group"&gt;Final words
 &lt;div id="final-words" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#final-words" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;This was a rather short post but I hope it prevents headache if you want to delete an Autopilot device with stale Azure AD / Intune records.&lt;/p&gt;</description></item><item><title>5 Ways to Screw Up Conditional Access</title><link>https://tech.nicolonsky.ch/5-ways-to-screw-up-conditional-access/</link><pubDate>Wed, 28 Aug 2019 08:34:02 +0000</pubDate><guid>https://tech.nicolonsky.ch/5-ways-to-screw-up-conditional-access/</guid><description>&lt;p&gt;Nowadays where cloud services are available from all over the world we cannot (only) rely on trusted networks and on identities protected by usernames and passwords. Conditional access allows you to define granular controls whether an identity can access cloud applications. Based on the positive feedback for my &amp;ldquo;&lt;a href="https://tech.nicolonsky.ch/5-ways-to-screw-up-your-intune-tenant/" &gt;5 Ways to Screw up your Intune Tenant&lt;/a&gt;&amp;rdquo; post I felt empowered to get conditional access covered as well.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Chose your platform wisely
 &lt;div id="chose-your-platform-wisely" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#chose-your-platform-wisely" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;If you intend to use the device platform filter make sure that you cover all platforms including unknown platforms. Otherwise your might have a lack in your battleship. &lt;a href="https://tech.nicolonsky.ch/bypassing-conditional-access-device-platform-policies/" &gt;Also note that platform detection is based on best effort and can be exploited&lt;/a&gt;.&lt;/p&gt;
&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Platform"
 src="https://tech.nicolonsky.ch/content/images/2019/08/conditional-access-device-platform.png"
 &gt;&lt;/figure&gt;

&lt;h2 class="relative group"&gt;Long live legacy
 &lt;div id="long-live-legacy" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#long-live-legacy" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;Mind the client apps configuration to ensure that your conditional access policies also apply to non-modern authentication clients. If you have created your conditional access policies in the early days of the product you didn&amp;rsquo;t have this option available.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Something that has created some confusion is that conditional access policies don&amp;rsquo;t include legacy authentication clients by default, this means that if you have a conditional access policy enforcing MFA for all users and all cloud apps, it doesn&amp;rsquo;t block legacy authentication clients (or &amp;ldquo;Other clients&amp;rdquo;, as the CA UI refers to them) - Sue Bohn, Microsoft&lt;/p&gt;</description></item><item><title>Windows Autopilot White Glove Field Notes</title><link>https://tech.nicolonsky.ch/windows-autopilot-white-glove-field-notes/</link><pubDate>Wed, 14 Aug 2019 16:38:31 +0000</pubDate><guid>https://tech.nicolonsky.ch/windows-autopilot-white-glove-field-notes/</guid><description>&lt;p&gt;I&amp;rsquo;m happy to share some field notes and experiences with the Windows Autopilot White Glove feature which is available with the Windows 10 1903 release. I&amp;rsquo;ve done a lot of testing and engineering for a recent project which also included this brand new feature.&lt;/p&gt;

&lt;h2 class="relative group"&gt;First things first (requirements)
 &lt;div id="first-things-first-requirements" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#first-things-first-requirements" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;This is probably the most important information of this post. Really make sure to verify the following prerequisites for Autopilot White Glove. Because there are additional requirements compared to Autopilot enrollments.&lt;/p&gt;

&lt;h3 class="relative group"&gt;Basic Autopilot
 &lt;div id="basic-autopilot" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#basic-autopilot" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;Make sure that a &amp;ldquo;classical&amp;rdquo; Autopilot Deployment is working properly without any issues.&lt;/p&gt;

&lt;h3 class="relative group"&gt;Hardware and OS
 &lt;div id="hardware-and-os" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#hardware-and-os" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Hardware with support for device Attestation (&amp;ldquo;Physical devices that support TPM 2.0 and device attestation; virtual machines are not supported.&amp;rdquo;)&lt;/li&gt;
&lt;li&gt;Physical devices with Ethernet connectivity (WiFi connectivity is not supported!)&lt;/li&gt;
&lt;li&gt;Windows 10, version 1903 with &lt;a href="https://support.microsoft.com/help/4505903" target="_blank" rel="noreferrer"&gt;KB4505903&lt;/a&gt; injected (equals OS Build 18362.267)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;Starting the white glove adventure
 &lt;div id="starting-the-white-glove-adventure" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#starting-the-white-glove-adventure" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;Preparing Windows 10 1903
 &lt;div id="preparing-windows-10-1903" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#preparing-windows-10-1903" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;As mentioned by Michael Niehaus Windows multiple Autopilot issues were fixed by &lt;a href="https://support.microsoft.com/help/4505903" target="_blank" rel="noreferrer"&gt;KB4505903&lt;/a&gt;. So we need to inject this cumulative update to the downloaded source. This was already the first hurdle to overcome because &lt;em&gt;I&amp;rsquo;ve missed the fact that the Windows Setup (install.wim) actually contained multiple image indexes (yeah it&amp;rsquo;s kinda embarrassing)&lt;/em&gt;. We achieve this by using dism offline servicing with &lt;strong&gt;PowerShell&lt;/strong&gt; cmdlets.&lt;/p&gt;</description></item><item><title>Windows Autopilot White Glove Error 0x81036501</title><link>https://tech.nicolonsky.ch/windows-autopilot-white-glove-error-0x81036501/</link><pubDate>Thu, 08 Aug 2019 16:58:05 +0000</pubDate><guid>https://tech.nicolonsky.ch/windows-autopilot-white-glove-error-0x81036501/</guid><description>&lt;p&gt;While testing Autopilot White glove for a customer project my test machines always got stuck within the &amp;ldquo;Registering your device for mobile management&amp;rdquo; step and timed out after 12 minutes and returned the error &amp;ldquo;0x81036501&amp;rdquo; just before showing the White Glove Failed screen. I was doing my tests with Windows 10 1903 DE (German) with the most recent cumulative update installed, meaning OS build: 18362.267.&lt;/p&gt;

&lt;h2 class="relative group"&gt;The Issue
 &lt;div id="the-issue" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#the-issue" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;As normal Autopilot enrollments were working like a charm this one had to be related to the White Glove scenario. Here&amp;rsquo;s a screen capture showing the actual behavior (unfortunately with German display language):&lt;/p&gt;
&lt;figure class="kg-card kg-image-card"&gt;&lt;img src="https://tech.nicolonsky.ch/content/images/2019/08/AutoPilotWhiteGlove-1.gif" class="kg-image"&gt;&lt;/figure&gt;
&lt;p&gt;By pressing [shift] + [F10] i opened a command prompt and launched the event viewer (eventvwr.msc). In the &amp;ldquo;&lt;em&gt;Microsoft-Windows-ModernDeployment-Diagnostics-Provider/Autopilot&lt;/em&gt;&amp;rdquo; event log I found the following error popping up multiple times, including a retry attempt and limit:&lt;/p&gt;
&lt;!--kg-card-begin: markdown--&gt;
&lt;p&gt;&lt;code&gt;Autopilot discovery failed to find a valid MDM. Confirm that the AAD tenant is properly provisioned and licensed for exactly one MDM. HRESULT = 0x81036501&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;AutopilotManager failed during device enrollment phase DeviceDiscovery. HRESULT = 0x81036501&lt;/code&gt;&lt;/p&gt;
&lt;!--kg-card-end: markdown--&gt;
&lt;p&gt;On the enrollment status page the error &amp;ldquo;0x81036501&amp;rdquo; got displayed for like one second before showing the red generic Autopilot White glove error screen.&lt;/p&gt;</description></item><item><title>Intune Win32 app requirements deep dive</title><link>https://tech.nicolonsky.ch/intune-win32-app-requirements-deep-dive/</link><pubDate>Mon, 05 Aug 2019 17:09:02 +0000</pubDate><guid>https://tech.nicolonsky.ch/intune-win32-app-requirements-deep-dive/</guid><description>&lt;p&gt;The Intune Win32 app requirements feature is quite underrated and often overseen in my experience. The ability to specify a custom PowerShell scripts allow us to check for specific hardware or device properties in order to determine if an app or firmware update should be installed or not. So there&amp;rsquo;s no need to build multiple and complex dynamic Azure AD groups for the assignment of your apps.&lt;/p&gt;

&lt;h3 class="relative group"&gt;Use cases from the field
 &lt;div id="use-cases-from-the-field" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#use-cases-from-the-field" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;From recent projects I&amp;rsquo;ve discovered the following use cases to deploy Win32 apps only to specific hardware types:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Install specific device drivers or hardware vendor&amp;rsquo;s software which is not available within the Windows update catalog  (e.g. hotkey features, firmware updates)&lt;/li&gt;
&lt;li&gt;Install a VPN client only on notebooks and tablets (e.g. Palo Alto GlobalProtect Client)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;Win32 app requirements
 &lt;div id="win32-app-requirements" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#win32-app-requirements" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;Intune Win32 app requirements are evaluated by the Intune Management Extension to check if a device fulfills defined requirements for an application installation. Requirements support both built-in and custom rules.&lt;/p&gt;

&lt;h3 class="relative group"&gt;Built-in rules
 &lt;div id="built-in-rules" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#built-in-rules" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;Wit the built-in capabilities we can check for:&lt;/p&gt;</description></item><item><title>5 Ways to Screw up your Intune Tenant</title><link>https://tech.nicolonsky.ch/5-ways-to-screw-up-your-intune-tenant/</link><pubDate>Wed, 31 Jul 2019 06:40:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/5-ways-to-screw-up-your-intune-tenant/</guid><description>&lt;p&gt;Here are 5 common recommendations based on misconfigurations I&amp;rsquo;ve came across in the field which will give your Intune tenant and devices a hard time to work smoothly. So better read this post that you not screw up your Intune tenant and maybe take advantage of the experiences others already gained.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Housekeeping
 &lt;div id="housekeeping" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#housekeeping" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s important to know which devices are actually being used and usually a nice addition to understand compliance data. Stale device entries in may give you a wrong impression of your Intune tenant and it&amp;rsquo;s health. So enable the automatic device cleanup rule to remove the enrolled device from Intune. Additionally you may also remove the device entries stored in Azure Active Directory (&lt;a href="https://tech.nicolonsky.ch/clean-up-azure-ad-devices/" target="_blank" rel="noreferrer"&gt;I created a little on-demand script for this which can also run in azure automation&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Same applies to registered Autopilot devices. E.g. if you allow your employees to buy their old devices from the company if they get a new one make sure to remove the device from the Autopilot service. Otherwise you&amp;rsquo;ll see it again popping up in your tenant very soon. Thus it also prevents the device from being registered in another tenant as autopilot device.&lt;/p&gt;</description></item><item><title>Automating network drive mapping configuration with Intune</title><link>https://tech.nicolonsky.ch/next-level-network-drive-mapping-with-intune/</link><pubDate>Fri, 19 Jul 2019 07:32:46 +0000</pubDate><guid>https://tech.nicolonsky.ch/next-level-network-drive-mapping-with-intune/</guid><description>&lt;p&gt;I&amp;rsquo;m thrilled to introduce the &lt;a href="https://intunedrivemapping.azurewebsites.net/DriveMapping" target="_blank" rel="noreferrer"&gt;intune-drive-mapping-generator&lt;/a&gt; which creates PowerShell scripts to map network drives with Intune. The tool is open source and built on ASP.NET Core MVC.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://intunedrivemapping.azurewebsites.net/DriveMapping" target="_blank" rel="noreferrer"&gt;&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="intune-drivemapping-generator"
 src="https://tech.nicolonsky.ch/content/images/2019/07/intune-drivemapping-generator.png"
 &gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The intune-drive-mapping-generator is your tool of choice to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Generate an Intune PowerShell script to map network drives on Azure AD joined devices&lt;/li&gt;
&lt;li&gt;Seamlessly migrate existing network drive mapping group policies&lt;/li&gt;
&lt;li&gt;Generate a network drive mapping configuration from scratch&lt;/li&gt;
&lt;li&gt;Use an existing Active Directory group as a filter to deploy all your drive mapping configurations within one script&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;This all happens without scripting effort. You receive a fully functional PowerShell script for the deployment with Intune.&lt;/em&gt;&lt;/p&gt;

&lt;h2 class="relative group"&gt;Architecture
 &lt;div id="architecture" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#architecture" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;This tool is designed to work best with the following components although it can be useful for other purposes(?) :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Azure AD Joined and Intune enrolled Windows 10 devices&lt;/li&gt;
&lt;li&gt;Synced user account from Active Directory to Azure Active Directory (Azure AD Connect)&lt;/li&gt;
&lt;li&gt;On-premises file servers&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;Howto
 &lt;div id="howto" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#howto" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;Export existing group policy
 &lt;div id="export-existing-group-policy" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#export-existing-group-policy" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;To convert your existing drive mapping group policy configuration, save the GPO as XML report with the group policy management console.&lt;/p&gt;</description></item><item><title>Creating desktop shortcuts with Intune</title><link>https://tech.nicolonsky.ch/intune-create-desktop-shortcut/</link><pubDate>Tue, 09 Jul 2019 23:22:24 +0000</pubDate><guid>https://tech.nicolonsky.ch/intune-create-desktop-shortcut/</guid><description>&lt;p&gt;Why want you to create desktop shortcuts with Intune? Business specific apps may require special shortcuts in order to launch the application with the right parameters. Or you need to create a shortcut for an application which is stored on your on premises fileserver. For this purpose I created a little solution which closes the gap between the modern cloud and on premises world. In comparison with other solutions this one works if you have redirected the users desktop with OneDrive Known Folder Move and automatically remediates missing shortcuts if they got deleted.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/nicolonsky/Techblog/tree/master/IntuneShortcut" target="_blank" rel="noreferrer"&gt;Direct link to the GitHub repository.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Browser links:&lt;/strong&gt; Instead of placing shortcuts to websites on the desktop I would recommend you to use managed bookmarks which can be directly provisioned within the web browser. I documented this for the new Microsoft Edge based on chromium &lt;a href="https://tech.nicolonsky.ch/managing-the-new-microsoft-edge-browser-with-intune/#provision-managed-favorites" &gt;here&lt;/a&gt;.
{: .notice}&lt;/p&gt;

&lt;h2 class="relative group"&gt;Features
 &lt;div id="features" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#features" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;This solution works when the desktop is redirected with OneDrive Known Folder Move&lt;/li&gt;
&lt;li&gt;Everything is user based (local userprofile)&lt;/li&gt;
&lt;li&gt;If the shortcut is missing or deleted it gets automatically (re)created&lt;/li&gt;
&lt;li&gt;Possibility to remove shortcut via Intune Win32 app uninstall&lt;/li&gt;
&lt;li&gt;Shortcut can point to: URL, File (UNC) or Folder (UNC)&lt;/li&gt;
&lt;li&gt;Ability to pass shortcut arguments&lt;/li&gt;
&lt;li&gt;Ability to specify shortcut icon (UNC/URL)&lt;/li&gt;
&lt;li&gt;Ability to deploy shortcut together with an app using Intune Win32 app dependencies&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;Architecture
 &lt;div id="architecture" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#architecture" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;A simple PowerShell script which does all the shortcut stuff is wrapped as Intune Win32 App. This adds possibility to detect the presence of the shortcut and if required to uninstall it with Intune. In order to work with the redirected desktop to OneDrive with Known Folder Move we can take advantage of the &lt;code&gt;[Environment]::GetFolderPath(&amp;quot;Desktop&amp;quot;)&lt;/code&gt; method to resolve the desktop location. Based on the Win32 app configuration the shortut get&amp;rsquo;s either created on the users personal desktop or on the allusers desktop.&lt;/p&gt;</description></item><item><title>Bypassing Conditional Access Device Platform Policies</title><link>https://tech.nicolonsky.ch/bypassing-conditional-access-device-platform-policies/</link><pubDate>Tue, 02 Jul 2019 17:12:06 +0000</pubDate><guid>https://tech.nicolonsky.ch/bypassing-conditional-access-device-platform-policies/</guid><description>&lt;p&gt;Recently I read &lt;a href="https://techcommunity.microsoft.com/t5/Azure-Active-Directory-Identity/Azure-AD-Mailbag-Conditional-Access-Q-amp-A/ba-p/566492" target="_blank" rel="noreferrer"&gt;a great article from the Microsoft IAM Director Sue Bohn&lt;/a&gt; concerning a Conditional Access Q&amp;amp;A. One question was about the device platform feature - which let&amp;rsquo;s you apply a policy only to a specific device platform like iOS, Android or Windows 10.&lt;/p&gt;
&lt;p&gt;The detection of the device platform relies on the user agent string sent by the application or web browser. Because this one can be spoofed easily better configure your Conditional Access policies wisely.&lt;/p&gt;

&lt;h2 class="relative group"&gt;The problem
 &lt;div id="the-problem" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#the-problem" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;As soon as you enable the device platform selection there&amp;rsquo;s the chance that a user doesn&amp;rsquo;t catch any Conditional Access policy.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;As a result, you should &lt;u&gt;not rely&lt;/u&gt; on the User Agent String to be present or to be accurate. Most browsers have a function to set an arbitrary User Agent String for testing purposes. (Microsoft)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 class="relative group"&gt;Bypass example
 &lt;div id="bypass-example" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#bypass-example" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;To give you an example, here&amp;rsquo;s a little walk-through:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Conditional Access Policy configured for all cloud apps&lt;/li&gt;
&lt;li&gt;Windows 10 selected as device platform&lt;/li&gt;
&lt;li&gt;Access control: Block&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class="kg-card kg-image-card"&gt;&lt;img src="https://tech.nicolonsky.ch/content/images/2019/07/conditional-access-policy.png" class="kg-image"&gt;&lt;/figure&gt;
&lt;p&gt;If we now try to access the azure portal with a Windows 10 app or browser we get the following result:&lt;/p&gt;</description></item><item><title>Calling the Microsoft Graph API via PowerShell without a user</title><link>https://tech.nicolonsky.ch/calling-the-microsoft-graph-api/</link><pubDate>Mon, 17 Jun 2019 18:47:47 +0000</pubDate><guid>https://tech.nicolonsky.ch/calling-the-microsoft-graph-api/</guid><description>&lt;p&gt;A colleague recently asked me how to access the Microsoft Graph API using PowerShell without specifying his user account or credentials. So here&amp;rsquo;s a little post about the required configuration to authenticate against the OAuth 2.0 endpoint of Azure AD with an app registration. This is especially useful for automation services like Azure automation.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://tech.nicolonsky.ch/calling-the-microsoft-graph-api/#powershell-template" &gt;At the end of this post you&amp;rsquo;ll find a PowerShell template.&lt;/a&gt;&lt;/p&gt;

&lt;h2 class="relative group"&gt;Gather application information
 &lt;div id="gather-application-information" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#gather-application-information" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;Create a new client secret for your app and note down the following values:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Client Secret&lt;/li&gt;
&lt;li&gt;Application ID (client ID)&lt;/li&gt;
&lt;li&gt;Directory ID (tenant ID)&lt;/li&gt;
&lt;/ul&gt;
&lt;figure class="kg-card kg-image-card kg-card-hascaption"&gt;&lt;img src="https://tech.nicolonsky.ch/content/images/2019/06/image-1.png" class="kg-image"&gt;&lt;figcaption&gt;Azure AD App registration&lt;/figcaption&gt;&lt;/figure&gt;
## PowerShell code

&lt;h3 class="relative group"&gt;Request authentication token
 &lt;div id="request-authentication-token" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#request-authentication-token" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;In order to use the Graph API we need an authentication token. The information we gathered before is now sent to the Azure AD OAuth 2.0 endpoint.&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://login.microsoftonline.com/{TenantID}/oauth2/v2.0/token&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;In the request supply a body with the following content:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$body&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="vm"&gt;@&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;client_id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;8f9f420d-606c-4e13-889e-837072dbfb42&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;client_secret&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;BlaBlaExampleSecret&amp;#34;&lt;/span&gt; &lt;span class="c"&gt;#Generated secret&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;https://graph.microsoft.com/.default&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;grant_type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;client_credentials&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The &lt;em&gt;scope&lt;/em&gt; and &lt;em&gt;grant_type&lt;/em&gt; are required attributes. A full example looks like:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$body&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="vm"&gt;@&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;client_id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;8f9f420d-606c-4e13-889e-837072dbfb42&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;client_secret&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;BlaBlaExampleSecret&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;https://graph.microsoft.com/.default&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;grant_type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;client_credentials&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$tenantId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;7955e1b3-cbad-49eb-9a84-e14aed7f3400&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;Invoke-WebRequest&lt;/span&gt; &lt;span class="n"&gt;-Uri&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;https://login.microsoftonline.com/&lt;/span&gt;&lt;span class="nv"&gt;$tenantId&lt;/span&gt;&lt;span class="s2"&gt;/oauth2/v2.0/token&amp;#34;&lt;/span&gt; &lt;span class="n"&gt;-ContentType&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;application/x-www-form-urlencoded&amp;#34;&lt;/span&gt; &lt;span class="n"&gt;-Body&lt;/span&gt; &lt;span class="nv"&gt;$body&lt;/span&gt; &lt;span class="n"&gt;-Method&lt;/span&gt; &lt;span class="n"&gt;Post&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;If everything works we receive an access token object as HTML 200/ok response:&lt;/p&gt;</description></item><item><title>Mastering Windows Hello for Business with your hybrid Identity</title><link>https://tech.nicolonsky.ch/mastering-windows-hello-for-business-with-your-hybrid-identity/</link><pubDate>Sun, 09 Jun 2019 18:07:32 +0000</pubDate><guid>https://tech.nicolonsky.ch/mastering-windows-hello-for-business-with-your-hybrid-identity/</guid><description>&lt;p&gt;I had the honor to deploy Windows Hello for Business several times for customers transitioning to a modern workplace using Azure AD and Microsoft Intune to manage their Windows 10 devices - combined with hybrid user identities. Now I want to share the most common hurdles and my experiences with you.&lt;/p&gt;
&lt;p&gt;Just to make sure that you have the modern mindset - here&amp;rsquo;s a little quote to reconsider your hybrid strategy (if not already done):&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;You don&amp;rsquo;t need a Hybrid Azure AD join for your Windows 10 devices. Be brave and don&amp;rsquo;t be afraid and switch to an Azure AD join. It will  simplify your device management and significantly reduce the complexity.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 class="relative group"&gt;Why additional configuration is required
 &lt;div id="why-additional-configuration-is-required" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#why-additional-configuration-is-required" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;To access on premise resources  who rely on Active Directory (file shares, applications) kerberos is used as authentication protocol. If you have Azure AD connect in place and a user sign&amp;rsquo;s in with his hybrid Identity using a password to a Windows 10 device which is Azure AD joined he automatically receives the required kerberos tickets if he wants to access resources.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;But&lt;/strong&gt; if the sign-in happens with Windows Hello for Business credentials (pin, biometrics) the authentication flow get&amp;rsquo;s interrupted because whether the domain controller (if it&amp;rsquo;s not a Windows Server 2016 DC) or the client can verify the integrity of each other.&lt;/p&gt;</description></item><item><title>Onboard macOS to Microsoft Defender ATP with Microsoft Intune</title><link>https://tech.nicolonsky.ch/onboard-macos-to-windows-defender-atp-with-microsoft-intune/</link><pubDate>Thu, 23 May 2019 14:23:57 +0000</pubDate><guid>https://tech.nicolonsky.ch/onboard-macos-to-windows-defender-atp-with-microsoft-intune/</guid><description>&lt;p&gt;Microsoft Defender ATP (MDATP)  for macOS hit finally the public preview status. We can now protect our macOS endpoints with cloud based power. I created a little guide about the onboarding process with Microsoft Intune and the user experience.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Prerequisites
 &lt;div id="prerequisites" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#prerequisites" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;From a macOS endpoint perspective:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;macOS version 10.12 (Sierra) or newer&lt;/li&gt;
&lt;li&gt;No third party endpoint protection installed&lt;/li&gt;
&lt;li&gt;At least 1GB of free disk space&lt;/li&gt;
&lt;li&gt;macOS client enrolled in your Intune tenant&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you want to enable macOS enrollment for your Intune tenant - &lt;a href="https://tech.nicolonsky.ch/enroll-macos-to-microsoft-intune/" target="_blank" rel="noreferrer"&gt;I&amp;rsquo;ve written a post about the enrollment process&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;From a Microsoft 365 perspective:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Microsoft Defender ATP license (Windows 10 Enterprise E5)&lt;/li&gt;
&lt;li&gt;Intune tenant wit macOS enrollment enabled&lt;/li&gt;
&lt;li&gt;Access to the Microsoft Defender Security Center&lt;/li&gt;
&lt;li&gt;Appropriate user rights to create and assign an Intune device configuration, LOB App&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This post assumes that you perform the tasks and file preparation on a macOS machine.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Preparing the onboarding package and files
 &lt;div id="preparing-the-onboarding-package-and-files" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#preparing-the-onboarding-package-and-files" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://securitycenter.windows.com/" target="_blank" rel="noreferrer"&gt;Access the Microsoft Defender Security Center&lt;/a&gt; and gather the installation and onboarding package:&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://tech.nicolonsky.ch/content/images/2019/05/onboarding-package.png"&gt;&lt;/figure&gt;
&lt;p&gt;To deploy the installation package with Microsoft Intune we need the Intune app wrapping tool for macOS which is available &lt;a href="https://github.com/msintuneappsdk/intune-app-wrapping-tool-mac" target="_blank" rel="noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Enroll macOS devices to Microsoft Intune</title><link>https://tech.nicolonsky.ch/enroll-macos-to-microsoft-intune/</link><pubDate>Thu, 23 May 2019 14:22:05 +0000</pubDate><guid>https://tech.nicolonsky.ch/enroll-macos-to-microsoft-intune/</guid><description>&lt;p&gt;As Microsoft starts to empower the integration for non Windows devices and also the available apps for macOS devices you might want to profit from your existing MDM solution of choice (Microsoft Intune) and enable features like conditional access or Windows Defender ATP on your  macOS devices. This post covers the enrollment with the company portal app. If you want to enroll your devices with DEP (device enrollment program) you can find a great guide &lt;a href="https://www.robinhobo.com/how-to-configure-apple-dep-within-microsoft-intune-and-migrate-existing-dep-devices-from-another-mdm-solution-to-microsoft-intune/" target="_blank" rel="noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;!--kg-card-begin: markdown--&gt;

&lt;h2 class="relative group"&gt;Mind the enrollment restrictions
 &lt;div id="mind-the-enrollment-restrictions" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#mind-the-enrollment-restrictions" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s start and check the configured enrollment restrictions to make sure that the macOS enrollment is not blocked for your tenant. You&amp;rsquo;ll find them on your Intune dashboard under: Microsoft Intune &amp;gt; Device enrollment - Enrollment restrictions&lt;/p&gt;
&lt;!--kg-card-end: markdown--&gt;&lt;figure class="kg-card kg-image-card kg-card-hascaption"&gt;&lt;img src="https://tech.nicolonsky.ch/content/images/2019/05/enrolment-restrictions.png" class="kg-image"&gt;&lt;figcaption&gt;Intune enrollment restrictions&lt;/figcaption&gt;&lt;/figure&gt;&lt;!--kg-card-begin: markdown--&gt;

&lt;h2 class="relative group"&gt;Get an Apple MDM push certificate
 &lt;div id="get-an-apple-mdm-push-certificate" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#get-an-apple-mdm-push-certificate" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;Without loosing into details - you need an Apple MDM push certificate (also called APNs) to manage apple devices with MDM. The push certificate allows your MDM solution to send notifications about device actions to your end devices (e.g. wipe, app installation, new policy). To request a push certificate you need a valid Apple ID.&lt;/p&gt;</description></item><item><title>Intune configure lid close action</title><link>https://tech.nicolonsky.ch/intune-lid-close-action/</link><pubDate>Sun, 19 May 2019 19:08:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/intune-lid-close-action/</guid><description>&lt;p&gt;When using your notebooks and portable devices together with a docking station your users might like to close the lid. The Windows 10 1903 release &lt;a href="https://docs.microsoft.com/en-us/windows/client-management/mdm/new-in-windows-mdm-enrollment-management#whats-new-in-mdm-for-windows-10-version-1903" target="_blank" rel="noreferrer"&gt;introduces additional power CSP settings&lt;/a&gt;. One of them allows you to configure the lid close action while on ac power - so the device doesn&amp;rsquo;t switch to hibernate mode as by default.&lt;/p&gt;

&lt;h1 class="relative group"&gt;Policy CSP configuration
 &lt;div id="policy-csp-configuration" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#policy-csp-configuration" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h1&gt;
&lt;p&gt;To configure this policy with Microsoft Intune use the following OMA-URI configuration within a new custom device configuration:&lt;/p&gt;
&lt;p&gt;| Name | SelectLidCloseActionPluggedIn |
| Description | Action that Windows takes when a user closes the lid on a mobile PC. |
| OMA-URI | ./Device/Vendor/MSFT/Policy/Config/Power/SelectLidCloseActionPluggedIn |
| Data type | Integer |
| Value | 0 |&lt;/p&gt;
&lt;p&gt;Other possible values are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;0 - Take no action&lt;/li&gt;
&lt;li&gt;1 - Sleep&lt;/li&gt;
&lt;li&gt;2 - System hibernate sleep state&lt;/li&gt;
&lt;li&gt;3 - System shutdown&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="https://tech.nicolonsky.ch/content/images/2019/05/intune-lid-action-config.png" &gt;&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Intune OMA-URI Lid Action"
 src="https://tech.nicolonsky.ch/content/images/2019/05/intune-lid-action-config.png"
 &gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;h2 class="relative group"&gt;End user experience
 &lt;div id="end-user-experience" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#end-user-experience" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;After the next MDM policy refresh the configured policy takes effect and is visible under the power options in control panel:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://tech.nicolonsky.ch/content/images/2019/05/power-options-2.png" &gt;&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Intune Lid Action End User Experience"
 src="https://tech.nicolonsky.ch/content/images/2019/05/power-options-2.png"
 &gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Introducing the OneDrive AutoMountTeamSites setting</title><link>https://tech.nicolonsky.ch/onedrive-automountteamsites/</link><pubDate>Sun, 17 Mar 2019 16:03:09 +0000</pubDate><guid>https://tech.nicolonsky.ch/onedrive-automountteamsites/</guid><description>&lt;p&gt;Reviewing the latest OneDrive features I wanted to try the new &lt;em&gt;AutoMountTeamSites&lt;/em&gt; setting which lets you preconfigure SharePoint online sites to sync automatically for defined users and devices.&lt;/p&gt;
&lt;p&gt;&lt;mark&gt;&lt;strong&gt;Updated on 12.07.2019&lt;/strong&gt;: &lt;a href="#intune-administrative-template-configuration"&gt;Included the Intune administrative template configuration&lt;/a&gt;&lt;/mark&gt;&lt;/p&gt;
&lt;p&gt;The setting is officially described as follow:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;This setting lets you specify SharePoint team site libraries to sync automatically the next time users sign in to the OneDrive sync client. (Microsoft)&lt;/p&gt;
&lt;/blockquote&gt;&lt;blockquote&gt;&lt;p&gt;If you enable this setting, the OneDrive sync client will automatically download the contents of the libraries you specified as online-only files the next time the user signs in. The user won&amp;rsquo;t be able to stop syncing the libraries. (Microsoft)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 class="relative group"&gt;Prerequisites
 &lt;div id="prerequisites" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#prerequisites" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;In order to get things up an running we need at least:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;OneDrive sync client version 19.012.0121.0011 or newer&lt;/li&gt;
&lt;li&gt;Windows 10 Version 1709 or newer&lt;/li&gt;
&lt;li&gt;OneDrive Files On-Demand enabled (&lt;a href="https://tech.nicolonsky.ch/onedrive-automountteamsites/#intune-administrative-template-configuration" &gt;described below&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Be aware that this feature is not supported with on-premises SharePoint sites and not recommended to enable this setting for more than 1'000 devices. The device limit is related to the Windows Push Notification Service which tells the OneDrive clients when a file change occurs on a server side. When you exceed that limit clients will find themselves in a polling mode. &lt;a href="https://hansbrender.com/2019/04/04/onedrive-update-for-gpo-team-site-libraries-to-sync-automatically/" target="_blank" rel="noreferrer"&gt;Hans Brender explains this behavior well on his blog&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Intune map network drives and execute PowerShell script on each user logon</title><link>https://tech.nicolonsky.ch/intune-execute-powershell-script-on-each-user-logon/</link><pubDate>Fri, 11 Jan 2019 20:51:36 +0000</pubDate><guid>https://tech.nicolonsky.ch/intune-execute-powershell-script-on-each-user-logon/</guid><description>&lt;p&gt;Recently a customer needed a drive mapping solution to access his on premise file shares during his transition phase to a cloud-only workplace. I wanted to share the solution with you because it&amp;rsquo;s  a frequently asked question around a modern workplace migration. The following solution can also be extended or modified for a printer mapping or other PowerShell scripts which need to run on each user logon.&lt;/p&gt;
&lt;!--kg-card-begin: markdown--&gt;
&lt;p&gt;&lt;mark&gt;&lt;strong&gt;Updated 04.08.2019&lt;/strong&gt;: I&amp;rsquo;ve developed an automated solution to generate network drive mapping configurations with an online tool which also migrates group policy network drive mappings. See: &lt;a href="https://tech.nicolonsky.ch/next-level-network-drive-mapping-with-intune"&gt;next-level-network-drive-mapping-with-intune&lt;/a&gt;.&lt;/mark&gt;&lt;/p&gt;
&lt;!--kg-card-end: markdown--&gt;&lt;!--kg-card-begin: markdown--&gt;
&lt;p&gt;&lt;a href="https://github.com/nicolonsky/Techblog/tree/master/IntuneNetworkDrives" target="_blank" rel="noreferrer"&gt;Direct link to the final scripts&lt;/a&gt;&lt;/p&gt;
&lt;!--kg-card-end: markdown--&gt;
&lt;p&gt;Lets assume we have the following scenario:&lt;/p&gt;
&lt;figure class="kg-card kg-image-card"&gt;&lt;img src="https://tech.nicolonsky.ch/content/images/2019/01/Hybrid-AAD.png" class="kg-image"&gt;&lt;/figure&gt;
- Customer with hybrid user-identities (Azure AD Connect)
- On premise ressources with legacy file shares
- Devices are Azure AD joined &amp;nbsp;( **not** hybrid joined)
- MDM managed with Intune
- [Optional] Always on VPN for external on-premise resource access
- [Optional] Windows Hello for Business deployment as described [here](https://docs.microsoft.com/en-us/windows/security/identity-protection/hello-for-business/hello-hybrid-aadj-sso) 

&lt;h2 class="relative group"&gt;Architecture
 &lt;div id="architecture" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#architecture" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;With my colleague &lt;a href="https://blog.alschneiter.com/" target="_blank" rel="noreferrer"&gt;Alain Schneiter&lt;/a&gt; I designed the following solution:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Main PowerShell script stored on Azure blob storage which handles the drive mapping -  driveletters, UNC paths and descriptions can be configured within the script  &lt;/li&gt;
&lt;li&gt;Client side script deployed with Intune which triggers the main script during logon.  The main script is not stored locally which makes it easy to customize (no updates oder changes needed on client side)&lt;/li&gt;
&lt;li&gt;Deployment is user targeted via Azure AD group and Intune&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;Azure blob storage configuration
 &lt;div id="azure-blob-storage-configuration" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#azure-blob-storage-configuration" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;We wanted to store the script within Azure because the customer was already using Azure blob storage. It&amp;rsquo;s also possible to store the PowerShell script on GitHub if you don&amp;rsquo;t want to use Azure.&lt;/p&gt;</description></item><item><title>Clean up stale Azure AD devices</title><link>https://tech.nicolonsky.ch/clean-up-azure-ad-devices/</link><pubDate>Thu, 10 Jan 2019 22:25:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/clean-up-azure-ad-devices/</guid><description>&lt;p&gt;If you are using Azure AD and the time passes you&amp;rsquo;ll have a lot of old device entries. If you enable the automatic device cleanup rule in Microsoft Intune the device is only removed within MDM and the Azure AD entry still exists.&lt;/p&gt;
&lt;figure class="kg-card kg-image-card kg-card-hascaption"&gt;&lt;img src="https://tech.nicolonsky.ch/content/images/2019/01/image-1.png" class="kg-image"&gt;&lt;figcaption&gt;Intune device cleanup rule&lt;/figcaption&gt;&lt;/figure&gt;
&lt;p&gt;For this reason I created a tiny PowerShell snippet to create a report with all devices which didn&amp;rsquo;t contact your Azure AD tenant since the treshold date specified. If you confirm the operation you can also delete all affected devices.&lt;/p&gt;
&lt;!--kg-card-begin: markdown--&gt;
&lt;p&gt;&lt;mark&gt;&lt;em&gt;Please be careful when running the script because when removing a device from Azure AD the stored Bitlocker recovery keys are also removed. I can recommend &lt;a href="http://rzander.azurewebsites.net/bitlocker-management-with-azure-storage-table/"&gt;Roger Zander&amp;rsquo;s Azure table-based Bitlocker recovery key solution&lt;/a&gt;.&lt;/em&gt;&lt;/mark&gt;&lt;/p&gt;
&lt;!--kg-card-end: markdown--&gt;&lt;!--kg-card-begin: markdown--&gt;&lt;script src="https://gist.github.com/nicolonsky/231844d2c383396331a94024bffbd7ff.js"&gt; &lt;/script&gt;&lt;!--kg-card-end: markdown--&gt;</description></item><item><title>Set Office 365 UsageLocation property with Azure automation</title><link>https://tech.nicolonsky.ch/office-usage-location-azure-automation/</link><pubDate>Wed, 09 Jan 2019 15:23:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/office-usage-location-azure-automation/</guid><description>&lt;p&gt;If you want to assign Microsoft licenses to your Azure AD users e.g. Microsoft 365 E3 licenses you can do this with group based licensing as described &lt;a href="https://docs.microsoft.com/en-us/azure/active-directory/fundamentals/active-directory-licensing-whatis-azure-portal" target="_blank" rel="noreferrer"&gt;here&lt;/a&gt;. &lt;del&gt;The problem is that even with group based licensing the UsageLocation property for each user must be set individually.&lt;/del&gt;&lt;/p&gt;
&lt;p&gt;&lt;mark&gt;Update: 13.01.2019: Since group based licensing is GA the tenant location is used if no UsageLocation is set on a user object. Use this guide if you want to manually assign licenses or override the tenant settings if you need to configure different UsageLocations.&lt;/mark&gt;&lt;/p&gt;

&lt;h2 class="relative group"&gt;Possible bulk and automation solutions
 &lt;div id="possible-bulk-and-automation-solutions" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#possible-bulk-and-automation-solutions" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;You can achieve this with the following options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;ldquo;Manual&amp;rdquo; trough Azure or Office 365 portal&lt;/li&gt;
&lt;li&gt;PowerShell (must be triggered manually or through scheduled task)&lt;/li&gt;
&lt;li&gt;Azure AD Connect synchronisation (UsageLocation populated in on prem AD)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Azure automation with PowerShell runbook as in this post 🙂&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 class="relative group"&gt;Azure automation sounds expensive?
 &lt;div id="azure-automation-sounds-expensive" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#azure-automation-sounds-expensive" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;Fortunately Azure automation offers 500 minutes of script runtime for free. Find more details under Automation pricing. Just to give you an idea: If the executed script has an average runtime of 1 minute you could run it (500 minutes / (30 calendear days / 1 minute script runtime)) = 16x per day. Each month. For free.&lt;/p&gt;</description></item><item><title>SwissSkills some thoughts about this years competition</title><link>https://tech.nicolonsky.ch/swissskills-experience/</link><pubDate>Sat, 15 Sep 2018 18:19:38 +0000</pubDate><guid>https://tech.nicolonsky.ch/swissskills-experience/</guid><description>&lt;p&gt;That&amp;rsquo;s it. Saturday morning, the day after my SwissSkills 2018 competition in Bern. Waiting for a call to answer even though I know that my performance was not good enough to deserve a podium spot.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Update, 16.09.2018&lt;/strong&gt;: the rankings are now available and I made it to the fourth place. Missing third by 0.05 points (!)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="https://www.swiss-skills.ch/2018/berufe/resultate/" target="_blank" rel="noreferrer"&gt;&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="SwissSkills2018 result"
 src="https://tech.nicolonsky.ch/content/images/2018/09/SwissSkills2018_result.png"
 &gt;&lt;/figure&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;h2 class="relative group"&gt;My journey
 &lt;div id="my-journey" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#my-journey" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;Last year I had the privilege to compete at the national ICT skills after qualifying through the regional championships. I went there with no expectations I just wanted to know where I stand amongst others. In the end I was overwhelmed with the 3rd place.&lt;/p&gt;
&lt;p&gt;With this achievement a few things had changed. I&amp;rsquo;ve gotten new opportunities regarding my job, had the chance to attend great events and had a confidence boost to finish my apprenticeship.&lt;/p&gt;
&lt;p&gt;Because of my 3rd place last year I was automatically qualified to compete this year at the SwissSkills in Bern. Now I had expectations and wanted to qualify myself for the upcoming WorldSkills in Kazan.&lt;/p&gt;

&lt;h2 class="relative group"&gt;The SwissSkills competition
 &lt;div id="the-swissskills-competition" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#the-swissskills-competition" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;I went to the event with a good feeling and felt confident. I had prepared myself well - even better than last year and I wanted this podium spot so badly.
During the competition I was realizing that just because you want something it doesn&amp;rsquo;t have to mean that you will get it. No matter how much you want it. I gave my very best but approximately after 5 hours into the competition I had trouble to focus properly and was unable to concentrate. Of course the tasks were difficult but not at an unsolvable level.&lt;/p&gt;</description></item><item><title>Deploy OneDrive KFM with Microsoft Intune OMA-URI</title><link>https://tech.nicolonsky.ch/onedrive-known-folder-move-ms-intune/</link><pubDate>Thu, 06 Sep 2018 18:37:21 +0000</pubDate><guid>https://tech.nicolonsky.ch/onedrive-known-folder-move-ms-intune/</guid><description>&lt;p&gt;OneDrive KFM (Known Folder Move) allows you to redirect common Windows folders (Desktop, Documents and Pictures) to the users personal OneDrive. OneDrive Known Folder Move is the modern replacement for the well known folder redirection group policy. The deployment with Microsoft Intune allows you to trigger or automate the OneDrive KFM configuration for your end users.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Updated on 04.08.2019&lt;/strong&gt;: Added administrative template configuration&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This post is based on a great article from Oliver Kieselbach about &lt;a href="https://oliverkieselbach.com/2017/11/07/deep-dive-admx-ingestion-to-configure-silentaccountconfig-with-onedrive/" target="_blank" rel="noreferrer"&gt;Deep dive ADMX ingestion to configure SilentAccountConfig with OneDrive&lt;/a&gt;. I used his blog to play around with the admx ingestion.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Prerequisites
 &lt;div id="prerequisites" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#prerequisites" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;To automatically deploy OneDrive Known Folder Move the following prerequisites must be met:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;OneDrive sync client with build 18.111.0603.0004 or greater&lt;/li&gt;
&lt;li&gt;Azure AD Joined or Hybrid Azure AD Joined Windows 10 Device Running Windows 10 1709 or later&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 class="relative group"&gt;Intune Configuration
 &lt;div id="intune-configuration" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#intune-configuration" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;

&lt;h3 class="relative group"&gt;Configure SilentAccountConfig
 &lt;div id="configure-silentaccountconfig" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#configure-silentaccountconfig" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;

&lt;h4 class="relative group"&gt;Option #1 - ADMX Templates
 &lt;div id="option-1---admx-templates" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#option-1---admx-templates" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h4&gt;
&lt;p&gt;With SilentAccountConfig enabled OneDrive for Business gets automatically configured with the current user account who&amp;rsquo;s signing in to Windows.&lt;/p&gt;</description></item><item><title>Windows 10 1803 New MDM Policy CSP Settings</title><link>https://tech.nicolonsky.ch/windows-10-1803-new-mdm-policy-csp-settings/</link><pubDate>Sat, 21 Apr 2018 22:11:30 +0000</pubDate><guid>https://tech.nicolonsky.ch/windows-10-1803-new-mdm-policy-csp-settings/</guid><description>&lt;p&gt;Hello. Long time no see. Finally I&amp;rsquo;m back with a new post. This time I created a nice little list with Windows 10 1803 New MDM Policy CSP Settings for the next Windows 10 release. If you&amp;rsquo;re not familiar with Policy CSP Settings - that are GPO Settings configureable over an Intune OMA-Uri Policy. Here&amp;rsquo;s &lt;a href="https://docs.microsoft.com/en-us/windows/configuration/provisioning-packages/how-it-pros-can-use-configuration-service-providers" target="_blank" rel="noreferrer"&gt;a great introducation to Policy CSP Settings.&lt;/a&gt;&lt;/p&gt;

&lt;h3 class="relative group"&gt;My favorite policy CPS&amp;rsquo;s available with Windows 10 1803
 &lt;div id="my-favorite-policy-cpss-available-with-windows-10-1803" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#my-favorite-policy-cpss-available-with-windows-10-1803" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;!--kg-card-begin: markdown--&gt;
&lt;p&gt;The following CSP&amp;rsquo;s are available on Windows 10 1803 and later:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ControlPolicyConflict: &lt;strong&gt;MDMWinsOverGP&lt;/strong&gt;&lt;br&gt;
This policy allows the IT admin to control which policy will be used whenever both the MDM policy and its equivalent Group Policy are set on the device.&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/windows/client-management/mdm/policy-csp-controlpolicyconflict" target="_blank" rel="noreferrer"&gt;Microsoft docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;LanmanWorkstation: &lt;strong&gt;EnableInsecureGuestLogons&lt;/strong&gt;&lt;br&gt;
This policy setting determines if the SMB client will allow insecure guest logons to an SMB server&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/windows/client-management/mdm/policy-csp-lanmanworkstation" target="_blank" rel="noreferrer"&gt;Microsoft docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;RestrictedGroups: &lt;strong&gt;ConfigureGroupMembership&lt;/strong&gt;&lt;br&gt;
This security setting allows an administrator to define the members of a security-sensitive (restricted) group.&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/windows/client-management/mdm/policy-csp-restrictedgroups" target="_blank" rel="noreferrer"&gt;Microsoft docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!--kg-card-end: markdown--&gt;
&lt;p&gt;You can find the entire list (CSV) on &lt;a href="https://github.com/nicolonsky/Techblog/blob/master/PolicyCSP/CSPPolicyList_New.csv" target="_blank" rel="noreferrer"&gt;Github&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The scripts to retrieve and compare the available Policy CSP&amp;rsquo;s for a Windows version are available on &lt;a href="https://github.com/nicolonsky/Techblog/tree/master/PolicyCSP" target="_blank" rel="noreferrer"&gt;GitHub&lt;/a&gt;. Feel free to leave feedback or improvement changes.&lt;/p&gt;</description></item><item><title>Surface Hub Miracast Connection Error</title><link>https://tech.nicolonsky.ch/surface-hub-miracast-connection-error/</link><pubDate>Fri, 05 Jan 2018 10:48:59 +0000</pubDate><guid>https://tech.nicolonsky.ch/surface-hub-miracast-connection-error/</guid><description>&lt;p&gt;Recently I had to troubleshoot a sticky Surface Hub Miracast Connection error for a customer. They were unable to connect to the surface hub from domain joined devices but a newly installed device from a blank Windows image was working as expected. I started Troubleshooting the Surface Hub Miracast Connection Error and checked all the points mentioned in the official &lt;a href="https://docs.microsoft.com/en-us/surface-hub/miracast-troubleshooting" target="_blank" rel="noreferrer"&gt;Troubleshoot Miracast on Surface Hub&lt;/a&gt; post from Microsoft.&lt;/p&gt;
&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="SurfaceHub"
 src="https://nicolonskytech.azurewebsites.net/content/images//2018/01/SurfaceHub-300x141.png"
 &gt;&lt;/figure&gt;

&lt;h2 class="relative group"&gt;Default Configuration
 &lt;div id="default-configuration" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#default-configuration" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;On a Windows 10 1709 device exists a default firewall rule to allow Miracast connections to wireless displays:&lt;/p&gt;
&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Miracast"
 src="https://nicolonskytech.azurewebsites.net/content/images//2018/01/MiracastRuleDefault-1024x34.png"
 &gt;&lt;/figure&gt;
&lt;p&gt;But the connection attempt was still interrupted after a timeout.&lt;/p&gt;

&lt;h2 class="relative group"&gt;Looking trough Group Policy
 &lt;div id="looking-trough-group-policy" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#looking-trough-group-policy" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;After analyzing the Windows 10 Security Baseline Group Policy configuration I came across the following settings:&lt;/p&gt;
&lt;p&gt;Computer Configuration &amp;gt; Windows Settings &amp;gt; Security Settings &amp;gt; Windows Firewall with Advanced Security:&lt;/p&gt;
&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Surface Hub Miracast Connection Error"
 src="https://nicolonskytech.azurewebsites.net/content/images//2018/01/FirewallGpoSettings.png"
 &gt;&lt;/figure&gt;
&lt;p&gt;In the settings for the public profile under the &amp;ldquo;Customize&amp;rdquo; section there&amp;rsquo;s a section called &amp;ldquo;&lt;strong&gt;Rule merging&lt;/strong&gt;&amp;rdquo;:&lt;/p&gt;
&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Surface Hub Miracast Connection Error"
 src="https://nicolonskytech.azurewebsites.net/content/images//2018/01/RuleMerging.png"
 &gt;&lt;/figure&gt;
&lt;p&gt;As you can see rule merging is turned of in the Windows 10 Security Baseline which means, **all locally configured firewall rules are being ignored for the public profile. **Because Miracast connections or connection attempts belong to the public profile of the Windows Firewall, the built-in local firewall rule gets always bypassed.&lt;/p&gt;</description></item><item><title>Windows 10 1709 Cannot Access SMB2 Share Guest Access</title><link>https://tech.nicolonsky.ch/windows-10-1709-cannot-access-smb2-share-guest-access/</link><pubDate>Thu, 19 Oct 2017 17:51:57 +0000</pubDate><guid>https://tech.nicolonsky.ch/windows-10-1709-cannot-access-smb2-share-guest-access/</guid><description>&lt;p&gt;After Upgrading to Windows 10 1709 (Fall Creators Update) I couldn&amp;rsquo;t access my Synology NAS anymore. Therefore I started troubleshooting the Windows 10 1709 Cannot Access SMB2 Share Guest Access error:&lt;/p&gt;
&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Windows 10 1709 Cannot Access SMB2 Share Guest Access"
 src="https://tech.nicolonsky.ch/content/images/2017/10/2017-10-19_1725-300x171.png"
 &gt;&lt;/figure&gt;
&lt;blockquote&gt;&lt;p&gt;An error occurred while reconnecting X: to &lt;code&gt;\\nas\data&lt;/code&gt;
Microsoft Windows Network: You can&amp;rsquo;t access this shared folder because your organization&amp;rsquo;s security policies block unauthenticated guest access. These policies help protect your PC from unsafe or malicious devices on the network.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 class="relative group"&gt;Cause
 &lt;div id="cause" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#cause" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;Starting with Windows 10 1709, Windows prevents you from accessing network shares with guest access enabled. Guest access means connecting to network shares without authentication, using the built-in &amp;ldquo;guest&amp;rdquo; account.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;This has no reference to the SMB1 protocol which was disabled in the latest Windows 10 release.&lt;/strong&gt;&lt;/p&gt;

&lt;h2 class="relative group"&gt;Resolution
 &lt;div id="resolution" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#resolution" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;To enable guest access again, configure the following GPO:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Computer configuration &amp;gt; administrative templates &amp;gt; network &amp;gt; Lanman Workstation: &amp;quot;Enable insecure guest logons&amp;quot; = Enabled&lt;/code&gt;&lt;/p&gt;
&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Windows 10 1709 Cannot Access SMB2 Share Guest Access"
 src="https://tech.nicolonsky.ch/content/images/2017/10/2017-10-19_1740-1024x726.png"
 &gt;&lt;/figure&gt;

&lt;h3 class="relative group"&gt;Registry Key
 &lt;div id="registry-key" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#registry-key" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;The according registry key is located under:&lt;/p&gt;</description></item><item><title>PowerShell Script Test Open TCP Ports</title><link>https://tech.nicolonsky.ch/power-shell-script-test-open-tcp-ports/</link><pubDate>Wed, 18 Oct 2017 13:28:12 +0000</pubDate><guid>https://tech.nicolonsky.ch/power-shell-script-test-open-tcp-ports/</guid><description>&lt;p&gt;Recently I was troubleshooting ADFS connection issues when I discovered a nice little Cmdlet called &amp;ldquo;Test-NetConnection&amp;rdquo;. With this Cmdelet you can verify TCP connectivity, in my case from a client to the ADFS server.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;The &lt;strong&gt;Test-NetConnection&lt;/strong&gt; cmdlet displays diagnostic information for a connection. It supports ping test, TCP test, route tracing, and route selection diagnostics. Depending on the input parameters, the output can include the DNS lookup results, a list of IP interfaces, IPsec rules, route/source address selection results, and/or confirmation of connection establishment.&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;Find a full documentation on the &lt;a href="https://docs.microsoft.com/en-us/powershell/module/nettcpip/test-netconnection?view=win10-ps" target="_blank" rel="noreferrer"&gt;Microsoft Docs Page&lt;/a&gt;.&lt;/p&gt;

&lt;h2 class="relative group"&gt;About the script
 &lt;div id="about-the-script" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#about-the-script" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;With this Script you are able to specify server names and port numbers to check in a CSV File. The Script generates an CSV output file as a report. You can use this script for troubleshooting or engineering purposes to verify if TCP ports are opened.&lt;/p&gt;
&lt;p&gt;Simply add the hostname and TCP port to the &amp;ldquo;CheckList.csv&amp;rdquo; and the script checks the specified servers and ports.&lt;/p&gt;
&lt;p&gt;The script will generate an output file for the same path containing the suffix &amp;ldquo;Report_&amp;rdquo; with the test results.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;CheckList.csv: &lt;br&gt;
&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="CheckList.csv"
 src="https://tech.nicolonsky.ch/content/images//2017/10/2017-10-18_1242.png"
 &gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Report_CheckList.csv generated after script execution:
&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Report_CheckList.csv"
 src="https://tech.nicolonsky.ch/content/images//2017/10/2017-10-18_1252.png"
 &gt;&lt;/figure&gt;
&lt;/p&gt;</description></item><item><title>Manage Local Administrator Rights Using Group Policy</title><link>https://tech.nicolonsky.ch/manage-local-administrator-rights-using-group-policy/</link><pubDate>Sat, 14 Oct 2017 13:37:49 +0000</pubDate><guid>https://tech.nicolonsky.ch/manage-local-administrator-rights-using-group-policy/</guid><description>&lt;p&gt;If you imagine that your users or administrators have uncontrolled local administrator rights it&amp;rsquo;s a nightmare. They have (certainly) full control over their computer, and could do a lot of harm. So managing local administrator rights is definitely a must.&lt;/p&gt;

&lt;h1 class="relative group"&gt;Manage Local Administrator Rights
 &lt;div id="manage-local-administrator-rights" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#manage-local-administrator-rights" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h1&gt;
&lt;p&gt;The Active Directory Group Policies offer a great possibility to manage local groups on clients or servers. All the magic happens with &amp;ldquo;Restricted Groups&amp;rdquo;.&lt;/p&gt;

&lt;h3 class="relative group"&gt;Adding a group or users to a local group
 &lt;div id="adding-a-group-or-users-to-a-local-group" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#adding-a-group-or-users-to-a-local-group" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;If you want to add a certain group to a built-in group add the group to the restricted groups under the &amp;ldquo;This group is a member of&amp;rdquo; sections:&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Group Policy Restricted Groups"
 src="https://tech.nicolonsky.ch/content/images//2017/10/2017-10-13_2326.png"
 &gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p&gt;When the GPO is no longer applied, the restricted group is being removed from the clients.&lt;/p&gt;

&lt;h3 class="relative group"&gt;Overwrite local group members
 &lt;div id="overwrite-local-group-members" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#overwrite-local-group-members" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;When you wan&amp;rsquo;t take full control over a local group, you can choose the &amp;ldquo;Members of this group&amp;rdquo; option. Then all group members are replaced with the specified users or groups here, except the built-in local Administrator account.&lt;/p&gt;</description></item><item><title>PowerShell Function Validate Object Properties Using ValidateScript</title><link>https://tech.nicolonsky.ch/power-shell-function-validate-object-properties/</link><pubDate>Thu, 12 Oct 2017 10:25:09 +0000</pubDate><guid>https://tech.nicolonsky.ch/power-shell-function-validate-object-properties/</guid><description>&lt;p&gt; &lt;/p&gt;
&lt;p&gt;Recently I was working on a PowerShell script with many custom functions. When I started to use PowerShell custom objects I wanted to be able to pass them to a function. So I faced the challenge of validating my object for all required properties and came up with this solution, using the ValidateScript block to test the object:&lt;/p&gt;
&lt;script src="https://gist.github.com/nicolonsky/9c09096dd91ceb7a8fa43ab5cf4c3740.js"&gt;&lt;/script&gt;

&lt;h4 class="relative group"&gt;Customizing the ValidateScript
 &lt;div id="customizing-the-validatescript" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#customizing-the-validatescript" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h4&gt;
&lt;p&gt;As you can see I use a ValidateScript for the parameter validation to test the object for the required properties. The properties can be specified in an array:
&lt;code&gt;$requiredProperties=@(&amp;quot;Property1&amp;quot;,&amp;quot;Property2&amp;quot;,&amp;quot;Property3&amp;quot;, &amp;quot;Property4&amp;quot;)&lt;/code&gt;
When we call the Function with an appropriate object:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$config&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;PSCUSTOMOBJECT&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="vm"&gt;@&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;property1&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;property2&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;property3&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;property4&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;We receive the following output:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;PS &lt;/span&gt;&lt;span class="n"&gt;H:&lt;/span&gt;&lt;span class="p"&gt;\&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;New-Example&lt;/span&gt; &lt;span class="n"&gt;-InputObject&lt;/span&gt; &lt;span class="nv"&gt;$config&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Succesfully&lt;/span&gt; &lt;span class="n"&gt;passed&lt;/span&gt; &lt;span class="nb"&gt;ValidateScript&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 class="relative group"&gt;Result
 &lt;div id="result" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#result" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;p&gt;If we remove one or more properties from our custom object, an error is thrown:&lt;/p&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;PS &lt;/span&gt;&lt;span class="n"&gt;H:&lt;/span&gt;&lt;span class="p"&gt;\&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$config&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;PSCUSTOMOBJECT&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="vm"&gt;@&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;property1&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;property2&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;property3&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Value&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;New-Example&lt;/span&gt; &lt;span class="n"&gt;-InputObject&lt;/span&gt; &lt;span class="nv"&gt;$config&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;New-Example&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Cannot&lt;/span&gt; &lt;span class="n"&gt;validate&lt;/span&gt; &lt;span class="n"&gt;argument&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="nb"&gt;parameter&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;InputObject&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Property&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Property4&amp;#39;&lt;/span&gt; &lt;span class="n"&gt;missing&lt;/span&gt; &lt;span class="n"&gt;At&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;10&lt;/span&gt; &lt;span class="n"&gt;char&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mf"&gt;26&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;New-Example&lt;/span&gt; &lt;span class="n"&gt;-InputObject&lt;/span&gt; &lt;span class="nv"&gt;$config&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="p"&gt;~~~~~~~&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;CategoryInfo&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="n"&gt;InvalidData&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;New-Example&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;ParameterBindingValidationException&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;FullyQualifiedErrorId&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ParameterArgumentValidationError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nb"&gt;New-Example&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;If you want to go a step further you could extend the ValidateScript to&amp;hellip;&lt;/p&gt;

&lt;h3 class="relative group"&gt;Prevent passing properties with a NULL or empty value
 &lt;div id="prevent-passing-properties-with-a-null-or-empty-value" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#prevent-passing-properties-with-a-null-or-empty-value" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h3&gt;
&lt;div class="highlight-wrapper"&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;PSObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Properties&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;ForEach-Object&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(([&lt;/span&gt;&lt;span class="no"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;IsNullOrEmpty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;))){&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;Throw&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;System.Management.Automation.ValidationMetadataException&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Property &amp;#39;&lt;/span&gt;&lt;span class="p"&gt;$(&lt;/span&gt;&lt;span class="nv"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#39; has either a NULL or empty value&amp;#34;&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;If we call our function again with the added IsNullOrEmpty validation NULL or emtpy values throw an exception:&lt;/p&gt;</description></item><item><title>Managing printers with PowerShell</title><link>https://tech.nicolonsky.ch/managing-printers-power-shell/</link><pubDate>Tue, 10 Oct 2017 17:54:54 +0000</pubDate><guid>https://tech.nicolonsky.ch/managing-printers-power-shell/</guid><description>&lt;p&gt;Managing printers with PowerShell instead of VBScript? Sometimes it&amp;rsquo;s necessary to add and remove specific printers to a computer. For example during a client deployment or when a user logs on. This post covers how to manage printers with PowerShell.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The following PowerShell commands are supported with PowerShell version 4 and newer.&lt;/strong&gt;&lt;/p&gt;

&lt;h2 class="relative group"&gt;Installing a local network printer
 &lt;div id="installing-a-local-network-printer" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#installing-a-local-network-printer" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;Installing a local printer (without a printserver) consists of the following steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Add the printer driver to your system&amp;rsquo;s driverstore&lt;/li&gt;
&lt;li&gt;Install the printer driver from the driverstore&lt;/li&gt;
&lt;li&gt;Add a printer port to communicate with the printer&lt;/li&gt;
&lt;li&gt;Last but not least add the printer&lt;/li&gt;
&lt;/ol&gt;

&lt;h4 class="relative group"&gt;Add the printer driver to the driverstore
 &lt;div id="add-the-printer-driver-to-the-driverstore" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#add-the-printer-driver-to-the-driverstore" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h4&gt;
&lt;p&gt;Before you can install the printer driver you need to import the printer driver to your system&amp;rsquo;s driverstore.&lt;/p&gt;
&lt;p&gt;This can be achieved with the built in Windows &amp;ldquo;pnputil&amp;rdquo; utility.&lt;/p&gt;
&lt;p&gt;The following code adds all drivers from the specified path to the driverstore:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Get-ChildItem %PathToYourDriverFolder% -Filter *.inf -Recurse | % {pnputil.exe /a $_.FullName}&lt;/code&gt;&lt;/p&gt;

&lt;h4 class="relative group"&gt;Install the printer driver from the driverstore
 &lt;div id="install-the-printer-driver-from-the-driverstore" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#install-the-printer-driver-from-the-driverstore" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h4&gt;
&lt;p&gt;This step is quite simple, you just need to know the name of the printer driver you want to install. For example &amp;ldquo;HP Universal Printing PCL 6&amp;rdquo;.&lt;/p&gt;</description></item><item><title>Disable Java Auto Update During Installation</title><link>https://tech.nicolonsky.ch/disable-java-auto-update/</link><pubDate>Tue, 10 Oct 2017 17:00:01 +0000</pubDate><guid>https://tech.nicolonsky.ch/disable-java-auto-update/</guid><description>&lt;blockquote&gt;&lt;p&gt;Disable Java Auto Update without registry modification?&lt;/p&gt;
&lt;/blockquote&gt;&lt;p&gt;Recently i had to install Oracle Java on a Terminal server and was curious, if it&amp;rsquo;s possible to configure the package that the auto update feature is disabled without any registry configuration?&lt;/p&gt;

&lt;h2 class="relative group"&gt;Custom configuration
 &lt;div id="custom-configuration" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#custom-configuration" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;On the Oracle website i found a great article about the possibility to pass a configuration file to the installer:&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the syntax to install Java silently with a custom configuration:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;jre-8u121-windows-x64.exe -s INSTALLCFG=&amp;quot;C:\Install\Java\java.settings.cfg&amp;quot; AUTO_UPDATE=Disable EULA=Disable NOSTARTMENU=Enable SPONSORS=Disable&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;You can find a full reference of all configuration items here: &lt;a href="https://docs.oracle.com/javase/8/docs/technotes/guides/install/config.html" target="_blank" rel="noreferrer"&gt;https://docs.oracle.com/javase/8/docs/technotes/guides/install/config.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Please be careful when using the &lt;code&gt;REMOVEOUTOFDATEJRES=1&lt;/code&gt; option, because when you install the same Java version in a different architecture (x86 &amp;amp; x64), the other architecture with the same version is being removed during the installation!&lt;/p&gt;
&lt;p&gt;You can find more information on the &lt;a href="http://tech.nicolonsky.ch/about/" target="_blank" rel="noreferrer"&gt;About&lt;/a&gt; section of my blog. Stay tuned for more posts.&lt;/p&gt;</description></item><item><title>About</title><link>https://tech.nicolonsky.ch/about/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/about/</guid><description>&lt;p&gt;Thank you for visiting my blog and reading this far. I am passionate about Cyber Security with the Microsoft Security stack.
On this blog I like to share ideas, solutions, experiences and learnings with the community. I write those blog posts during my free time and don&amp;rsquo;t write posts with sponsored content.&lt;/p&gt;

 



&lt;div
 
 class="flex px-4 py-3 rounded-md shadow bg-primary-100 dark:bg-primary-900"
 
 &gt;
 &lt;span
 
 class="text-primary-400 pe-3 flex items-center"
 
 &gt;
 &lt;span class="relative block icon"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"&gt;&lt;path fill="currentColor" d="M506.3 417l-213.3-364c-16.33-28-57.54-28-73.98 0l-213.2 364C-10.59 444.9 9.849 480 42.74 480h426.6C502.1 480 522.6 445 506.3 417zM232 168c0-13.25 10.75-24 24-24S280 154.8 280 168v128c0 13.25-10.75 24-23.1 24S232 309.3 232 296V168zM256 416c-17.36 0-31.44-14.08-31.44-31.44c0-17.36 14.07-31.44 31.44-31.44s31.44 14.08 31.44 31.44C287.4 401.9 273.4 416 256 416z"/&gt;&lt;/svg&gt;
&lt;/span&gt;
 &lt;/span&gt;

 &lt;span
 
 class="dark:text-neutral-300"
 
 &gt;Please note that all posts on this blog reflect my own opinions and are provided &lt;strong&gt;&amp;ldquo;as is&amp;rdquo;, without warranty of any kind&lt;/strong&gt;.&lt;/span&gt;
&lt;/div&gt;


&lt;h2 class="relative group"&gt;User Group
 &lt;div id="user-group" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#user-group" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;To further strengthen the swiss Microsoft Security Community, I&amp;rsquo;m also Organizing the Workplace &amp;amp; Security Ninja User Group Switzerland with my good friend &lt;a href="https://medium.com/@verboonjanic" target="_blank" rel="noreferrer"&gt;Janic&lt;/a&gt;. The latest event and call for speakers information is available on &lt;a href="https://meetup.com/wpninjasugswitzerland" target="_blank" rel="noreferrer"&gt;meetup&lt;/a&gt;.&lt;/p&gt;
&lt;figure style="width:25%;"&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="auto"
 alt=""
 width="463"
 height="426"
 src="https://tech.nicolonsky.ch/img/ninja.png"
 srcset="https://tech.nicolonsky.ch/img/ninja.png 800w, https://tech.nicolonsky.ch/img/ninja.png 1280w"
 sizes="(min-width: 768px) 50vw, 65vw"
 data-zoom-src="https://tech.nicolonsky.ch/img/ninja.png"&gt;&lt;/figure&gt;

&lt;h2 class="relative group"&gt;Offline Activities
 &lt;div id="offline-activities" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#offline-activities" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;p&gt;Here some offline impressions:&lt;/p&gt;</description></item><item><title>Talks</title><link>https://tech.nicolonsky.ch/talks/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://tech.nicolonsky.ch/talks/</guid><description>&lt;p&gt;I am looking forward speaking on the events listed below. Do not hesitate to contact me for your next event. Slides from past events can mostly be downloaded as PDF.&lt;/p&gt;
&lt;figure&gt;&lt;img
 class="my-0 rounded-md"
 loading="lazy"
 decoding="async"
 fetchpriority="low"
 alt="Speaking"
 src="https://tech.nicolonsky.ch/content/images/talks.jpg"
 &gt;&lt;/figure&gt;

&lt;h2 class="relative group"&gt;Upcoming
 &lt;div id="upcoming" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#upcoming" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Date&lt;/th&gt;
 &lt;th&gt;Event&lt;/th&gt;
 &lt;th&gt;Session&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;x&lt;/td&gt;
 &lt;td&gt;Your event?&lt;/td&gt;
 &lt;td&gt;For any speaking related inquiries just drop me an &lt;a href="mailto:hi@nicolasuter.ch" &gt;e-mail&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 class="relative group"&gt;Past
 &lt;div id="past" class="anchor"&gt;&lt;/div&gt;
 
 &lt;span
 class="absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none"&gt;
 &lt;a class="text-primary-300 dark:text-neutral-700 !no-underline" href="#past" aria-label="Anchor"&gt;#&lt;/a&gt;
 &lt;/span&gt;
 
&lt;/h2&gt;
&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Date&lt;/th&gt;
 &lt;th&gt;Event&lt;/th&gt;
 &lt;th&gt;Session&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;08.10.2025&lt;/td&gt;
 &lt;td&gt;Workplace Ninja User Group Switzerland&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://www.meetup.com/wpninjasugswitzerland/events/310458561" target="_blank" rel="noreferrer"&gt;Intune misconfigurations in the wild, what we see and what you should fix!&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;24.09.2025&lt;/td&gt;
 &lt;td&gt;Workplace Ninja Summit 2025&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://wpninjas25.sched.com/speaker/nicola134" target="_blank" rel="noreferrer"&gt;Various sessions&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;10.06.2025&lt;/td&gt;
 &lt;td&gt;Switch NetSec WG 2025&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://www.switch.ch/en/events" target="_blank" rel="noreferrer"&gt;KQL Threat Hunting hands on lab&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;16.09.2024&lt;/td&gt;
 &lt;td&gt;Workplace Ninja Summit 2024&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://wpninjas24.sched.com/speaker/nicola134" target="_blank" rel="noreferrer"&gt;Various sessions&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;28.05.2024&lt;/td&gt;
 &lt;td&gt;KQL Café&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://kqlcafe.github.io/website/" target="_blank" rel="noreferrer"&gt;Preventive side of ITDR with KQL&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;05.05.2024&lt;/td&gt;
 &lt;td&gt;MMS 2024 at MOA&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://mms2024atmoa.sched.com/speaker/nicola.suter" target="_blank" rel="noreferrer"&gt;Various sessions&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;30.10.2023&lt;/td&gt;
 &lt;td&gt;MMS 2023 Miami Beach Edition&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://mms2023miami.sched.com/speaker/nicola.suter" target="_blank" rel="noreferrer"&gt;Various sessions&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;27.09.2023&lt;/td&gt;
 &lt;td&gt;Workplace Ninja Summit 2023&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://sched.co/1PXEK" target="_blank" rel="noreferrer"&gt;Demystifying Defender for Endpoint Security Settings Management&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;19.03.2021&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://www.meetup.com/wpninjasugswitzerland/events/274918216/" target="_blank" rel="noreferrer"&gt;WPNinjaUG_CH 2103 Virtual&lt;/a&gt;&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://tech.nicolonsky.ch/content/slides/automating-intune-tasks-with-the-microsoft-graph-api.pdf" &gt;Automating Intune Tasks with the Microsoft Graph API&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;30.09.2020&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://www.expertslive.ch/" target="_blank" rel="noreferrer"&gt;Experts Live Switzerland&lt;/a&gt;&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://tech.nicolonsky.ch/content/slides/A-safari-through-the-Intune-device-management-scenario-jungle.pdf" &gt;A safari through the Intune device management scenario jungle&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;29.11.2019&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://geekmania.ch/2019/" target="_blank" rel="noreferrer"&gt;Geekmania&lt;/a&gt;&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://tech.nicolonsky.ch/content/slides/Geekmania-2019-WHFB.pdf" &gt;Hybrid Azure AD Join and Windows Hello for Business&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;04.10.2019&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://configmgr.ch/cmce-1910/" target="_blank" rel="noreferrer"&gt;Configmgr Community Event (CMCE)&lt;/a&gt;&lt;/td&gt;
 &lt;td&gt;&lt;a href="https://tech.nicolonsky.ch/content/slides/CMCE-1910-Classic%20On-Prem%20Services%20in%20the%20Cloud.pdf" &gt;Classic On-Prem Services in the Cloud&lt;/a&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;</description></item></channel></rss>