<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>windows on Digi Hunch</title><link>https://static.digihunch.com/tag/windows/</link><description>Recent content in windows on Digi Hunch</description><generator>Hugo -- gohugo.io</generator><language>en-US</language><lastBuildDate>Tue, 08 Apr 2025 14:46:49 -0400</lastBuildDate><atom:link href="https://static.digihunch.com/tag/windows/index.xml" rel="self" type="application/rss+xml"/><item><title>Key mapping for external PC keyboard on Mac</title><link>https://static.digihunch.com/2022/11/key-mapping-on-external-pc-keyboard-on-macbook/</link><pubDate>Wed, 23 Nov 2022 10:38:00 -0400</pubDate><guid>https://static.digihunch.com/2022/11/key-mapping-on-external-pc-keyboard-on-macbook/</guid><description>&lt;img src="https://static.digihunch.com/wp-content/uploads/2025/04/key-mapping-image.webp" alt="Featured image of post Key mapping for external PC keyboard on Mac" /&gt;&lt;p class="wp-block-paragraph"&gt;This post is to document my steps to use external Windows keyboard on Mac with custom key mapping.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading" id="h-background"&gt;Background&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Apple&amp;#8217;s magic keyboard does not support multi-device so I have to repurpose my Logitech K810 keyboard with MacBook. Logitech K810 is and &lt;a href="https://www.pcmag.com/reviews/logitech-k810-bluetooth-illuminated-keyboard"&gt;old model&lt;/a&gt; with Windows key layout even though it also supports MacOS.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The bottom row has the same number of keys as magic keyboard but with different keys. For example, magic keyboard has cmd key (aka GUI keys) besides space bar but K810 has Alt. Magic keyboard has Option key next to cmd key and K810 has Windows key on the left and Ctrl key on the right. The position of left Ctrl and FN is different on magic keyboard too. Since I rely on &lt;a href="https://static.digihunch.com/2018/02/linux-tips-and-tricks-in-shell/"&gt;shortcuts&lt;/a&gt; on Magic keyboard, I therefore decide configure key mapping on the Windows key, Alt keys and right ctrl key to match magic keyboard. &lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter size-full"&gt;&lt;img loading="lazy" decoding="async" width="1024" height="450" src="https://static.digihunch.com/wp-content/uploads/2025/04/K810.webp" alt="" class="wp-image-12872" srcset="https://static.digihunch.com/wp-content/uploads/2025/04/K810.webp 1024w, https://static.digihunch.com/wp-content/uploads/2025/04/K810-300x132.webp 300w, https://static.digihunch.com/wp-content/uploads/2025/04/K810-768x338.webp 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /&gt;&lt;figcaption class="wp-element-caption"&gt;K810 Layout&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In a nutshell, I need to remap some keys on an external Windows keyboard connected to MacOS (Monterey).&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;What is not working&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In MacOS, you could modify keys from keyboard preference as below. However, in my case I need to keep left ctrl key and overwrite the right ctrl key. MacOS does not distinguish them unfortunately. The native method is not flexible so I did not bother.&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter size-full"&gt;&lt;img loading="lazy" decoding="async" width="300" height="206" src="https://static.digihunch.com/wp-content/uploads/2025/04/macos-keyboard-pref.webp" alt="" class="wp-image-12871"/&gt;&lt;figcaption class="wp-element-caption"&gt;Use MacOS keyboard preference to modify keys&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In the mean time, I hate to install a third-party application (such as &lt;a href="https://karabiner-elements.pqrs.org/"&gt;Karabiner-Elements&lt;/a&gt;) just for the purpose of key mapping. Even though I appreciate the efforts by the community, I just don&amp;#8217;t find it a neat solution for the additional dependency.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;Challenges with key mapping&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;I then came across a developer&amp;#8217;s &lt;a href="https://rakhesh.com/mac/using-hidutil-to-map-macos-keyboard-keys/"&gt;post&lt;/a&gt; on using a utility called hidutil to map keys. This is promising after I tested using this command to swap key a/A and b/B. &lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;hidutil property --set &lt;span style="color:#e6db74"&gt;&amp;#39;{&amp;#34;UserKeyMapping&amp;#34;:[{&amp;#34;HIDKeyboardModifierMappingSrc&amp;#34;: 0x700000004,&amp;#34;HIDKeyboardModifierMappingDst&amp;#34;: 0x700000005},{&amp;#34;HIDKeyboardModifierMappingSrc&amp;#34;: 0x700000005,&amp;#34;HIDKeyboardModifierMappingDst&amp;#34;: 0x700000004}]}&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;The command above takes effect immediately, on all keyboards. In my case I only need mapping on an external keyboard, not the built-in keyboard. Luckily hidutil has &amp;#8211;matching switch where I can specify ProductID and VendorID. I can find both of them from About This Mac -&amp;gt; System Report -&amp;gt; Hardware -&amp;gt; Bluetooth:&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter size-full"&gt;&lt;img loading="lazy" decoding="async" width="1024" height="654" src="https://static.digihunch.com/wp-content/uploads/2025/04/vendor-id-product-id.webp" alt="" class="wp-image-12870" srcset="https://static.digihunch.com/wp-content/uploads/2025/04/vendor-id-product-id.webp 1024w, https://static.digihunch.com/wp-content/uploads/2025/04/vendor-id-product-id-300x192.webp 300w, https://static.digihunch.com/wp-content/uploads/2025/04/vendor-id-product-id-768x491.webp 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /&gt;&lt;figcaption class="wp-element-caption"&gt;Vendor ID and Product ID&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;From &lt;a href="https://developer.apple.com/library/archive/technotes/tn2450/_index.html"&gt;this&lt;/a&gt; technical note, we can find out the usage IDs of the keys in the table at the bottom of the page. Then use the Usage ID as the last two bytes of the source and destination values of the mapping expression above. For example, 0x700000004 stands for key A/a, and 0x700000005 stands for key B/b. In my case, after going through this table, my key mapping is:&lt;/p&gt;&#10;&lt;figure class="wp-block-table"&gt;&lt;table class="has-very-light-gray-to-cyan-bluish-gray-gradient-background has-background"&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;strong&gt;Source Key on K810&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;Source Code on K810&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;Destination Key&lt;/strong&gt;&lt;/th&gt;&lt;th&gt;&lt;strong&gt;Destination Code&lt;/strong&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Left Alt&lt;/td&gt;&lt;td&gt;0x7000000E2&lt;/td&gt;&lt;td&gt;Left GUI (cmd)&lt;/td&gt;&lt;td&gt;0x7000000E3&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Right Alt&lt;/td&gt;&lt;td&gt;0x7000000E6&lt;/td&gt;&lt;td&gt;Right GUI (cmd)&lt;/td&gt;&lt;td&gt;0x7000000E7&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Left Win&lt;/td&gt;&lt;td&gt;0x7000000E3&lt;/td&gt;&lt;td&gt;Left Alt (option)&lt;/td&gt;&lt;td&gt;0x7000000E2&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Right Ctrl&lt;/td&gt;&lt;td&gt;0x7000000E4&lt;/td&gt;&lt;td&gt;Right Alt (option)&lt;/td&gt;&lt;td&gt;0x7000000E6&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Fn+F12&lt;/td&gt;&lt;td&gt;0x700000045&lt;/td&gt;&lt;td&gt;Globe&lt;/td&gt;&lt;td&gt;0xFF00000003&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;There is even a &lt;a href="https://hidutil-generator.netlify.app/"&gt;website&lt;/a&gt; that helps you generate the usage ID. I put together a command, which is working, on the external keyboard.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;hidutil property --matching &lt;span style="color:#e6db74"&gt;&amp;#39;{&amp;#34;ProductID&amp;#34;:0xB319,&amp;#34;VendorID&amp;#34;:0x046D}&amp;#39;&lt;/span&gt; --set &lt;span style="color:#e6db74"&gt;&amp;#39;{&amp;#34;UserKeyMapping&amp;#34;:[{&amp;#34;HIDKeyboardModifierMappingSrc&amp;#34;:0x7000000E2,&amp;#34;HIDKeyboardModifierMappingDst&amp;#34;:0x7000000E3},{&amp;#34;HIDKeyboardModifierMappingSrc&amp;#34;:0x7000000E6,&amp;#34;HIDKeyboardModifierMappingDst&amp;#34;:0x7000000E7},&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;{&amp;#34;HIDKeyboardModifierMappingSrc&amp;#34;:0x7000000E3,&amp;#34;HIDKeyboardModifierMappingDst&amp;#34;:0x7000000E2},&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;{&amp;#34;HIDKeyboardModifierMappingSrc&amp;#34;:0x7000000E4,&amp;#34;HIDKeyboardModifierMappingDst&amp;#34;:0x7000000E6},&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;{&amp;#34;HIDKeyboardModifierMappingSrc&amp;#34;:0x700000045,&amp;#34;HIDKeyboardModifierMappingDst&amp;#34;:0xFF00000003}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#e6db74"&gt;]}&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;The other way to confirm that key mapping is working, is to look up key mapping with the following command:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;hidutil property --matching &lt;span style="color:#e6db74"&gt;&amp;#39;{&amp;#34;ProductID&amp;#34;:0xB319,&amp;#34;VendorID&amp;#34;:0x046D}&amp;#39;&lt;/span&gt; --get &lt;span style="color:#e6db74"&gt;&amp;#34;UserKeyMapping&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;To wipe out the mapping, we can use the following command:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;hidutil property --matching &lt;span style="color:#e6db74"&gt;&amp;#39;{&amp;#34;ProductID&amp;#34;:0xB319,&amp;#34;VendorID&amp;#34;:0x046D}&amp;#39;&lt;/span&gt; --set &lt;span style="color:#e6db74"&gt;&amp;#39;{&amp;#34;UserKeyMapping&amp;#34;:[]}&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Note that we have to use the same matching expression. However, I noticed that the command only works while the bluetooth keyboard is connected. When I reboot the MacBook the mapping goes away as well.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;The solution to key mapping&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Even though I could run this command after reboot using a plist file in ~/Library/LaunchAgents/, as the reference blog suggests, it will not work because I cannot guarantee the bluetooth keyboard is connected before MacOS executes it. Also, I might disconnect and re-connect the keyboard and I want to ensure that the system runs that command whenever the keyboard gets connected.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In the &lt;a href="https://github.com/pqrs-org/Karabiner-Elements"&gt;Karabiner Element&lt;/a&gt; community, some developers touched on &lt;a href="https://github.com/pqrs-org/Karabiner-Elements/issues/2196#issuecomment-621928482"&gt;this&lt;/a&gt;. Basically we can customize the plist file to tell MacOS when to fire the hidutil command, by using &amp;#8220;LaunchEvents&amp;#8221; key in the XML. There is an &lt;a href="https://github.com/pqrs-org/Karabiner-Elements/issues/2196#issuecomment-621928482"&gt;example&lt;/a&gt; for USB keyboard. For myself, I edit the plist file to be:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;?xml version=&amp;#34;1.0&amp;#34; encoding=&amp;#34;UTF-8&amp;#34;?&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;&amp;lt;!DOCTYPE plist PUBLIC &amp;#34;-//Apple//DTD PLIST 1.0//EN&amp;#34; &amp;#34;http://www.apple.com/DTDs/PropertyList-1.0.dtd&amp;#34;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;plist&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;version=&lt;/span&gt;&lt;span style="color:#e6db74"&gt;&amp;#34;1.0&amp;#34;&lt;/span&gt;&lt;span style="color:#f92672"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;Label&lt;span style="color:#f92672"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;local.hidutilKeyMapping&lt;span style="color:#f92672"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;LaunchEvents&lt;span style="color:#f92672"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;com.apple.iokit.matching&lt;span style="color:#f92672"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;com.apple.bluetooth.hostController&lt;span style="color:#f92672"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;dict&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;IOProviderClass&lt;span style="color:#f92672"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;IOBluetoothHCIController&lt;span style="color:#f92672"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;idProduct&lt;span style="color:#f92672"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;integer&amp;gt;&lt;/span&gt;B319&lt;span style="color:#f92672"&gt;&amp;lt;/integer&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;idVendor&lt;span style="color:#f92672"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;integer&amp;gt;&lt;/span&gt;046D&lt;span style="color:#f92672"&gt;&amp;lt;/integer&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;IOMatchLaunchStream&lt;span style="color:#f92672"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;true/&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;ProgramArguments&lt;span style="color:#f92672"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;array&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;/usr/bin/hidutil&lt;span style="color:#f92672"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;property&lt;span style="color:#f92672"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;--matching&lt;span style="color:#f92672"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;{&amp;#34;ProductID&amp;#34;:0xB319,&amp;#34;VendorID&amp;#34;:0x046D}&lt;span style="color:#f92672"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;--set&lt;span style="color:#f92672"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;{&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;UserKeyMapping&amp;#34;: [&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; { &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;HIDKeyboardModifierMappingSrc&amp;#34;:0x7000000E2,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;HIDKeyboardModifierMappingDst&amp;#34;:0x7000000E3&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; { &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;HIDKeyboardModifierMappingSrc&amp;#34;:0x7000000E6,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;HIDKeyboardModifierMappingDst&amp;#34;:0x7000000E7&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; { &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;HIDKeyboardModifierMappingSrc&amp;#34;:0x7000000E3,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;HIDKeyboardModifierMappingDst&amp;#34;:0x7000000E2&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; { &#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;HIDKeyboardModifierMappingSrc&amp;#34;:0x7000000E4,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;HIDKeyboardModifierMappingDst&amp;#34;:0x7000000E6&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;HIDKeyboardModifierMappingSrc&amp;#34;:0x700000045,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &amp;#34;HIDKeyboardModifierMappingDst&amp;#34;:0xFF00000003&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; ]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&lt;span style="color:#f92672"&gt;&amp;lt;/string&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;/array&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;key&amp;gt;&lt;/span&gt;RunAtLoad&lt;span style="color:#f92672"&gt;&amp;lt;/key&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;&amp;lt;true/&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;/dict&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;&amp;lt;/plist&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Store the file above as ~/Library/LaunchAgents/com.local.hidutilKeyMapping.plist (create LaunchAgents directory if it doesn&amp;#8217;t exist) and then run the following to load it:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;launchctl load ~/Library/LaunchAgents/com.local.hidutilKeyMapping.plist&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;This works perfectly. The dict section (line 7 to line 23) of the file is based on &lt;a href="http://technologeeks.com/docs/launchd.pdf"&gt;this&lt;/a&gt; document as the GitHub &lt;a href="https://github.com/pqrs-org/Karabiner-Elements/issues/2196#issuecomment-621928482"&gt;comment&lt;/a&gt; suggests. The LaunchEvents section narrows down the type of events that will trigger the program with arguments. It triggers whenever a bluetooth device with specific ProductID and VendorID connects to Mac. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;We can still use hidutil command from the previous section to ensure that the custom key mapping remain in effect:&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-large"&gt;&lt;img loading="lazy" decoding="async" width="1024" height="531" src="https://static.digihunch.com/wp-content/uploads/2025/04/hidutil-command-1024x531.webp" alt="" class="wp-image-12869" srcset="https://static.digihunch.com/wp-content/uploads/2025/04/hidutil-command-1024x531.webp 1024w, https://static.digihunch.com/wp-content/uploads/2025/04/hidutil-command-300x155.webp 300w, https://static.digihunch.com/wp-content/uploads/2025/04/hidutil-command-768x398.webp 768w, https://static.digihunch.com/wp-content/uploads/2025/04/hidutil-command-1536x796.webp 1536w, https://static.digihunch.com/wp-content/uploads/2025/04/hidutil-command-2048x1061.webp 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Note that the output above has usage values converted to decimal from hexadecimal, with destination on top and source at the bottom.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;I like this solution as it is light-weight, targeting a specific event, highly customizable and resolves an issue in a very specific circumstance.&lt;/p&gt;&#10;&lt;h2 class="wp-block-heading"&gt;Final words&lt;/h2&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter size-full"&gt;&lt;img loading="lazy" decoding="async" width="1024" height="91" src="https://static.digihunch.com/wp-content/uploads/2025/04/K380-layout.webp" alt="" class="wp-image-12868" srcset="https://static.digihunch.com/wp-content/uploads/2025/04/K380-layout.webp 1024w, https://static.digihunch.com/wp-content/uploads/2025/04/K380-layout-300x27.webp 300w, https://static.digihunch.com/wp-content/uploads/2025/04/K380-layout-768x68.webp 768w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /&gt;&lt;figcaption class="wp-element-caption"&gt;K380 layout&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;After all this customization effort, I came across the Logitech &lt;a href="https://www.logitech.com/en-us/products/keyboards/k380-multi-device.920-011135.html"&gt;K380&lt;/a&gt; model (current alternative to K810), whose layout is exactly the way I customized K810 to be. So I ordered the new K380 model for just $29.99 during the week of black Friday. Remembering that I had my K810 for $94.98 back in 2015, what&amp;#8217;s the point of all this&amp;#8230;.&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2022/11/aws-serverless-services-and-developer-tools/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;AWS serverless services and developer tools&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2022/12/landing-zone-in-aws/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Landing Zone in AWS – An Introduction&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>Java Garbage Collection</title><link>https://static.digihunch.com/2020/08/java-garbage-collection/</link><pubDate>Fri, 07 Aug 2020 23:19:17 -0400</pubDate><guid>https://static.digihunch.com/2020/08/java-garbage-collection/</guid><description>&lt;p class="wp-block-paragraph"&gt;Tuning the garbage collector is the most important thing that can be done to improve the performance of a Java application. GC is typically caused when the JVM decides GC is necessary, specifically when:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;a minor GC will be triggered when the new generation is full;&lt;/li&gt;&#10;&lt;li&gt;a full GC will be triggered when the old generation is full;&lt;/li&gt;&#10;&lt;li&gt;a concurrent GC (if applicable) will be triggered when the heap starts to fill up&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;OpenJDK has three collectors suitable for production, with different performance characteristics. In order to study the GC behaviours in application, it is important to turn on GC logging. The detailed step is different in JDK 8 and JDK 11 (read about java version &lt;a href="https://static.digihunch.com/2018/11/the-java-confusions/"&gt;here&lt;/a&gt;).&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Java developers don&amp;#8217;t need to manage life cycle of objects explicitly as the JVM automatically fress the object. In order to track objects that are still in use, it is insufficient to count references to objects. Instead, the JVM must periodically search the heap for unused objects. Once it finds unused objects, the JVM frees the memory occupied by those objects. It also needs to compact the memory to prevent memory fragmentation. The performance of GC is dominated by these basic operations (finding unused objects; freeing up their memory; compacting the heap), no matter which collector is used. Some algorithms delay compaction until absolutely necessary, some compact entire sections of the heap at a time, and some compact the heap by relocating small amounts of memory at a time. These different approaches are why different algorithms have different performance characteristics.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Java programs are typically heavily multithreaded, and the garbage collector itself often runs multiple threads too. We refer to the application logic threads as mutator threads, since they are mutating objects as part of the application logic. When GC threads track object references or move objects around in memory, they must make sure application threads are not using those objects on the move. This introduces a pause when all application threads are stopped (known as stop-the-world pauses), which generally has the greatest impact on the performance of an application. Minimizing those pauses is one important consideration when tuning GC.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-garbage-collectors-are-generational"&gt;Garbage collectors are generational&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Most garbage collectors work by splitting the heap into generations. These are called the old (or tenured) generation, and the young generation, which is further divided into sections known as eden and survivor spaces, with eden taking up the vast majority of the young generation. The rationale for having separate generations is that many objects are used for a very short period of time in the real life of application programming. Garbage collector is designed to take advantage of this. Objects are first allocated in the young generation, which is a subset of the entire heap. When the young generation fills up, the garbage collector will stop all the application threads and empty out the young generation. Objects that are no longer in use are discarded, and objects that are still in use are moved elsewhere. This operation is called a minor GC or a young GC. Common GC algorithms have stop-the-world pauses during collection of the young generation.&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-large"&gt;&lt;img loading="lazy" decoding="async" width="553" height="276" src="https://static.digihunch.com/wp-content/uploads/2020/08/image-9.png" alt="" class="wp-image-1270"/&gt;&lt;figcaption class="wp-element-caption"&gt;Heap Generation&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;This design has two performance advantages. First, Cleaning up young generation as a only a portion of the entire heap causes shorter pause than cleaning up the entire heap. Second, by moving used objects to survivor spaces or old generation, and discarding unused objects, compatction is achieved.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;With used objects moved to the old generation, eventually it woo will fill up, and the JVM will needt o find any objects within the old generation that are no longer in use to discard. This is where GC algorithms have their biggest differences. The simpler alghorithms stop all application threads, find the unused objects, free their memory, and then compact the heap. This process is called a full GC, and it generally causes a relatively long pause for the application threads.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;On the other hand, sophisticated alghrithms are able to find unused objects while application threads are running. These algorithms are called concurrent collectors, or low-pause collectors. A concurrent collector typically allows an application to experience fewer and shorter pauses. The biggest trade-off here is the overall CPU required by the sophisticated algorithms.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-the-three-main-algorithms"&gt;The three main algorithms&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Serial GC is the simplest and the default for single core host (e.g. client-class machine, single-processor VM or Docker container). The serial collector uses a single thread to process the heap. It will stop all application threads as the heap is processed (for either a minor or full GC). During a full GC, it will fully compact the old generation. The serial collector is enabled by using the -XX:+UseSerialGC flag.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The throughput collector (aka parallel collector) is the default collector for any 64-bit machine with two or more CPUs. The throughput collector uses multiple threads to collect the young generation, which makes minor GCs much faster than when the serial collector is used. This uses multiple threads to process the old generation as well. The throughput collector stops all application threads during both minor and full GCs, and it fully compacts the old generation during a full GC. Since it is the default in most situations where it would be used, it needen&amp;#8217;t be expliticly enabled. To enable it where necessary, use the flag -XX:+UseParallelGC&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The G1 GC (or garbage first garbage collector) uses a concurrent collection strategy to collect the heap with minimal pauses. It is the default collector in JDK 11 and later for 64-bit JVMs on machines with two or more CPUs. G1 GC divides the heap into regions, but it still considers the heap to have two generations. Some of those regions make up the young generation, and the young generation is still collected by stopping all application threads and moving all objects that are alive into the old generation or the survisor spaces, using multiple threads. In G1 GC, the old generation is processed by background threads that don&amp;#8217;t need to stop the application threads to perform most of their work.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In G1 GC, the old generation is processed by background threads that don&amp;#8217;t need to stop the application threads to perform most of their work. Because the old generation is divided into regions, G1 GC can clean up objects from the old generation by copying from one region into another, which means that it compacts the heap during normal processing. This helps keep G1 GC heaps from becoming fragmented.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The trade-off for avoiding the full GC cycles is CPU time; the multiple background threads G1 GC uses to process the old generation requires CPU cycles available at the same time the application threads are running. G1 GC is enabled by specifying the flag -XX:+UseG1GC. It is the default in JDK 11, and functional in JDK 8 as well, with some performance feature missing.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In all cases, GC is caused when the JVM decices GC is necessary; a minor GC will be triggered when the new generation is full; a full GC will be triggered when the old generation is full, or a concurrent GC (if applicable) will be triggered when the heap starts to fill up. Java also provides a mechanism for applications to force a GC to occur: the System.gc() method, although it is always a bad idea to call that method explicitly because it triggers a full GC which hangs the application threads. This method can be disabled by including -XX:+DisableExplicitGC in the JVM arguments.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;As to choosing GC algorithm, the rule of thumb is that G1 GC is the better choice. However, in JDK 8, the ability of G1 GC to avoid a full GC is also a key consideration. In this case we may need to choose betwen serial collectors and throughput collectors, based on the number of CPUs on the machine.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The serial collector makes sense when running CPU-bound applications on a machine with a single CPU, even if that single CPU is hyper-threaded. The throughput collector makes sens on multi-CPU machines running jobs that are CPU bound. Even for jobs that are not CPU bound, the throughput collector can be the better choice if it does relatively few full GCs or if the old generation is generally full.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-basic-gc-tuning"&gt;Basic GC tuning&lt;/h3&gt;&#10;&lt;h4 class="wp-block-heading" id="h-sizing-the-heap"&gt;Sizing the heap&lt;/h4&gt;&#10;&lt;p class="wp-block-paragraph"&gt;If the heap is too small, the program will spend too much time performing GC and not enough time performing application logic. On the contrary, a very large heap will increase the time spent in GC pauses, even thought the pauses occur less frequently. It is also potentially dangerous due to interaction with memory swap. If a Java program with a 12 GB heap is running on a system where &lt;a href="https://static.digihunch.com/2018/04/centos-remove-swap-safely/"&gt;swap&lt;/a&gt; is enabled, the OS may handle it by keeping 8GB of the heap in RAM and 4GB on disk. The JVM does not know about this because swapping is handled by the OS. The JVM will happily fill up all 12GB of heap it has been told to use. This can cause a sever performance penalty when OS swaps data from disk to RAM. Worse, the one time this swapping is guaranteed to occur is during a full GC, when the JVM must access the entire heap. Swapping during full GC makes the pause an order of magnitude longer.&lt;br&gt;So heap size (total for all JVMs) should never exceed the amount of physical memory on the machine. Size of heap is controled by two values (Xms as initial value and Xmx as maximum value). Having an initial and maximum size for the heap allows the JVM to tune its behaviour depending on the workload. If the JVM sees that it is doing too much GC, with the initial heap size, it will continually increase the heap until the JVM is doing the &amp;#8220;correct&amp;#8221; amount of GC, or until the heap hits its maximum size.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;A good rule of thumb is to size the heap so that it is 30% occupied after a full GC. To calculate this, start your application and push it to high load. Then connect to the application with jconsole, force a full GC, and observe how much memory is used when the full GC completes.&lt;/p&gt;&#10;&lt;h4 class="wp-block-heading" id="h-sizing-the-generations"&gt;Sizing the generations&lt;/h4&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The JVM must also decide how much of the heap to allocate respectively to they young generation and old generation. THe JVM usually does this automatically and usually does a good job in determining the optimal ratio. In some cases you might hand-tune these values.&lt;br&gt;In general, if there is a relatively larger young generation, young GC pause times will increase, but the young generation will be collected less often, and fewer objects will be promoted into the old genration. But on the other hand, older generation will be relatively smaller and fill up more frequently and do more full GCs. The command-line flag to tune the generation sizes are:&lt;br&gt;-XX:NewRatio=N&lt;br&gt;-XX:NewSize=N&lt;br&gt;-XX:MaxNewSize=N&lt;br&gt;-Xmn N&lt;br&gt;The size of initial young generation is determined by initial heap size and new ratio:&lt;br&gt;Initial Young Gen Size = Initial Heap Size / (1 + NewRatio)&lt;br&gt;The young generation will grow in tandem with the overall heap size, but it can also fluctuate as a percentage of the total heap (based on the initial and maximum size of the young generation). Adaptive sizing controls how the JVM alters the ratio of young genration to old gneeration within the heap. It should be kept enabled in general. For finely tuned heaps, adaptive sizing can be disabled for a small performance boost.&lt;/p&gt;&#10;&lt;h4 class="wp-block-heading" id="h-sizing-the-metaspace"&gt;Sizing the metaspace&lt;/h4&gt;&#10;&lt;p class="wp-block-paragraph"&gt;When the JVM loads classes, it must keep track of certain metadata about those classes. This occupies a separate heap space called the metaspace. In older JVMs this was handled by a different implementation called permgen. To end users, the metaspace is opaque. It does not hold the actual instance of the class. The objects are held in the regular heap. Information in the metaspace is used only by the compiler and JVM runtime, and the data it holds is referred to as class metadata.&lt;br&gt;Tuning the metaspace is fairly rare these days because the default values for the size of metaspace are very generous. It is sized dynamically based on an initial size (-XX:MetaspaceSize=N) and will increase as needed to a maximum size (-XX:MaxMetaspaceSize=N).&lt;br&gt;Resizing the metaspace requires a full GC, so it is an expensive operation. If there are a lot of full GCs during the startup of a program (as it it loading classes), it is often because permgen or metaspace is being resized, so increasing the initial size is a good idea to improve startup in that case.&lt;/p&gt;&#10;&lt;h4 class="wp-block-heading" id="h-controlling-parallelism"&gt;Controlling Parallelism&lt;/h4&gt;&#10;&lt;p class="wp-block-paragraph"&gt;All GC alghorithms except the serial collector use multiple threads. The number of these threads is controlled by the -XX:ParallelGCThreads=N flag. Bacuase these GC operations stop all application threads from executing, the JVM attempts to use as many CPU resources as it can in order to minimize the pause time. By default, that means the JVM will run one thread for each CPU on a machine, up to eight. Once that threashold has reached, the JVM adds new thread for only every 1.6 CPus. Sometimes this number is too large relative to the heap size and hand tuning is needed.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Reference&lt;/strong&gt;: Java Performance by Scott Oaks&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-large is-resized"&gt;&lt;img loading="lazy" decoding="async" src="https://static.digihunch.com/wp-content/uploads/2023/01/java-performance-780x1024.jpeg" alt="" class="wp-image-7911" width="240" height="315" srcset="https://static.digihunch.com/wp-content/uploads/2023/01/java-performance-780x1024.jpeg 780w, https://static.digihunch.com/wp-content/uploads/2023/01/java-performance-229x300.jpeg 229w, https://static.digihunch.com/wp-content/uploads/2023/01/java-performance-768x1008.jpeg 768w, https://static.digihunch.com/wp-content/uploads/2023/01/java-performance.jpeg 1036w" sizes="auto, (max-width: 240px) 100vw, 240px" /&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;a href="https://www.amazon.com/gp/product/1492056111/ref=as_li_ss_il?ie=UTF8&amp;amp;linkCode=li2&amp;amp;tag=glowinghunch-20&amp;amp;linkId=a780d6a00fe93c93bf399c6c9393c806&amp;amp;language=en_US" target="_blank" rel="noopener noreferrer"&gt;&lt;/a&gt;This &lt;a href="https://engineering.linkedin.com/garbage-collection/garbage-collection-optimization-high-throughput-and-low-latency-java-applications"&gt;post&lt;/a&gt; also contains some helpful information, where the original Oracle &lt;a href="https://engineering.linkedin.com/garbage-collection/garbage-collection-optimization-high-throughput-and-low-latency-java-applications"&gt;white paper&lt;/a&gt; about GC was cited. Further than GC, this &lt;a href="https://www.oracle.com/java/technologies/javase/javase-core-technologies-apis.html"&gt;website&lt;/a&gt; from Oracle describes more about JVM.&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2020/08/virtualization-of-graphics-computing-resource/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Virtualization 2 of 4 – Graphics Computing&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2020/08/cloud-storage-overview/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Cloud storage overview&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>Virtualization 1 of 4 – Hypervisor</title><link>https://static.digihunch.com/2020/07/overview-of-virtualization/</link><pubDate>Mon, 27 Jul 2020 22:52:00 -0400</pubDate><guid>https://static.digihunch.com/2020/07/overview-of-virtualization/</guid><description>&lt;p class="wp-block-paragraph"&gt;In broad terms, virtualization of computing resource is about isolation of resources, at different levels. There are five levels of virtualization:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Application level, such as JVM, .NET CLR&lt;/li&gt;&#10;&lt;li&gt;Library (user-level API) level&lt;/li&gt;&#10;&lt;li&gt;Operating system level, such as LXC, Docker, OpenVZ&lt;/li&gt;&#10;&lt;li&gt;Hardware abstraction layer (HAL) level, such as VMware, Xen, etc&lt;/li&gt;&#10;&lt;li&gt;Instruction set architecture (ISA) level&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In my context I deal mostly with OS level and HAL (hardware abstraction layer) level of virtualization. In loose terms, the word &lt;em&gt;containerization&lt;/em&gt; refers to &lt;span style="text-decoration: underline;"&gt;OS level virtualization&lt;/span&gt;, while the word &lt;em&gt;virtualization&lt;/em&gt; is exclusively reserved for &lt;span style="text-decoration: underline;"&gt;HAL level virtualization&lt;/span&gt;, also referred to as &lt;span style="text-decoration: underline;"&gt;hypervisor-based virtualization&lt;/span&gt;. This post will just focus on this family of technology and loosely refers to it as virtualization.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Virtualization technology evolved from on-premise data centre environment and now is the backbone of cloud computing. The challenges of IT operation in the era of virtualization involves managing VM sprawling, investigating performance issues, planning capacity and addressing storage I/O block. The idea of virtualization is sharing (thus isolating) resources for better utilization, leading to better return on investment. This posting is to cover only the very basics of virtualization.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-hypervisor"&gt;Hypervisor&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Hypervisor is the software layer which provides the capability to run multiple virtual machines on the same physical host. It is broken down into two categories:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;&lt;strong&gt;Type I hypervisor (aka bare metal hypervisor)&lt;/strong&gt;: directly run on physical hardware. They control the hardware as well as manage the virtual machines. For example, Linux KVM, VMware ESXi, Xen and Microsoft Hyper-V&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Type II hypervisor&lt;/strong&gt;: runs as an application or service on top of the host operating system, which is installed on the bare metal. Guest operating system calls need to traverse via the host operating system stack to reach hardware resource. For example, Oracle Virtual Box, VMware Fusion and Linux Containers (LXC)&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter"&gt;&lt;img decoding="async" src="https://img.vembu.com/wp-content/uploads/2019/12/Hypervisor-Types.png" alt="Type-1 vs Type-2 Hypervisor"/&gt;&lt;figcaption class="wp-element-caption"&gt;Hypervisor Types&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;h3 class="wp-block-heading" id="h-virtualization-techniques"&gt;Virtualization Techniques&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The most primitive form of technology that can be arguably categorized under virtualization is hardware emulation, where a piece of (more accessible) hardware imitates another (less accessible). The architecture limits itself in functional testing only, and is not built for performance or production at all.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The original virtualization technology deals with CPU and memory virtualization. In this well-written &lt;a href="https://github.com/skonstantinov89/books/blob/master/Understanding%20Full%20Virtualization%2C%20Paravirtualization%2C%20and%20Hardware%20Assist.pdf"&gt;whitepaper &lt;/a&gt;fromVMware, there are three CPU virtualization techniques introduced for x86 architecture.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The x86 architecture offers four levels of privilege known as Ring 0,1,2 and 3 to operating system and applications to manage access to the computer hardware. User-level applications typically run in Ring 3, the OS must execute its privileged instructions in Ring 0 since it needs to have direct access to memory and hardware. The two main challenges with virtualizing x86 architecture are:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;A virtualization layer between hardware operating system who expects Ring 0 privilege;&lt;/li&gt;&#10;&lt;li&gt;Some instructions with different semantics when not executed in Ring 0 cannot be virtualized effectively. They need to be translated at runtime.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;These challenges makes true virtualization of x86 architecture impossible and thus VMware developed three alternative technologies.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;a href="https://en.wikipedia.org/wiki/Full_virtualization"&gt;&lt;strong&gt;Full virtualization&lt;/strong&gt;&lt;/a&gt; (using binary translation): virtual machine presents a complete simulation of the actual hardware environment so that an unmodified guest OS can run in isolation. The Guest OS is not aware that the underlying environment it is running on is virtualized, and issues hardware calls to communicate with (what it thinks as) hardware. The virtual processors have to understand guest CPU instruction, and reproduce the equivalent CPU instructions of the host machine. VMware&amp;#8217;s technology to address this is called &lt;strong&gt;Binary Translation&lt;/strong&gt;. This overhead makes true full virtualization difficult to achieve. In real life, a virtual environment that provides &amp;#8220;enough representation of the underlying hardware&amp;#8221; can be considered to provide full virtualization as long as it allows guest OS to run without modification. Full virtualization comes with a performance penalty. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;a href="https://en.wikipedia.org/wiki/Paravirtualization"&gt;&lt;strong&gt;Paravirtualization &lt;/strong&gt;&lt;/a&gt;(aka OS assisted virtualization): refers to communication between the guest OS and the hypervisor to improve performance and efficiency. In this technology, guest OS is modified with an interface to host hardware to be able to communicate and operate seamlessly. Since the guest OS is modified, the VM does not need to be a complete simulation of the hardware. The modified guest OS knows it is running on a virtualized environment, and (vm driver) makes API calls (known as &amp;#8216;hyper calls&amp;#8217;) to the hypervisor. This allows para-virtualization technology to achieve performance closer to non-virtualized environment. However, since paravirtualization cannot support unmodified operating systems, its compatibility and portability is poor. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;a href="https://en.wikipedia.org/wiki/Hardware-assisted_virtualization"&gt;&lt;strong&gt;Hardware-Assisted Virtualization&lt;/strong&gt;&lt;/a&gt;: hardware vendors such as Intel and AMD both have developed extensions (new features) to simplify virtualization techniques, for example, the introduction of privileged instructions with new CPU execution mode feature to allow hypervisor to run in a new root mode below ring 0. This removed the need for full virtualization and paravirtualization. With VMware originally as a promoter of full virtualization and Xen for paravirtualization, most virtualization technologies today utilizes hardware-assisted virtualization feature, for example, Linux KVM, VMware workstation, VMware fusion, Xen, VirtualBox, etc. Intel&amp;#8217;s virtualization extension is VT-x. AMD&amp;#8217;s counterpart is AMD-V technology.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;To virtualize memory, another level of memory virtualization is required (similar to the virtual memory support in Linux). Hypervisor is responsible for mapping guest physical memory to the actual machine memory, and it uses shadow page tables to accelerate the mappings, usually at a performance cost.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-popular-hypervisors"&gt;Popular hypervisors&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;On the market there are a few popular hypervisor technologies. They are all type 1 hypervisors:&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;a href="https://en.wikipedia.org/wiki/Xen"&gt;Xen &lt;/a&gt;is an open-source &lt;a href="https://xenproject.org/"&gt;hypervisor project&lt;/a&gt; originally developed in Cambridge University, licensed under GPLv2. . Based on that, Citrix developed its commercial product XenServer, a bare-metal virtualization platform with enterprise-grade features for x86 and AMD environments. Oracle VM is another commercial implementation of Xen. The Xen project also supports many cloud platforms such as Openstack, Cloudstac, etc. Xen project supports paravirtualization (Xen-PV) as well as hardware-assisted virtualization (Xen-HVM) for virtualization of X86, IA64, ARM and other CPU architectures. The earlier versions does not support memory overcommit (aka &amp;#8220;dynamic memory optimization&amp;#8221;, &amp;#8220;memory &lt;a href="https://static.digihunch.com/2020/05/understanding-where-the-memory-goes-on-linux-vm/"&gt;ballooning&lt;/a&gt;&amp;#8220;, or as Citrix calls it &amp;#8220;dynamic memory control, DMC&amp;#8221;). This delivers better performance but also has higher budgetary requirement on hardware since there isn&amp;#8217;t room for over-subscription. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Hyper-V is a Microsoft product. It executes in high CPU privilege (Microsoft calls it ring -1 which is equivalent to root mode as Intel calls it). On the guest VM, OS kernel and drivers run in ring 0, application rin in ring 3. This eliminates the need for binary translation. Hyper-V does not support memory overcommit either. Hyper-V is well integrated with Windows platform. It supports Linux as well although with some performance penalty.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Linux KVM (Kernel-based Virtual Machine) is a full open-source virtualization solution for GNU/Linux. What makes KVM a special hypervisor is that it uses a loadable kernel module kvm.ko that turns itself into a hypervisor and provides VMs with direct access to the hardware. So it is a type 1 hypervisor despite of the presence of Linux OS. KVM also contains a processor specific module, kvm-intel.ko or kvm-amd.ko. KVM leverages qemu to access devices. Because KVM runs as a process inside of Linux OS, KVM can use many existing feature in Linux kernel. Redhat has an enterprise solution based on KVM.&lt;/p&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter size-full"&gt;&lt;img loading="lazy" decoding="async" width="850" height="414" src="https://static.digihunch.com/wp-content/uploads/2023/01/Comparison-of-Xen-KVM-and-QEMU.png" alt="" class="wp-image-7813" srcset="https://static.digihunch.com/wp-content/uploads/2023/01/Comparison-of-Xen-KVM-and-QEMU.png 850w, https://static.digihunch.com/wp-content/uploads/2023/01/Comparison-of-Xen-KVM-and-QEMU-300x146.png 300w, https://static.digihunch.com/wp-content/uploads/2023/01/Comparison-of-Xen-KVM-and-QEMU-768x374.png 768w" sizes="auto, (max-width: 850px) 100vw, 850px" /&gt;&lt;figcaption class="wp-element-caption"&gt;Xen vs KVM&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;VMware &lt;a href="https://en.wikipedia.org/wiki/VMware_ESXi"&gt;ESXi &lt;/a&gt;is VMware&amp;#8217;s premium hypervisor product (not open-source) and is available for &lt;s&gt;free download&lt;/s&gt;, although the advanced features are not free. (Update no free download link &lt;a href="https://www.reddit.com/r/vmware/comments/1amtzvc/esxi_hypervisor_free_gone/"&gt;anymore&lt;/a&gt;.) VMware &lt;a href="https://static.digihunch.com/2018/07/overview-of-vsphere/"&gt;vSphere&lt;/a&gt; is virtualization platform built on top of ESXi, including a whole family of virtualization products.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-market-segments-and-players"&gt;Market segments and players&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Virtualization involves many market segments such as virtual desktop infrastructure (VDI, for desktop virtualization), server virtualization is the predominant domain in the virtualization of data centre environment. This effort led to Hyper-Converged Infrastructure (HCI) where almost all the traditional hardware resources are software-defined through the virtualization layer. The management of infrastructure is abstracted away from the physical hardware management. The three most fundamental areas in HCI are:&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Server (compute) virtualization: the previous section covers the virtualization of memory and x86 CPU, which are the main focus on computing resource virtualization. Additionally, graphics computing resources can be virtualized today. Example products include: VMware vShpere (compute virtualization based on ESXi hypervisor).&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;&lt;a href="https://en.wikipedia.org/wiki/Storage_virtualization"&gt;Storage Virtualization&lt;/a&gt;&lt;/strong&gt;: the technology to abstract physical data storage resource to make them appear as if they were a centralized resource. Storage virtualization takes place at three levels depending on the use case: block-level, file-level and object level. Example products include: VMWare vSAN (vSphere-native storage), HPE 3PAR (Tier-1 storage), EMC VxRail, PureStorage Flash Array (Tier 1), etc. Storage Virtualization enables &lt;a href="https://en.wikipedia.org/wiki/Software-defined_storage"&gt;&lt;strong&gt;Software-Defined Storage&lt;/strong&gt; &lt;/a&gt;&lt;strong&gt;(SDS)&lt;/strong&gt;, the provisioning and management of data storage independent of the underlying hardware.&amp;nbsp;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;&lt;a href="https://en.wikipedia.org/wiki/Network_virtualization"&gt;Network Virtualization&lt;/a&gt;&lt;/strong&gt;: the technology to abstract network resources that were traditionally delivered in hardware to software. Network virtualization decouples network services from the underlying hardware management and allows virtual provisioning of an entire network. VLAN is a classic example of network virtualization. There are also various overlay technologies such as VXLAN, which provides an industry framework for overlaying virtualized layer 2 network over layer 3 network (used in Docker network) using an encapsulation mechanism and a control plane. Example products include: VMware NSX Data Center (L2-L7 network and security virtualization platform), Cisco ACI, Palo Alto Panorama. Network Virtualization enables &lt;strong&gt;&lt;a href="https://en.wikipedia.org/wiki/Software-defined_networking"&gt;Software-Defined Network&lt;/a&gt; (SDN)&lt;/strong&gt;, an approach to network management that enables dynamic, programmatically efficient network configuration in order to improve network performance and monitoring, making it more like cloud computing than traditional network management.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-delivery-model"&gt;Delivery model&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Virtualization allows managed service providers (MSPs) to deliver IT service in the following three models:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;&lt;strong&gt;Iaas (Infrastructure as a Service)&lt;/strong&gt;: MSP delivers VM to customers.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;PaaS (Platform as a Service)&lt;/strong&gt;: MSP delivers environments to customers (e.g. Database as a Service, managed RabbitMQ service, etc).&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;SaaS (Software as a Service)&lt;/strong&gt;: MSP delivers entire application for the customer.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter is-resized"&gt;&lt;img decoding="async" src="https://www.redhat.com/cms/managed-files/iaas_focus-paas-saas-diagram-1200x1046.png" alt="What is IaaS?" style="width:608px;height:388px"/&gt;&lt;figcaption class="wp-element-caption"&gt;IT service delivery models enabled by virtualization technology&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Since virtualization is the backbone of cloud computing. This model is also referred to as cloud computing delivery model.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-virtualization-and-containerization"&gt;Virtualization and Containerization&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;These two concepts are similar and could be confusing to beginners. Both provide a mechanism to isolate computing resource for different applications, for the purpose of higher utilization of resource. The difference lies in how and where the isolation is made. Virtualization requires a guest operating system per VM (OS level isolation), whereas the container technology isolates application processes along with its runtime into a container (dependency level isolation), using some new Linux kernel features such as &lt;em&gt;namespaces &lt;/em&gt;and &lt;em&gt;cgroups&lt;/em&gt;. All containers make their system calls to the container engine on the host operating system. So they share a kernel on the same host. In this sense, container engine running on OS could be considered as type 2 hypervisor.&lt;/p&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img decoding="async" src="https://dzone.com/storage/temp/10561741-vm-container-figure1.jpg" alt="Image title"/&gt;&lt;figcaption class="wp-element-caption"&gt;From VMs to containers&lt;/figcaption&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;VMware is a major player in enterprise data centre virtualization, which is facing fierce competition from public and private cloud vendors. VMware also has its own private cloud services. Docker is the most popular container technology that conforms to the specifications of Open Container Initiative (OCI), a governance structure for industry standards around container formats and runtimes.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-virtualization-and-cloud"&gt;Virtualization and Cloud&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Among public cloud vendors, AWS &lt;a href="https://cloudacademy.com/blog/aws-ami-hvm-vs-pv-paravirtual-amazon/"&gt;EC2 &lt;/a&gt;used Xen PV and Xen HVM in its earlier implementations. It has transitioned to AWS bare metal. The history is well summarized &lt;a href="http://www.brendangregg.com/blog/2017-11-29/aws-ec2-virtualization-2017.html"&gt;here&lt;/a&gt;. Microsoft Azure runs Azure Hypervisor as the native hypervisor in Azure Cloud Services platform. It is a customized version of Microsoft Hyper-V specifically for Azure platform. With GCP, Google &lt;a href="https://cloud.google.com/compute/docs/faq"&gt;Compute Engine&lt;/a&gt; (GCE) instance runs VMs on KVM as hypervisor. It can also enable nested virtualization.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The scope of cloud computing is evolving overtime. It originally only refers to a business model of offering IT services (in one of the three delivery models outlined above) based on virtualization technology. Therefore I cannot make comparison between a technology and a business model. Today, with public cloud vendor extending their offerings (with various managed services and platforms) and people&amp;#8217;s misuse of the terms, the buzz-word &amp;#8220;cloud&amp;#8221; seems to suggest anything that is offered in public cloud service. The essence still remain the same where managed services and managed platforms are built on top of virtualized compute unit under the hood, which are driven by virtualization technologies.&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2020/07/zookeeper-and-kafka-overview/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Kafka high-level Overview&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2020/08/virtualization-of-graphics-computing-resource/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Virtualization 2 of 4 – Graphics Computing&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>Setup WSL2 (and Docker) on Windows 10</title><link>https://static.digihunch.com/2020/06/wsl2-environment-on-windows-10/</link><pubDate>Tue, 02 Jun 2020 22:01:00 -0400</pubDate><guid>https://static.digihunch.com/2020/06/wsl2-environment-on-windows-10/</guid><description>&lt;p class="wp-block-paragraph"&gt;This is not for Linux snobs, but rather for those who are stuck with a Windows work laptop, have to deal with Linux on a daily basis, and are not a fan of PuTTY. This posting provides the steps to setup Windows 10 so you get a work environment closer to a Linux one. The environment to begin with should be Windows 10 version 2004 and above in order to use WSL2. &lt;a href="https://docs.microsoft.com/en-us/windows/wsl/compare-versions"&gt;Here&amp;#8217;s &lt;/a&gt;the comparison between WSL and WSL2. This &lt;a href="https://www.youtube.com/watch?v=lwhMThePdIo"&gt;presentation &lt;/a&gt;is a great deep dive into how WSL2 works. The architecture diagram below is from that presentation. Note that WSL2 operates on a &amp;#8220;true&amp;#8221; Linux Kernel, therefore giving WSL2 the ability to run Docker.&lt;/p&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img decoding="async" src="https://4.bp.blogspot.com/-e_FaEsP7nH8/Xca4QMFtjQI/AAAAAAAAERA/r59YN5UCXlwdNsfPNy-sjjyTQ4o_dtbjACLcBGAsYHQ/s1600/wsl1-wsl2.png" alt=""/&gt;&lt;/figure&gt;&#10;&lt;h3 class="wp-block-heading" id="h-install-wsl2"&gt;Install WSL2&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;WSL2 was officially released in Windows 10 version 2004 (build 19041 or higher) and we will use Ubuntu 20.04 LTS. If you&amp;#8217;re upgraded from older version of Windows 10 you will need to upgrade. The steps are:&lt;/p&gt;&#10;&lt;ol class="wp-block-list"&gt;&#10;&lt;li&gt;Install Ubuntu 20.04 LTS from Microsoft Store, which requires Windows components &amp;#8220;Windows Subsystem for Linux&amp;#8221; and &amp;#8220;Virtual Machine Platform&amp;#8221;; or, if you already have an older version of Ubuntu such as 18.04, you will need to run a distribution upgrade with &amp;#8220;sudo apt-get dist-upgrade&amp;#8221;;&lt;/li&gt;&#10;&lt;li&gt;Upgrade Linux Virtual Machine from WSL to WSL2, following the official instruction &lt;a href="https://docs.microsoft.com/en-us/windows/wsl/install-win10"&gt;here&lt;/a&gt;; Once completed, use this command to confirm the WSL version installed: wsl.exe &amp;#8211;list -v&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;div class="wp-block-image"&gt;&#10;&lt;figure class="aligncenter size-large is-resized"&gt;&lt;img loading="lazy" decoding="async" width="634" height="104" src="https://static.digihunch.com/wp-content/uploads/2020/06/image-1.png" alt="" class="wp-image-1056" style="width:317px;height:52px"/&gt;&lt;/figure&gt;&#10;&lt;/div&gt;&#10;&lt;p class="wp-block-paragraph"&gt;There&amp;#8217;s also plenty of Youtube videos with step-by-step instruction on upgrading to WSL2 and its advantage over WSL. Once you&amp;#8217;re there, you will realize one problem: the command terminal for Ubuntu is ugly:&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-large"&gt;&lt;img loading="lazy" decoding="async" width="2318" height="622" src="https://static.digihunch.com/wp-content/uploads/2020/06/image.png" alt="" class="wp-image-1055"/&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The colour looks awful and it does not support multi-tabs. If you want better palette, there are a number of options. Check out &lt;a href="https://github.com/Microsoft/Terminal/tree/master/src/tools/ColorTool"&gt;ColorTool&lt;/a&gt; project and &lt;a href="https://github.com/mbadolato/iTerm2-Color-Schemes"&gt;iTerms2 Colors&lt;/a&gt; project. The former gives you away to configure color scheme (from command prompt but takes effect in WSL as well) and the latter gives you rich choices of color schemes. My personal favourite is &amp;#8220;Banana Blueberry&amp;#8221;. The command to set color scheme is: &lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;C:\ColorTool.exe -b &amp;#34;iTerm2-Color-Schemes-master\schemes\Banana Blueberry.itermcolors&amp;#34;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 class="wp-block-heading" id="h-windows-terminal"&gt;Windows Terminal&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;For a better terminal, consider Windows Terminal from Microsoft Store. &lt;a href="https://github.com/microsoft/terminal"&gt;Windows terminal&lt;/a&gt; is an open-source project and still a little &lt;a href="https://github.com/microsoft/terminal/issues/4448"&gt;glitchy&lt;/a&gt; as of June 2020. However it is heading to the right direction. Once installed, you may customize it by clicking settings:&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-large"&gt;&lt;img loading="lazy" decoding="async" width="1066" height="412" src="https://static.digihunch.com/wp-content/uploads/2020/06/image-3.png" alt="" class="wp-image-1058"/&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;A json file will open and you may edit it for customization, for example, you can adjust each profile (e.g. PowerShell, Windows command or WSL); you can specify default profile and default open location. &lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// This file was initially generated by Windows Terminal 1.0.1401.0&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// It should still be usable in newer versions, but newer versions might have additional&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// settings, help text, or changes that you will not see unless you clear this file&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// and let us generate a new one for you.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// To view the default settings, hold &amp;#34;alt&amp;#34; while clicking on the &amp;#34;Settings&amp;#34; button.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// For documentation on these settings, see: https://aka.ms/terminal-documentation&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;{&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;$schema&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;https://aka.ms/terminal-profiles-schema&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;defaultProfile&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;{2c4de342-38b7-51cf-b940-2309a097f518}&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// You can add more global application settings here.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// To learn more about global settings, visit https://aka.ms/terminal-global-settings&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// If enabled, selections are automatically copied to your clipboard.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;copyOnSelect&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// If enabled, formatted data is also copied to your clipboard&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;copyFormatting&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// A profile specifies a command to execute paired with information about how it should look and feel.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Each one of them will appear in the &amp;#39;New Tab&amp;#39; dropdown,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// and can be invoked from the commandline with `wt.exe -p xxx`&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// To learn more about profiles, visit https://aka.ms/terminal-profile-settings&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;profiles&amp;#34;&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;defaults&amp;#34;&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Put settings here that you want to apply to all profiles.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;list&amp;#34;&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;guid&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;{2c4de342-38b7-51cf-b940-2309a097f518}&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;hidden&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Ubuntu&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;source&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Windows.Terminal.Wsl&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;startingDirectory&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;//wsl$/Ubuntu/home/myuser/&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Make changes here to the powershell.exe profile.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;guid&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;{61c54bbd-c2c6-5271-96e7-009a87ff44bf}&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Windows PowerShell&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;commandline&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;powershell.exe&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;hidden&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Make changes here to the cmd.exe profile.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;guid&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;{0caa0dad-35be-5f56-a8ff-afceeeaa6101}&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Command Prompt&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;commandline&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;cmd.exe&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;hidden&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; {&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;guid&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;{b453ae62-4e3d-5e58-b989-0a998ec441b8}&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;hidden&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Azure Cloud Shell&amp;#34;&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;source&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;Windows.Terminal.Azure&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; },&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Add custom color schemes to this array.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// To learn more about color schemes, visit https://aka.ms/terminal-color-schemes&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;schemes&amp;#34;&lt;/span&gt;: &lt;span style="color:#f92672"&gt;[]&lt;/span&gt;,&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Add custom keybindings to this array.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// To unbind a key combination from your defaults.json, set the command to &amp;#34;unbound&amp;#34;.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// To learn more about keybindings, visit https://aka.ms/terminal-keybindings&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#e6db74"&gt;&amp;#34;keybindings&amp;#34;&lt;/span&gt;:&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;[&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Copy and paste are bound to Ctrl+Shift+C and Ctrl+Shift+V in your defaults.json.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// These two lines additionally bind them to Ctrl+C and Ctrl+V.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// To learn more about selection, visit https://aka.ms/terminal-selection&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; { &lt;span style="color:#e6db74"&gt;&amp;#34;command&amp;#34;&lt;/span&gt;: {&lt;span style="color:#e6db74"&gt;&amp;#34;action&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;copy&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;singleLine&amp;#34;&lt;/span&gt;: &lt;span style="color:#66d9ef"&gt;false&lt;/span&gt; }, &lt;span style="color:#e6db74"&gt;&amp;#34;keys&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;ctrl+c&amp;#34;&lt;/span&gt; },&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; { &lt;span style="color:#e6db74"&gt;&amp;#34;command&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;paste&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;keys&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;ctrl+v&amp;#34;&lt;/span&gt; },&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Press Ctrl+Shift+F to open the search box&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; { &lt;span style="color:#e6db74"&gt;&amp;#34;command&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;find&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;keys&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;ctrl+shift+f&amp;#34;&lt;/span&gt; },&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// Press Alt+Shift+D to open a new pane.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// - &amp;#34;split&amp;#34;: &amp;#34;auto&amp;#34; makes this pane open in the direction that provides the most surface area.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// - &amp;#34;splitMode&amp;#34;: &amp;#34;duplicate&amp;#34; makes the new pane use the focused pane&amp;#39;s profile.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#75715e"&gt;// To learn more about panes, visit https://aka.ms/terminal-panes&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; { &lt;span style="color:#e6db74"&gt;&amp;#34;command&amp;#34;&lt;/span&gt;: { &lt;span style="color:#e6db74"&gt;&amp;#34;action&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;splitPane&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;split&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;auto&amp;#34;&lt;/span&gt;, &lt;span style="color:#e6db74"&gt;&amp;#34;splitMode&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;duplicate&amp;#34;&lt;/span&gt; }, &lt;span style="color:#e6db74"&gt;&amp;#34;keys&amp;#34;&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;alt+shift+d&amp;#34;&lt;/span&gt; }&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;]&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;With these configuration, we have a quite comfortable Linux work environment on Windows.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-update-to-zsh-and-beautify-it"&gt;Update to Zsh and beautify it&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;I&amp;#8217;m no so big a fan of zsh (for lack of default &lt;a href="https://superuser.com/questions/584249/using-wildcards-in-commands-with-zsh/740728"&gt;wildcard support&lt;/a&gt;) but I do like one of its themes. We can install zsh on WSL2 (assuming Ubuntu distribution). This is a good &lt;a href="https://blog.nillsf.com/index.php/2020/02/17/setting-up-wsl2-windows-terminal-and-oh-my-zsh/"&gt;instruction&lt;/a&gt;. I do like the theme name agnoster. However, the theme displays username at the beginning of the prompt, which takes a lot of screen real estate if your username is long. To remove it, the trick is to add a line in ~/.zshrc, as answered in &lt;a href="https://stackoverflow.com/questions/28491458/zsh-agnoster-theme-showing-machine-name/38295938#:~:text=You%20can%20set%20DEFAULT_USER%3D%22%5B,the%20%5Buser%20name%5D%20value.&amp;amp;text=This%20will%20negate%20the%20%22%24user%22%20!%3D"&gt;this&lt;/a&gt; thread. &lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-docker-runtime"&gt;Docker runtime&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;There is a lot of fun to have in WSL2 on Windows 10. For example, you can configure Docker runtime on Windows according to &lt;a href="https://nickjanetakis.com/blog/a-linux-dev-environment-on-windows-with-wsl-2-docker-desktop-and-more"&gt;this post&lt;/a&gt;. However, you cannot route traffic to the container in the absence of docker0 bridge for Docker on WSL2, as indicated in the &lt;a href="https://docs.docker.com/desktop/windows/networking/#known-limitations-use-cases-and-workarounds"&gt;known limitations&lt;/a&gt;.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Update: Docker also brings a Kubernetes cluster named docker-desktop. This allows you configure Kubernetes cluster, or install &lt;a href="https://static.digihunch.com/2021/07/helm-configuration-management-for-kubernetes-resources/"&gt;Helm&lt;/a&gt; and Rancher (&lt;a href="https://rafalfaro.medium.com/how-to-install-rancher-2-5-in-docker-desktops-bundled-kubernetes-cluster-ebd5e1b0ae8"&gt;instruction&lt;/a&gt;) for cluster management.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-dual-boot"&gt;Dual-Boot?&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;With WSL2 on top of a real Linux kernel, I do not find a need for a dual-boot system on my workstation. To be fair, only in the following scenarios should one consider installing a dual-boot system.&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;You need to work on a specify version of Linux Kernel. The kernel provided by Microsoft is called &amp;#8220;microsoft-standard-WSL2&amp;#8221;, and its pretty up to date (5.x)&lt;/li&gt;&#10;&lt;li&gt;You need to run GUI applications on Linux. Update: Microsoft has started developing GUI application support on WSL2, even though it usually takes time to mature.&lt;/li&gt;&#10;&lt;li&gt;You need to work on a distribution not available in Windows Store. WSL2 provides a kernel and it&amp;#8217;s up to developers to provide Linux distros in Windows store. Popular (and official) ones are: Ubuntu 20.04 LTS by Canonical Group, Debian by the Debian project, SUSE Linux Enterprise Server by SUSE, Kali Linux.&lt;/li&gt;&#10;&lt;li&gt;&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 class="wp-block-heading"&gt;Certificate Issuers&lt;/h2&gt;&#10;&lt;p class="wp-block-paragraph"&gt;I have to use WSL2 mostly because I&amp;#8217;m forced to use a Windows laptop on my contracts. That also means that the Windows laptop has been configured to corporate firewall&amp;#8217;s packet inspection. When that is the case, they corporate IT usually automatically imports a firewall certificate to the Windows trust store. However, the WSL is missing this certificate. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The symptom would be that you cannot run certain curl command. For example, when I do the followings:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl -LO &lt;span style="color:#e6db74"&gt;&amp;#34;https://dl.k8s.io/release/&lt;/span&gt;&lt;span style="color:#66d9ef"&gt;$(&lt;/span&gt;curl -L -s https://dl.k8s.io/release/stable.txt&lt;span style="color:#66d9ef"&gt;)&lt;/span&gt;&lt;span style="color:#e6db74"&gt;/bin/linux/amd64/kubectl&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl: &lt;span style="color:#f92672"&gt;(&lt;/span&gt;60&lt;span style="color:#f92672"&gt;)&lt;/span&gt; SSL certificate problem: unable to get local issuer certificate&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;More details here: https://curl.se/docs/sslcerts.html&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;curl failed to verify the legitimacy of the server and therefore could not&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;establish a secure connection to it. To learn more about this situation and&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;how to fix it, please visit the web page mentioned above. &#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;This error message basically means that the website certificate cannot be trusted. To view the certificate, use Open SSL command:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;openssl s_client -connect dl.k8s.io:443 -servername dl.k8s.io | openssl x509 -text -noout | less&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;In my case, I noticed that the certificate is a Zscaler issued certificate (firewall). While running the same command from my personal device returns a Goolge Trust issued certificate. This indicates that the certificate is changed by the proxy managed by the corporation. To fix this I need to export the certificate from Windows, and then import it in WSL. The &lt;a href="https://stackoverflow.com/questions/72167566/wsl-docker-curl-60-ssl-certificate-problem-unable-to-get-local-issuer-certi"&gt;answer&lt;/a&gt; in this post has good detailed steps.&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2020/05/ansible-directory-for-scalability-2-of-2/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Ansible at scale 2 of 2&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2020/06/network-analyzer-capture-filter-and-display-filter/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Capture filter and Display filter in Network Analyzer&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>NTLM and Kerberos protocols</title><link>https://static.digihunch.com/2020/03/ntlm-and-kerberos/</link><pubDate>Wed, 25 Mar 2020 20:33:00 -0400</pubDate><guid>https://static.digihunch.com/2020/03/ntlm-and-kerberos/</guid><description>&lt;p class="wp-block-paragraph"&gt;This article explains how two most common authentication mechanisms (NTLM and Kerberos) work. Both authentication protocols are based on symmetric key cryptography. The protocols themselves are platform independent. &lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-ntlm-authentication"&gt;NTLM Authentication&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;NTLM is the default authentication protocol prior to Windows 2000 and still prevalent today as backup to Kerberos. It is based on challenge/response mechanism.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="690px" viewBox="-0.5 -0.5 690 392" style="max-width:100%;max-height:392px;"&gt;&lt;defs&gt;&lt;/defs&gt;&lt;g&gt;&lt;rect x="0" y="0" width="689" height="391" fill="#f5f5f5" stroke="#666666" pointer-events="all"&gt;&lt;/rect&gt;&lt;rect x="464" y="27" width="47" height="50" fill="none" stroke="none" pointer-events="all"&gt;&lt;/rect&gt;&lt;path d="M 477.44 41.39 C 477.36 37.61 478.62 33.96 480.93 31.25 C 483.23 28.55 486.39 27.01 489.69 27 C 497.05 27.08 503.05 33.48 503.32 41.54 C 503.6 45.24 502.49 48.91 500.24 51.69 C 498 54.46 494.83 56.1 491.46 56.23 C 484.01 56.39 477.79 49.81 477.44 41.39 Z M 464 77 C 464.3 69.97 466.88 63.42 471.14 58.94 C 474.51 55.56 479.21 55.36 482.75 58.44 C 484.77 59.95 486.99 61.17 489.35 62.06 C 491.76 63.12 494.41 62.94 496.73 61.56 C 498 60.94 499.12 60.04 500.03 58.94 C 500.92 57.86 502.47 57.64 503.62 58.44 C 505.64 59.81 507.46 62.24 508.88 65.48 C 510.26 69.16 510.98 73.05 511 76.99 Z" fill="#00188d" stroke="none" pointer-events="all"&gt;&lt;/path&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 84px; margin-left: 488px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; "&gt;User&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="488" y="96" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;User&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="82" y="31" width="144" height="57" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 142px; height: 1px; padding-top: 60px; margin-left: 83px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 14px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; "&gt;Client&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="154" y="64" fill="#000000" font-family="Helvetica" font-size="14px" text-anchor="middle" font-weight="bold"&gt;Client&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="82" y="253" width="144" height="120" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 142px; height: 1px; padding-top: 313px; margin-left: 83px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 14px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; "&gt;Server&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="154" y="317" fill="#000000" font-family="Helvetica" font-size="14px" text-anchor="middle" font-weight="bold"&gt;Server&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 464.21 59.5 L 232.37 59.5" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 469.46 59.5 L 462.46 63 L 464.21 59.5 L 462.46 56 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 227.12 59.5 L 234.12 56 L 232.37 59.5 L 234.12 63 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 48px; margin-left: 360px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 14px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; "&gt;Log on&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="360" y="52" fill="#000000" font-family="Helvetica" font-size="14px" text-anchor="middle"&gt;Log on&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="528" y="252" width="120" height="120" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 259px; margin-left: 529px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 14px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; "&gt;Domain Controller&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="588" y="273" fill="#000000" font-family="Helvetica" font-size="14px" text-anchor="middle" font-weight="bold"&gt;Domain Controller&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 548 314 C 548 298 628 298 628 314 L 628 350 C 628 366 548 366 548 350 Z" fill="#ffffff" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 548 314 C 548 326 628 326 628 314" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 78px; height: 1px; padding-top: 341px; margin-left: 549px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 14px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "&gt;Active Directory&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="588" y="345" fill="#000000" font-family="Helvetica" font-size="14px" text-anchor="middle"&gt;Active Dire&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 118 253 L 118 94.37" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 118 89.12 L 121.5 96.12 L 118 94.37 L 114.5 96.12 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;g transform="translate(-0.5 -0.5)rotate(-90 104.5 161.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 162px; margin-left: 105px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 14px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; "&gt;(2) Challenge&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="105" y="166" fill="#000000" font-family="Helvetica" font-size="14px" text-anchor="middle"&gt;(2) Challenge&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 154 88 L 154 246.63" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 154 251.88 L 150.5 244.88 L 154 246.63 L 157.5 244.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;g transform="translate(-0.5 -0.5)rotate(-90 141.5 161.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 162px; margin-left: 142px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 14px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; "&gt;(3) Response&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="142" y="166" fill="#000000" font-family="Helvetica" font-size="14px" text-anchor="middle"&gt;(3) Response&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 82 59.5 L 51 59.88 Q 41 60 41 70 L 41 303 Q 41 313 51 313 L 75.63 313" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 80.88 313 L 73.88 316.5 L 75.63 313 L 73.88 309.5 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;g transform="translate(-0.5 -0.5)rotate(-90 25.5 175.4969513328582)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 175px; margin-left: 26px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 14px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; "&gt;(1) Username&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="26" y="180" fill="#000000" font-family="Helvetica" font-size="14px" text-anchor="middle"&gt;(1) Username&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 226 283 L 521.63 282.02" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 526.88 282 L 519.89 285.53 L 521.63 282.02 L 519.87 278.53 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 266px; margin-left: 376px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 14px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; "&gt;(4) Challenge from (2) and Response from (3)&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="376" y="271" fill="#000000" font-family="Helvetica" font-size="14px" text-anchor="middle"&gt;(4) Challenge from (2) and Response from (3)&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 528 342 L 232.37 342.98" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 227.12 343 L 234.11 339.47 L 232.37 342.98 L 234.13 346.47 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 329px; margin-left: 369px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 14px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; "&gt;(5) Authentication Result&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="369" y="334" fill="#000000" font-family="Helvetica" font-size="14px" text-anchor="middle"&gt;(5) Authentication Result&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 190 253 L 190 94.37" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 190 89.12 L 193.5 96.12 L 190 94.37 L 186.5 96.12 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;g transform="translate(-0.5 -0.5)rotate(-90 177.5 170.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 171px; margin-left: 178px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 14px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; "&gt;(6) Authentication result&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="178" y="175" fill="#000000" font-family="Helvetica" font-size="14px" text-anchor="middle"&gt;(6) Authentication result&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="440" y="149" width="242" height="20" fill="none" stroke="none" pointer-events="all"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 240px; height: 1px; padding-top: 159px; margin-left: 441px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 19px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; "&gt;NTLM Authentication&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="561" y="165" fill="#000000" font-family="Helvetica" font-size="19px" text-anchor="middle" font-weight="bold"&gt;NTLM Authentication&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;switch&gt;&lt;g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;/g&gt;&lt;a transform="translate(0,-5)" xlink:href="https://desk.draw.io/support/solutions/articles/16000042487" target="_blank" rel="noopener noreferrer"&gt;&lt;text text-anchor="middle" font-size="10px" x="50%" y="100%"&gt;Viewer does not support full SVG 1.1&lt;/text&gt;&lt;/a&gt;&lt;/switch&gt;&lt;/svg&gt;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Authentication starts with user trying to log on from a client computer providing the username and password. The following steps will occur:&lt;/p&gt;&#10;&lt;ol class="wp-block-list"&gt;&lt;li&gt; The client application hashes user&amp;#8217;s password (with HMAC-MD5) and then discard the password. Then the client only sends the username to the server;&lt;/li&gt;&lt;li&gt;The server generates a challenge (16-byte random number) and sends it to the client;&lt;/li&gt;&lt;li&gt;The client encrypts this challenge with the hash (of user&amp;#8217;s password from step 1), and send the result back to the server as response (encrypted challenge);&lt;/li&gt;&lt;li&gt;The server sends the following three items to the domain controller:&lt;ul&gt;&lt;li&gt;username (in plain text)&lt;/li&gt;&lt;li&gt;the challenge it had sent to the client&lt;/li&gt;&lt;li&gt;the response from the client (encrypted challenge)&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;The domain controller has the hash of user&amp;#8217;s password stored, and retrieved (by username). It uses the hash to encrypt the challenge by itself and get its own version of encrypted challenge. It then compares it with the one passed on from the server. If identical, the user is authenticated and the domain controller notifies the user;&lt;/li&gt;&lt;li&gt;The server sends the appropriate response back to the client.&lt;/li&gt;&lt;/ol&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Essentially, NTLM mechanism is comparing the result encrypted by the client the result encrypted by the credential stored in itself. The results are expected to be identical because the encryption key &amp;#8211; hash of user&amp;#8217;s password &amp;#8211; should be identical. In this whole process, there is no password transmission on the wire. However, the disadvantage with this challenge-response based mechanism is that it does not let client authenticates the server, and is therefore considered less secure. This is what Kerberos is built to address.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-kerberos-authentication"&gt;Kerberos Authentication&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Kerberos is a ticket-based authentication mechansim. In Kerberos, a Key Distribution Centre (KDC) consists of AS (Authentication Service) and TGT (Ticket Granting Service). Authentication takes place in the following steps:&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="532px" viewBox="-0.5 -0.5 532 422" style="max-width:100%;max-height:422px;"&gt;&lt;defs&gt;&lt;/defs&gt;&lt;g&gt;&lt;rect x="0" y="0" width="530" height="420" fill="#dae8fc" stroke="#6c8ebf" pointer-events="all"&gt;&lt;/rect&gt;&lt;rect x="295" y="20" width="220" height="220" fill="#f5f5f5" stroke="#666666" pointer-events="all"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 218px; height: 1px; padding-top: 27px; margin-left: 296px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #333333; line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; "&gt;Key Distribution Centre (KDC)&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="405" y="39" fill="#333333" font-family="Helvetica" font-size="12px" text-anchor="middle" font-weight="bold"&gt;Key Distribution Centre (KDC)&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;image x="19.5" y="309.5" width="80" height="80" xlink:href="https://app.diagrams.net/img/lib/clip_art/computers/Server_Tower_128x128.png"&gt;&lt;/image&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-start; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 397px; margin-left: 60px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 12px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; "&gt;Server&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="60" y="409" fill="#000000" font-family="Helvetica" font-size="12px" text-anchor="middle"&gt;Server&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="305" y="50" width="90" height="40" fill="#ffffff" stroke="#000000" pointer-events="all"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 88px; height: 1px; padding-top: 70px; margin-left: 306px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 10px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "&gt;Authentication Service&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="350" y="73" fill="#000000" font-family="Helvetica" font-size="10px" text-anchor="middle"&gt;Authentication Ser&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="305" y="200" width="90" height="30" fill="#ffffff" stroke="#000000" pointer-events="all"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 88px; height: 1px; padding-top: 215px; margin-left: 306px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 10px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "&gt;Ticket-Granting Service&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="350" y="218" fill="#000000" font-family="Helvetica" font-size="10px" text-anchor="middle"&gt;Ticket-Granting Se&amp;#8230;&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 435 130 C 435 116.67 495 116.67 495 130 L 495 160 C 495 173.33 435 173.33 435 160 Z" fill="#ffffff" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 435 130 C 435 140 495 140 495 130" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 58px; height: 1px; padding-top: 153px; margin-left: 436px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 10px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: normal; word-wrap: normal; "&gt;Database&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="465" y="156" fill="#000000" font-family="Helvetica" font-size="10px" text-anchor="middle"&gt;Database&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 130.96 130.32 L 299.1 62.39" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 303.96 60.42 L 298.78 66.29 L 299.1 62.39 L 296.16 59.8 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;g transform="translate(-0.5 -0.5)rotate(-25 202.70257604259405 91.20055218559185)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 91px; margin-left: 203px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 10px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; "&gt;1) KRB_AS_REQ&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="203" y="94" fill="#000000" font-family="Helvetica" font-size="10px" text-anchor="middle"&gt;1) KRB_AS_REQ&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 305 70 L 136.25 138.95" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 131.39 140.94 L 136.55 135.05 L 136.25 138.95 L 139.2 141.53 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;g transform="translate(-0.5 -0.5)rotate(-24 218.785592780956 111.81428594103647)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 112px; margin-left: 219px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 10px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; "&gt;2) KRB_AS_REP&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="219" y="115" fill="#000000" font-family="Helvetica" font-size="10px" text-anchor="middle"&gt;2) KRB_AS_REP&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 130.72 159 L 298.87 205.79" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 303.92 207.2 L 296.24 208.7 L 298.87 205.79 L 298.12 201.95 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;g transform="translate(-0.5 -0.5)rotate(15 232.31861821225834 178.1096243201083)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 178px; margin-left: 232px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 10px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; "&gt;3) KRB_TGS_REQ&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="232" y="181" fill="#000000" font-family="Helvetica" font-size="10px" text-anchor="middle"&gt;3) KRB_TGS_REQ&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 305 215 L 136.15 170" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 131.08 168.65 L 138.75 167.07 L 136.15 170 L 136.94 173.83 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;g transform="translate(-0.5 -0.5)rotate(15 212.42059056182575 197.87113961107798)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 198px; margin-left: 212px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 10px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; "&gt;4) KRB_TGS_REP&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="212" y="201" fill="#000000" font-family="Helvetica" font-size="10px" text-anchor="middle"&gt;4) KRB_TGS_REP&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 100 180 L 80.97 303.71" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 80.17 308.9 L 77.78 301.44 L 80.97 303.71 L 84.69 302.51 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;g transform="translate(-0.5 -0.5)rotate(-80 80.41477191496142 229.60286507136118)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 230px; margin-left: 80px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 10px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; "&gt;5) KRB_AP_REQ&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="80" y="233" fill="#000000" font-family="Helvetica" font-size="10px" text-anchor="middle"&gt;5) KRB_AP_REQ&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 40 310 L 40 186.37" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 40 181.12 L 43.5 188.12 L 40 186.37 L 36.5 188.12 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;rect x="-20" y="230" width="90" height="20" fill="none" stroke="none" transform="rotate(-90,25,240)" pointer-events="all"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)rotate(-90 25.000000000000114 239.9999999999999)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 240px; margin-left: 25px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 10px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; "&gt;6) KRB_AP_REP&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="25" y="243" fill="#000000" font-family="Helvetica" font-size="10px" text-anchor="middle"&gt;6) KRB_AP_REP&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 398.93 65.01 L 440.07 117.49" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 395.69 60.88 L 402.76 64.23 L 398.93 65.01 L 397.25 68.55 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 443.31 121.62 L 436.24 118.27 L 440.07 117.49 L 441.75 113.95 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 398.98 205.03 L 431.02 164.97" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 395.7 209.13 L 397.34 201.47 L 398.98 205.03 L 402.8 205.85 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 434.3 160.87 L 432.66 168.53 L 431.02 164.97 L 427.2 164.15 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;rect x="10" y="120" width="120" height="60" fill="#f5f5f5" stroke="#666666" pointer-events="all"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 118px; height: 1px; padding-top: 150px; margin-left: 11px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 14px; font-family: Helvetica; color: #333333; line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; "&gt;Client&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="70" y="154" fill="#333333" font-family="Helvetica" font-size="14px" text-anchor="middle" font-weight="bold"&gt;Client&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="46.5" y="20" width="47" height="50" fill="none" stroke="none" pointer-events="all"&gt;&lt;/rect&gt;&lt;path d="M 59.94 34.39 C 59.86 30.61 61.12 26.96 63.43 24.25 C 65.73 21.55 68.89 20.01 72.19 20 C 79.55 20.08 85.55 26.48 85.82 34.54 C 86.1 38.24 84.99 41.91 82.74 44.69 C 80.5 47.46 77.33 49.1 73.96 49.23 C 66.51 49.39 60.29 42.81 59.94 34.39 Z M 46.5 70 C 46.8 62.97 49.38 56.42 53.64 51.94 C 57.01 48.56 61.71 48.36 65.25 51.44 C 67.27 52.95 69.49 54.17 71.85 55.06 C 74.26 56.12 76.91 55.94 79.23 54.56 C 80.5 53.94 81.62 53.04 82.53 51.94 C 83.42 50.86 84.97 50.64 86.12 51.44 C 88.14 52.81 89.96 55.24 91.38 58.48 C 92.76 62.16 93.48 66.05 93.5 69.99 Z" fill="#00188d" stroke="none" pointer-events="all"&gt;&lt;/path&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe flex-end; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 17px; margin-left: 70px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 14px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; "&gt;User&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="70" y="17" fill="#000000" font-family="Helvetica" font-size="14px" text-anchor="middle"&gt;User&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;path d="M 70 113.63 L 70 76.37" fill="none" stroke="#000000" stroke-miterlimit="10" pointer-events="stroke"&gt;&lt;/path&gt;&lt;path d="M 70 118.88 L 66.5 111.88 L 70 113.63 L 73.5 111.88 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;path d="M 70 71.12 L 73.5 78.12 L 70 76.37 L 66.5 78.12 Z" fill="#000000" stroke="#000000" stroke-miterlimit="10" pointer-events="all"&gt;&lt;/path&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 1px; height: 1px; padding-top: 90px; margin-left: 40px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 14px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; white-space: nowrap; "&gt;Log on&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="40" y="95" fill="#000000" font-family="Helvetica" font-size="14px" text-anchor="middle"&gt;Log on&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;rect x="290" y="370" width="200" height="20" fill="none" stroke="none" pointer-events="all"&gt;&lt;/rect&gt;&lt;g transform="translate(-0.5 -0.5)"&gt;&lt;switch&gt;&lt;foreignObject style="overflow: visible; text-align: left;" pointer-events="none" width="100%" height="100%" requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;div xmlns="http://www.w3.org/1999/xhtml" style="display: flex; align-items: unsafe center; justify-content: unsafe center; width: 198px; height: 1px; padding-top: 380px; margin-left: 291px;"&gt;&lt;div style="box-sizing: border-box; font-size: 0; text-align: center; "&gt;&lt;div style="display: inline-block; font-size: 15px; font-family: Helvetica; color: #000000; line-height: 1.2; pointer-events: all; font-weight: bold; white-space: normal; word-wrap: normal; "&gt;Kerberos Authentication&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/foreignObject&gt;&lt;text x="390" y="384" fill="#000000" font-family="Helvetica" font-size="15px" text-anchor="middle" font-weight="bold"&gt;Kerberos Authentication&lt;/text&gt;&lt;/switch&gt;&lt;/g&gt;&lt;/g&gt;&lt;switch&gt;&lt;g requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility"&gt;&lt;/g&gt;&lt;a transform="translate(0,-5)" xlink:href="https://desk.draw.io/support/solutions/articles/16000042487" target="_blank" rel="noopener noreferrer"&gt;&lt;text text-anchor="middle" font-size="10px" x="50%" y="100%"&gt;Viewer does not support full SVG 1.1&lt;/text&gt;&lt;/a&gt;&lt;/switch&gt;&lt;/svg&gt;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The authentication starts with user trying to log on from a client computer. Note that the &amp;#8220;client&amp;#8221; here refers to Kerberos client relative to Kerberos server (KDC). The client machine can serve as application server that runs kerberos library. The user provides username and password.&lt;/p&gt;&#10;&lt;ol class="wp-block-list"&gt;&lt;li&gt;The client sends KRB_AS_REQ as plain text to AS including:&lt;ul&gt;&lt;li&gt;username&lt;/li&gt;&lt;li&gt;timestamp&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;AS verifies timestamp, and validates username exists. If timestamp is too far (i.e. over 5 min) from current time, or user is not a legal principal, KRB_AS_REQ will be rejected. Otherwise, AS generates a random TGS session key and uses it to build a TGT. In KRB_AS_REP AS sends two messages to the client:&lt;ul&gt;&lt;li&gt;Message 1 is the TGT, which is encrypted with TGS secret key (so the client cannot decrypt TGT). It includes:&lt;ul&gt;&lt;li&gt;username&lt;/li&gt;&lt;li&gt;TGS name&lt;/li&gt;&lt;li&gt;timestamp&lt;/li&gt;&lt;li&gt;client network address&lt;/li&gt;&lt;li&gt;lifetime of TGT&lt;/li&gt;&lt;li&gt;TGS session key&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Message 2 is encrypted with client secret key (stored in AS)&lt;ul&gt;&lt;li&gt;TGS name&lt;/li&gt;&lt;li&gt;timestamp&lt;/li&gt;&lt;li&gt;lifetime&lt;/li&gt;&lt;li&gt;TGS session key (same as message 1)&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;The client receives both message 1 (TGT) and message 2. It decrypts message 2 with its own secret key and obtains TGS session key. For message 1 (TGT), the client cannot decrypt it. The client simply stores it in the credential cache. Then the client prepares two messages to send to the KDC:&lt;ul&gt;&lt;li&gt;Message 3 contains:&lt;ul&gt;&lt;li&gt;TGS name&lt;/li&gt;&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;lifetime&lt;/li&gt;&lt;li&gt;TGT (message1, encrypted with TGS secret key)&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Message 4 (aka Authenticator) is encrypted with TGS session key and contains:&lt;ul&gt;&lt;li&gt;username&lt;/li&gt;&lt;li&gt;timestamp&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;KDC processes message 3, determines TGS name is valid and forward TGT to TGS. TGS decrypts TGT using its own secret key and obtains TGS session key, along with username and timestamp. Then TGS decrypts message 4 using the newly obtained TGS session key, in order to get username and timestamp from message 4 as well. At this point, TGS has two sources of username and timestamp: one from TGT; the other from message 4. The TGS make sure they are identical, check if TGT is expired, and confirm that authenticator is not in the cache (to prevent replay). If all checks pass, the TGS then generates a random service session key. It will send two messages back to the client:&lt;ul&gt;&lt;li&gt;Message 5 (the service ticket) is encrypted with service secret key (stored in TGS) and contains:&lt;ul&gt;&lt;li&gt;username&lt;/li&gt;&lt;li&gt;service name&lt;/li&gt;&lt;li&gt;timestamp&lt;/li&gt;&lt;li&gt;client network address&lt;/li&gt;&lt;li&gt;lifetime&lt;/li&gt;&lt;li&gt;service session key&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Message 6 is encrypted with the TGS session key containing:&lt;ul&gt;&lt;li&gt;service name&lt;/li&gt;&lt;li&gt;timestamp&lt;/li&gt;&lt;li&gt;lifetime&lt;/li&gt;&lt;li&gt;service session key&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;The client receives message 5 and message 6 but it cannot decrypt message 5. The client cached TGS session key from previous step so it can decrypt message 6 and obtain service session key. Now the client contact the server by sending the following two messages:&lt;ul&gt;&lt;li&gt;Message 7: a new authenticator message encrypted with service session key that contains:&lt;ul&gt;&lt;li&gt;username&lt;/li&gt;&lt;li&gt;timestamp&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Message 8: the same as message 5, encrypted with service secret key&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;The server now receives message 7 and message 8. It decryptes message 8 to get service session key, along with username, service name, timestamp, etc. Using the service session key it descrypts message 7 to get a second source of username and timestamp. Similar to what happened in TGS, now the server compares username from the authenticator and from the ticket, checks if ticket is expired, and confirms that authenticator is not already in cache (to prevent replay attack). If all checks turn out okay. The service confirms its identity to the client with:&lt;ul&gt;&lt;li&gt;Message 9: an authenticator message encrypted with service session key that contains:&lt;ul&gt;&lt;li&gt;service name&lt;/li&gt;&lt;li&gt;timestamp&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;Lastly, the client receives message 9 and decrypts it with the service session key in cache. The client then confirms the service name and timestamp are valid/expected. If they are good, the authentication is completed and the client starts to communicate with the server.&lt;/li&gt;&lt;/ol&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The steps above borrowed some information from &lt;a href="https://www.vanimpe.eu/2017/05/26/kerberos-made-easy/"&gt;this page&lt;/a&gt;. The Keberos authentication process involves many steps and several keys:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&lt;li&gt;session (shared) keys:&lt;ul&gt;&lt;li&gt;TGS session key&lt;/li&gt;&lt;li&gt;Service session key&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;li&gt;secret keys:&lt;ul&gt;&lt;li&gt;client secret key&lt;/li&gt;&lt;li&gt;TGS secret key&lt;/li&gt;&lt;li&gt;Service secret key&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;By using these keys, no password is ever transmitted across the wire in the clear. The client and the server authenticate each other (mutual authentication). With a trusted third party, Kerberos ensures that the service ticket is only used by the intended client, and that only the intended server can validate the requested service ticket. Although, this sounds similar in two way authentication in TLS handshake, Kerberos does not encrypt the application traffic, neither is it intended to.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-kerberos-implementations"&gt;Kerberos Implementations&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt; The most popular implementation is &lt;a href="http://web.mit.edu/kerberos/dist/"&gt;MIT Kerberos 5&lt;/a&gt;. The other well-known implementation is &lt;a href="https://github.com/heimdal/"&gt;Heimdal&lt;/a&gt;. In addition, it is supported as API in GSS-API. In Windows applications, &lt;a href="https://static.digihunch.com/2020/03/introduction-to-authentication-frameworks-pam-and-sspi/"&gt;SSPI&lt;/a&gt; (Security Support Provider Interface) provides similar functionality to the GSS-API. SSPI can be viewed as Microsoft&amp;#8217;s implementation of GSS-API, which can be virtually regarded as Kerberos API.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;a href="https://www.kerberos.org/software/appskerberos.pdf"&gt;Kerberos &lt;/a&gt;is supported by many application protocols through GSS-API. If you build a Linux application, the server where the application is hosted acts as &lt;a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/managing_smart_cards/configuring_a_kerberos_5_client"&gt;Kerberos client&lt;/a&gt; (i.e. requiring krb-libs package and /etc/krb5.conf configured correctly) to interact with customer&amp;#8217;s &lt;a href="https://static.digihunch.com/2020/02/everything-about-the-domain/"&gt;Active Directory&lt;/a&gt; environment. If you need to configure&lt;a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/managing_smart_cards/configuring_a_kerberos_5_server"&gt; Kerberos servers&lt;/a&gt;, you will need other packages such as krb5-admin-server, krb5-kdc, and krb5-user.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;This &lt;a href="https://web.archive.org/web/20220201074221/https://ldapwiki.com/wiki/Kerberos"&gt;page&lt;/a&gt; lists some pros and cons of Kerberos. Some important takeaways are:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&lt;li&gt;Kerberos is &lt;strong&gt;legacy&lt;/strong&gt; protocol, &lt;strong&gt;complex&lt;/strong&gt; to set-up and maintain. It requires user accounts, user clients and the services on the server to all have a trusted relationship to the Kerberos token server. All must be in the same Kerberos realm or in domains that have a trust relationship between each other.&lt;/li&gt;&lt;/ul&gt;&#10;&lt;ul class="wp-block-list"&gt;&lt;li&gt;Kerberos cannot be used in a scenario where users want to connect to services from unknown/untrusted clients as in a typical Internet or cloud computing environment, where authentication provider typically does not have knowledge about the users client system. This implies Kerberos does not work will with modern REST applications and Authentication Methods such as SAML, and OAuth 2.0&lt;/li&gt;&lt;/ul&gt;&#10;&lt;ul class="wp-block-list"&gt;&lt;li&gt;Kerberos was created to accomplish authorization back in the days when no-one used a secure network connections.&lt;/li&gt;&lt;/ul&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2020/03/introduction-to-authentication-frameworks-pam-and-sspi/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Introduction to Authentication Frameworks (PAM and SSPI)&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2020/04/common-local-git-operations/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Common local Git operations&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>Introduction to Authentication Frameworks (PAM and SSPI)</title><link>https://static.digihunch.com/2020/03/introduction-to-authentication-frameworks-pam-and-sspi/</link><pubDate>Tue, 24 Mar 2020 20:19:00 -0400</pubDate><guid>https://static.digihunch.com/2020/03/introduction-to-authentication-frameworks-pam-and-sspi/</guid><description>&lt;p class="wp-block-paragraph"&gt;This article gives a very brief high-level introduction to PAM (Pluggable Authentication Module) and SSPI (Security Support Provider Interface) as authentication frameworks in Linux and Windows respectively. &lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-pam"&gt;PAM&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The &lt;a href="https://web.archive.org/web/20211022181300/https://ldapwiki.com/wiki/Pluggable%20Authentication%20Modules"&gt;Pluggable Authentication Module (PAM) architecture&lt;/a&gt; provides a powerful abstraction for user IAM using pluggable authentication model Unix platforms. It defines a generic API for authentication and hides the underlying mechanisms. Thanks to PAM, administrators can plug different authentication modules and protocols into Linux. This makes different authentication methods and protocols available to applications running on Linux. Here is some of authentication methods and protocols that PAM supports:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Unix file-based authentication (using /etc/passwd or /etc/shadow)&lt;/li&gt;&#10;&lt;li&gt;LDAP-based authentication&lt;/li&gt;&#10;&lt;li&gt;Kerbero-based authentication&lt;/li&gt;&#10;&lt;li&gt;NTLM-based authentication&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;PAM obviates the need for a separate authentication schemes. It exports methods of the various libraries under its auspices to calling applications. Here is a diagram for PAM on &lt;a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/managing_smart_cards/pluggable_authentication_modules"&gt;Redhat&lt;/a&gt;.&lt;/p&gt;&#10;&lt;figure class="wp-block-image size-full"&gt;&lt;img loading="lazy" decoding="async" width="765" height="678" src="https://static.digihunch.com/wp-content/uploads/2023/01/pam.jpg" alt="" class="wp-image-8107" srcset="https://static.digihunch.com/wp-content/uploads/2023/01/pam.jpg 765w, https://static.digihunch.com/wp-content/uploads/2023/01/pam-300x266.jpg 300w" sizes="auto, (max-width: 765px) 100vw, 765px" /&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;PAM can also enbable single-sign-on(SSO) on the UNIX platform. If the password used for different services are identical, PAM can be used to share the password transparently between the application&amp;#8217;s possibly different authentication mechanisms. PAM is configured in /etc/pam.d/ directory.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The Windows equivalent of PAM is the Security Support Provider Interface (SSPI) and its Security Support Provider (SSP) Modules. For example /etc/pam./login manages login module, /tec/pam.d/imap manages imap module.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-sspi"&gt;SSPI&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;a href="https://docs.microsoft.com/en-us/windows-server/security/windows-authentication/windows-authentication-architecture"&gt;Windows Authentication Architecture&lt;/a&gt; involves Local Security Authority (LSA, to authenticate users to local computer only and is managed in local security policy) and Security Support Provider Interface (SSPI).&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;a href="https://docs.microsoft.com/en-us/windows-server/security/windows-authentication/security-support-provider-interface-architecture"&gt;SSPI&lt;/a&gt; is the API that obtains integrated security service for authentication, message integrity, message privacy, and security quality-of-service for any distributed application protocol. SSPI is the implementation of the Generic Security Service API (GSS-API) in Windows operating system. Applications and infrastructure services authenticate users by using the SSPI to abstract calls for authentication. This way, developers do not need to understand the complexities of specific authentication protocols or build authentication protocols into their applications. &lt;a href="https://docs.microsoft.com/en-us/windows-server/security/windows-authentication/security-support-provider-interface-architecture"&gt;Here &lt;/a&gt;is the architecture diagram:&lt;/p&gt;&#10;&lt;figure class="wp-block-image"&gt;&lt;img decoding="async" src="https://docs.microsoft.com/en-us/windows-server/security/media/security-support-provider-interface-architecture/authn_securitysupportproviderinterfacearchitecture.jpg" alt="Diagram showing the Security Support Provider Interface Architecture"/&gt;&lt;/figure&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The SSPI in Windows provides a mechansim that carries authentication token over the existing communication channel between the client computer and the server. When two computers or devices need to be authenticated so that they can communicate securely, the requests for authentication are routed to the SSPI, which completes the authentication process, regardless of the network protocol currently in use. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Here is some exampls of SSPs that are supported by SSPI:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&#10;&lt;li&gt;Kerberos SSP (default for Active Directory)&lt;/li&gt;&#10;&lt;li&gt;NTLM SSP&lt;/li&gt;&#10;&lt;li&gt;Digest SSP&lt;/li&gt;&#10;&lt;li&gt;Negotiate SSP (based on &lt;a href="https://en.wikipedia.org/wiki/SPNEGO"&gt;SPNEGO&lt;/a&gt;, RFC4178)&lt;/li&gt;&#10;&lt;li&gt;Credential SSP&lt;/li&gt;&#10;&lt;li&gt;Negotiate Extension SSP&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Some SSPs such as Kerberos SSP and NTLM SSP use a single protocol. Some (e.g. Negotiate SSP and Credential SSP) combine several protocols to allow application to select what security mechanism they wish to use and negotiate with authentication services.&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2020/03/authentication-mechanisms-under-simple-authentication-and-security-layer-sasl/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;SASL Authentication Mechanisms&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2020/03/ntlm-and-kerberos/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;NTLM and Kerberos protocols&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>SASL Authentication Mechanisms</title><link>https://static.digihunch.com/2020/03/authentication-mechanisms-under-simple-authentication-and-security-layer-sasl/</link><pubDate>Thu, 19 Mar 2020 22:53:00 -0400</pubDate><guid>https://static.digihunch.com/2020/03/authentication-mechanisms-under-simple-authentication-and-security-layer-sasl/</guid><description>&lt;h3 class="wp-block-heading"&gt;Introduction&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Authentication is used in many protocols (such as LDAP binding) and it usually involves sending password. Given the nature of authentication protocol, its traffic encryption is usually mandatory. Simple Authentication and Security Layer (SASL) is introduced to ensure the security during authentication. It is not a single protocol, but rather a framework for authentication and data security involving many protocols. The intent is to decouple authentication mechanisms from application protocols, thus allowing any authentication mechanism (under SASL) to be used in any application protocol (that supports SASL). Application protocols that support SASL typically can also be built on Transport Layer Security (TLS), whose latest versions (1.2 and 1.3) are considered more secure.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;None (ANONYMOUS)&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The server basically does not authenticate the client. The client connects to the server anonymously. Under SASL framework, this may also be referred to as ANONYMOUS mechanism.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;Simple (PLAIN)&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In simple authentication method the password is sent to server in the clear. This is subject to eavesdropping and is not secure. It is still surprisingly widespread in legacy configurations probably due to the simplicity of configuration. This option should not be available in cloud environment. Under SASL framework, this may also be referred to as PLAIN mechanism.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;CRAM-MD5 and DIGEST-MD5&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;a href="https://web.archive.org/web/20211206115031/https://ldapwiki.com/wiki/CRAM-MD5"&gt;CRAM-MD5&lt;/a&gt;: described in RFC 2195, using HMAC-MD5 algorithm. In this challenge-response scheme based mechanism, the client&amp;#8217;s password is protected during authentication, but the application session (e.g. LDAP) traffic is not encrypted. It includes random data from the server and is slightly better than Simple authentication. However, this authentication method is not recommended either.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;a href="https://web.archive.org/web/20220129132628/https://ldapwiki.com/wiki/DIGEST-MD5"&gt;DIGEST-MD5&lt;/a&gt;: described in RFC 2831. This is very similar to CRAM-MD5 but is is somewhat stronger because it includes random data from both the client and server. In addition, it also provides a provision to ensure connection integrity and confidentiality (a data security layer).&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;GSSAPI&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Generic Security Service Application Program Interface (&lt;a href="https://en.wikipedia.org/wiki/Generic_Security_Services_Application_Program_Interface"&gt;GSS-API&lt;/a&gt;) is an API specification for programs to access security services. GSS-API by itself does not provide any security. Instead, security-service vendors provide GSSAPI implementations &amp;#8211; usually in the form of libraries installed with their security software. These libraries present a GSSAPI-compatible interface to application developers who can write their application to use only the vendor-independent GSSAPI. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Under SASL, the dominant GSSAPI mechanism implementation in use is Kerberos version 5. GSSAPI allows Kerberos implementations to be API compatible. In many contexts, &lt;a href="https://en.wikipedia.org/wiki/Generic_Security_Services_Application_Program_Interface"&gt;GSSAPI&lt;/a&gt; simply implies &lt;a href="https://en.wikipedia.org/wiki/Kerberos_(protocol)"&gt;Kerberos&lt;/a&gt;.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;NTLM&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;NT LAN Manager (NTLM) is a challenge-response based Microsoft security protocols. It is implemented in a Security Support Provider (&lt;a href="https://en.wikipedia.org/wiki/Security_Support_Provider_Interface"&gt;SSP&lt;/a&gt;), which combines the older LAN Manager authentication protocol, NTLMv1, NTLMv2 and NTLM2 Session protocols in a single package. Group policy manages whether these protocols are used or can be used. NTLM passwords are considered weak because they can be brute-forced very easily with modern hardware. It might still be enabled in server configuration as a backup mechanism to Kerberos.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;TLS (EXTERNAL)&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;CRAM-MD5, DIGEST-MD5, GSSAPI, and NTLM are more commonly referred to as SASL mechanisms (in loose terms). These mechanisms allow for a secure password exchange without requiring TLS by trying to address the authentication traffic encryption problem at application layer. Using TLS this can also be address at transport layer. TLS can be used in combination with any of the mechanisms above but usually TLS/Simple mechanism is sufficient. In many occasions the mechanisms under SASL can be replaced by simple authentication encrypted with TLS. Under the SASL framework, this may also be referred to as EXTERNAL mechanism so TLS (in strict terms) is also considered a SASL mechanism.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;Summary&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;This article outlined several authentication protocols under SASL. Since SASL is the framework that intends to govern all authentication protocols, the use case of these protocol can be widespread. For example, in &lt;a href="https://docs.oracle.com/cd/E19253-01/816-4556/ldapsecure-75/index.html"&gt;LDAP&lt;/a&gt; you can find all of them. Here is a comparison across them:&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&#10;&lt;table id="tablepress-7" class="tablepress tablepress-id-7"&gt;&#10;&lt;thead&gt;&#10;&lt;tr class="row-1"&gt;&#10;&#9;&lt;td class="column-1"&gt;&lt;/td&gt;&lt;th class="column-2"&gt;Password on wire&lt;/th&gt;&lt;th class="column-3"&gt;Session&lt;/th&gt;&#10;&lt;/tr&gt;&#10;&lt;/thead&gt;&#10;&lt;tbody class="row-striping row-hover"&gt;&#10;&lt;tr class="row-2"&gt;&#10;&#9;&lt;td class="column-1"&gt;Simple&lt;/td&gt;&lt;td class="column-2"&gt;Clear&lt;/td&gt;&lt;td class="column-3"&gt;No Encryption&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-3"&gt;&#10;&#9;&lt;td class="column-1"&gt;SASL/CRAM-MD5&lt;/td&gt;&lt;td class="column-2"&gt;Encrypted&lt;/td&gt;&lt;td class="column-3"&gt;No Encryption&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-4"&gt;&#10;&#9;&lt;td class="column-1"&gt;SASL/DIGEST-MD5&lt;/td&gt;&lt;td class="column-2"&gt;Encrypted&lt;/td&gt;&lt;td class="column-3"&gt;No Encryption&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-5"&gt;&#10;&#9;&lt;td class="column-1"&gt;SASL/GSSAPI&lt;/td&gt;&lt;td class="column-2"&gt;Kerberos&lt;/td&gt;&lt;td class="column-3"&gt;Encryption&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-6"&gt;&#10;&#9;&lt;td class="column-1"&gt;TLS:SIMPLE&lt;/td&gt;&lt;td class="column-2"&gt;Encrypted&lt;/td&gt;&lt;td class="column-3"&gt;Encrypted&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;!-- #tablepress-7 from cache --&gt;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Common SASL implementation includes Cyrus SASL and GNU SASL. There are also some API implementations that supports some of SASL mechanisms, such as SSPI.&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2020/03/oauth-and-openid-connect/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;OAuth 2.0 and OIDC 1 of 2&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2020/03/introduction-to-authentication-frameworks-pam-and-sspi/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Introduction to Authentication Frameworks (PAM and SSPI)&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>Lightweight Directory Access Protocol (LDAP)</title><link>https://static.digihunch.com/2020/03/lightweight-directory-access-protocol-ldap/</link><pubDate>Mon, 02 Mar 2020 21:11:00 -0400</pubDate><guid>https://static.digihunch.com/2020/03/lightweight-directory-access-protocol-ldap/</guid><description>&lt;h3 class="wp-block-heading" id="h-introduction"&gt;Introduction&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Originally LDAP only refers to the connectivity protocol to the directory server. This term is being used loosely today and it also refers to the actual directory service that supports and complies with LDAP. LDAP v3 is the current version developed in RFC 2251.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;A directory is information about some set of entities such as people, organization, or stones. An example of directory would be /etc/passwd file in Linux. A directory server is simply an application with the main purpose of maintaining directories. Typically, the read traffic is high whereas write traffic is low. LDAP is a general-purpose directory server. It can store information about people, or cars, or rocks. You just need to define what a person&amp;#8217;s entry looks like as well as what a rock&amp;#8217;s entry looks like. The general architecture of LDAP provides the capability nedded for managing large amount of diverse directory entries.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;An LDAP entry consists of DN (distinguished name) and attributes. An attribute may have one or more attribute names and they are defined in attribute definitions. Attribute names are not case-sensitive. An attribute may have one or more values if multiple values are allowed for that attribute. Attribute values may be case-sensitive depending on the definition.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;A special attributed named objectclass attribute provides information about what type of record it is, and what attributes canbe given to the record. For example, the organization name (o) is required for any entry with an organization object class. While a record may have multiple object classes, one of these object classes must be the structural object class for the record. A structural object class determines what type of object the record is.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In addition to regular attributes, the directory server may also attach special operational attributes to an entry. Operational attributes are used by the directory server itself to store information about entries. Such attributes are not designed for use by end users, and are usually not returned during LDAP searches.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;An LDAP schema defines types of records in a directory and how those records might relate to each other. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Information in an LDAP directory is organized into one or more hierarchies where, at the top of the hierarchy, there is a base entry, and other entries are organized in tree-like structures beneath the base entry. Each node on the hierarchy is an entry, with a DN and more than one attributes. This hierarchically organized collection of entries is called a directory information tree (DIT). In DIT, LDAP directories stores data in hierarchical relationships. The root entry sits at the top and subordinate entry is beneath that, which in turn may have its own subordinate entries. Each of these records has its own DN, and its own attributes. The DN of each entry is composed of two parts: the relative DN (RDN) and the full DN of the superior entry.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;LDAP is nothing other than a special sort of database that organizes data into tree structures, like a file system hierarchy. This view is more easily seen by comparing an LDAP directory to a relational database system (RDB), where SQL is the protocol and RDBMS is the service. LDAP refers to both the protocol and the service.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-openldap"&gt;OpenLDAP&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;A common LDAP implementation is openldap. OpenLDAP suite can be broken up into four components:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&lt;li&gt;Servers: slapd (stand-alone LDAP Daemon) provides LDAP services.&lt;/li&gt;&lt;li&gt;Clients: ldapsearch is used to manipulate LDAP data&lt;/li&gt;&lt;li&gt;Utilities: support LDAP servers&lt;/li&gt;&lt;li&gt;Libraries: provide programming interfaces to LDAP&lt;/li&gt;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Installing OpenLDAP requires libldap-2.3-0, slapd, ldap-utiles packages. It is configured in /etc/ldap/. An HDB (hierarchical database) needs to be specified in the configuration.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;To test as a client, the first thing that must happen is the client must authenticate to the server (via simple bind or &lt;a href="https://static.digihunch.com/2020/03/authentication-mechanisms-under-simple-authentication-and-security-layer-sasl/"&gt;SASL&lt;/a&gt; Bind). LDAP server verifies the identity, permission as well as password provided by the client.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;LDAPTLS_REQCERT=never ldapsearch -x -o ldif-wrap=256 -H ldaps://ldap.digihunch:636/ -b &amp;#34;OU=Admin,OU=Service Department,DC=digihunch,DC=com&amp;#34; -D &amp;#34;gh\ldap-bind-user&amp;#34; -w &amp;#39;S@f35+P@55w0rd&amp;#39; &amp;#34;(objectclass=user)&amp;#34; -s sub -d 9&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;The command above first sets client environment variable LDAPTLS_REQCERT to never, in case the client is being asked to provide certificate. Then the ldapsearch command performs the bind.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;To search the directory, the client needs to provide the followings:&lt;/p&gt;&#10;&lt;ul class="wp-block-list"&gt;&lt;li&gt;Base DN: where in the directory to start from&lt;/li&gt;&lt;li&gt;Scope: how deep in the tree to look&lt;/li&gt;&lt;li&gt;Attributes: what information to be retrieved per result&lt;/li&gt;&lt;li&gt;Filter: what to look for&lt;/li&gt;&lt;/ul&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Below is an example of ldapsearch (-b for Base DN, -s for Scope, -S for attributes, stdin for filter):&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ldapsearch -x -o ldif-wrap=256 -H ldaps://ldap.digihunch:636/ -b &amp;#34;OU=Admin,OU=Service Department,DC=digihunch,DC=com&amp;#34; -D &amp;#34;gh\ldap-bind-user&amp;#34; -w &amp;#39;S@f35+P@55w0rd&amp;#39; &amp;#34;(memberof=CN=Security-Admin,OU=Admin,OU=Service Department,DC=digihunch,DC=com)&amp;#34; -s sub -S name&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p class="wp-block-paragraph"&gt;Users with appropriate permissions may also other directory operations using ldapadd, ldapmodify, ldapdelete, ldapcompare, ldapmodrdn, ldappasswd, ldapwhoami, etc&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Apart from those in Openldap toolkits, there are many other tools such as Apache Directory Studio that allows you to perform similar functionality with a user interface.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading" id="h-ldap-security"&gt;LDAP security&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Historically LDAP servers listens to port 389 through which traffic is sent in clear text. This is a bad security practice known as &amp;#8220;insecure bind&amp;#8221;. To secure LDAP traffic, two prevalent approaches are Secure LDAP and StartTLS.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;strong&gt;Secure LDAP&lt;/strong&gt; was the original attempt to secure LDAP traffic as an addition to LDAP v2. It is also known as LDAPS, LDAP over TLS/SSL or LDAP channel binding (“channel binding” just refers to the establishment of encrypted channel following TLS handshake. It provides a facility to tie an authentication exchange to security services provided at a lower layer. Defined in &lt;a href="https://tools.ietf.org/html/rfc5056"&gt;RFC 5056&lt;/a&gt;). Secure LDAP operates on port 636 on the server side and TLS handshake must be established for traffic encryption. Client application usually need to import the certificate of LDAP server. As part of TLS 1.2 protocol, the server may also request client certificate during &lt;em&gt;ServerHello&lt;/em&gt; message. The presence of &lt;em&gt;CertificateRequest&lt;/em&gt; means the server either demands client certificate, or tries to get client certificate (i.e. TLSVerifyClient is set to demand or try, which is only visible on the server). If client cert is only attempted, the LDAP client may choose to ignore it. If client cert is demanded, then a two-way TLS authentication is required and thus the client must proof its identity to the server. This Secure LDAP configuration requires the server to listen to both 389 and 636 ports on the same server to support both secure and legacy applications, which is unnecessary. Secure LDAP therefore is not the preferred approach. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The standardized way of implementing SSL/TLS in LDAP v.3 is to use the &lt;strong&gt;StartTLS&lt;/strong&gt; method. This method should be implemented whenever possible. If an AD server supports StartTLS, the client can start with a STARTTLS command to the server so that the server begins the TLS encryption process. In the binding phase, TLS handshake follows a &lt;strong&gt;LDAP_START_TLS_OID&lt;/strong&gt; command through port 389.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Here’s the summary of the three LDAP configuration mode:&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&#10;&lt;table id="tablepress-5" class="tablepress tablepress-id-5"&gt;&#10;&lt;thead&gt;&#10;&lt;tr class="row-1"&gt;&#10;&#9;&lt;td class="column-1"&gt;&lt;/td&gt;&lt;th class="column-2"&gt;Legacy&lt;/th&gt;&lt;th class="column-3"&gt;SecureLDAP (aka LDAPS, LDAP over TLS/SSL)&lt;/th&gt;&lt;th class="column-4"&gt;StartTLS&lt;/th&gt;&#10;&lt;/tr&gt;&#10;&lt;/thead&gt;&#10;&lt;tbody class="row-striping row-hover"&gt;&#10;&lt;tr class="row-2"&gt;&#10;&#9;&lt;td class="column-1"&gt;Listening port&lt;/td&gt;&lt;td class="column-2"&gt;389&lt;/td&gt;&lt;td class="column-3"&gt;636&lt;/td&gt;&lt;td class="column-4"&gt;389&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-3"&gt;&#10;&#9;&lt;td class="column-1"&gt;Traffic Encrypted&lt;/td&gt;&lt;td class="column-2"&gt;No&lt;/td&gt;&lt;td class="column-3"&gt;Yes&lt;/td&gt;&lt;td class="column-4"&gt;Yes&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;tr class="row-4"&gt;&#10;&#9;&lt;td class="column-1"&gt;Standard&lt;/td&gt;&lt;td class="column-2"&gt;Yes but this should always be avoided since it is insecure&lt;/td&gt;&lt;td class="column-3"&gt;Introduced in the time of LDAP v2, but the option is deprecated (although still supported) by RedHat&lt;/td&gt;&lt;td class="column-4"&gt;Introduced in LDAP v3. This may be left as the only valid option.&lt;/td&gt;&#10;&lt;/tr&gt;&#10;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;!-- #tablepress-5 from cache --&gt;&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Note that one of the recent changes that drives may customer away from the legacy mode is the &lt;a href="https://support.microsoft.com/en-us/help/4520412/2020-ldap-channel-binding-and-ldap-signing-requirement-for-windows"&gt;requirement for LDAP channel binding&lt;/a&gt; on Windows servers, with a target date of March 2020. Our current strategy at CS is to direct customer towards Secure LDAP as we do not support StartTLS yet and we know we do support LDAPS. Although Secure LDAP itself is somewhat legacy this would not hold long. According to &lt;a href="https://en.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol"&gt;this&lt;/a&gt; Wikipedia page:&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The use of LDAP over SSL was common in LDAP Version 2 (LDAPv2) but it was never standardized in any formal specification. This usage has been deprecated along with LDAPv2, which was officially retired in 2003. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The trade off between StartTLS and TLS/SSL exists not only in LDAP protocol, but also in many other protocols such as SMTP (port 2525, 25, 587). StartTLS is also called &lt;a href="https://en.wikipedia.org/wiki/Opportunistic_TLS"&gt;Opportunistic TLS&lt;/a&gt;. The standard is in the relevant RFC documents.&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2020/02/everything-about-the-domain/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Introduction to Active Directory (AD)&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2020/03/saml-security-assertion-markup-language/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Security Assertion Markup Language (SAML)&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item><item><title>Introduction to Active Directory (AD)</title><link>https://static.digihunch.com/2020/02/everything-about-the-domain/</link><pubDate>Fri, 28 Feb 2020 21:36:00 -0400</pubDate><guid>https://static.digihunch.com/2020/02/everything-about-the-domain/</guid><description>&lt;h3 class="wp-block-heading"&gt;Workgroup, homegroup and Windows Domain&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;A workgroup is a group of computers on the same local network. A Windows computer not joined to a domain is part of a workgroup. In a workgroup, no computer has control over any other computer and it does not require a password. Any computer can join or leave a workgroup any time. Workgroup was previously for home file and printer sharing and Microsoft later introduced homegroup for more security. Compared to workgroup, all computers in a homegroup needs to be on the same home network (instead of local network). Homegroup is password protected. New computer needs to join homegroup by providing the password.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Windows domains (or domains for short) provide network administrators with a way to manage a large number of PCs and control them from one place and remotely.&amp;nbsp;One or more servers — known as domain controllers — have control over the domain and the computers on it. Computers on a domain has to be on the same local network, either physically or over VPN. Centralized control is essential for corporate operation.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Administrators can join a Windows PC with professional or enterprise license to a domain. Once joined, the computer does not use its own local user accounts. When a user logs into a computer on that domain, the computer authenticates the user account name and password with the domain controller. Also, the computer cannot just leave the domain without administrator access. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Network administrators can change group policy settings on the domain controller. Each computer on the domain will get these settings from the domain controller and they’ll override any local settings users specify on their PCs. All the settings are controlled from a single place. This prevents from users from changing many system settings on a computer joined to a domain. The domain controller is in charge of what a user can do. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Apart from centralized administration, the benefit the users is that they can log in with the same username and password on any computer joined to the domain, if permission allows.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;Domain Controller&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;In order to achieve centralized administration and log-in from any computer in the corporate world, a centralized service called domain controller is introduced. At a high level, a domain controller maintains a list for each of the followings:&lt;/p&gt;&#10;&lt;ol class="wp-block-list"&gt;&lt;li&gt;Users and their passwords&lt;/li&gt;&lt;li&gt;Computers and their credentials&lt;/li&gt;&lt;/ol&gt;&#10;&lt;p class="wp-block-paragraph"&gt;This is because in a domain, not only the users, but also the computers (workstations or servers) need to be authenticated. For example, when a Windows server boots up, it needs to log on to the domain with its own credential. This way we can control whether the server is allowed to query the domain for information about users. If it is allowed to query the domain, then we can determine whether the user is allowed to log on that server, and eventually, authenticate the user. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;For a domain controller, it responsibility to credentials for users and computers, and respond to log in requests (authentication service) is a critical commitment in the enterprise environment. Domain controller is therefore commonly built with high availability and fault tolerance.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Administrators needs to add each new user to the user directory in domain controller. They also needs to register each new computer with the domain controller by joining them to the domain. &lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;Joining a Domain&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;As explained earlier, joining a Window domain means register a computer in the domain so it has the permission to query the domain to validate users identity and permissions. Both Windows server and Linux server can join a domain. Windows servers usually provide a path through UI to join a domain and password is required. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;To join a Linux (e.g. Redhat) server to a domain, we can use a tool called &lt;em&gt;adcli&lt;/em&gt;. Here is a good example of using this command to join a &lt;a href="https://www.2daygeek.com/join-integrate-rhel-centos-linux-system-to-windows-active-directory-ad-domain/"&gt;domain&lt;/a&gt;.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;Authentication&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;A Windows or Linux server in the domain needs to go to the domain controller to authenticate itself and the users. Authentication involves several protocols, including kerberos, NTLM, TLS/SSL and Digest, as part of an extensible architecture. In addition, some protocols are combined into authentication packages such as Negotiate and the Credential Security Support Provider.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;The &lt;a href="https://web.mit.edu/kerberos/krb5-1.12/doc/index.html"&gt;MIT Kerberos Documentation&lt;/a&gt; provides some tools (e.g. kinit, klist) to configure and troubleshoot Kerberos protocol.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;Active Directory &lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Since Windows 2000, Active Directory is a complete redesign and re-branding of the entire Windows Domain system. The term &lt;em&gt;Active Directory&lt;/em&gt; now refer to either the entire domain system, or the actual database that comprises the Windows Domain information or both.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;All of the information that makes up an Active Directory is stored in an X.500 compatible database, typically replicated between domain controllers to ensure high availability and fault tolerance. X.500 is a set of network directory standards. A Windows Domain is a kind of network directory, hence the name Active Directory for its replacement. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Active Directory introduced one important new type of object and concept, Forests. An Active Directory Forest is kind of a list of lists, meaning, it is a collection of Domains that are all related to each other for both security and management purposes.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;&lt;a href="https://medium.com/@yoursproductly/understanding-active-directory-4e7508372b80"&gt;Here&lt;/a&gt; is more details about Active Directory.&lt;/p&gt;&#10;&lt;h3 class="wp-block-heading"&gt;Lightweight Directory Access Protocol&lt;/h3&gt;&#10;&lt;p class="wp-block-paragraph"&gt;As mentioned above, &lt;a href="https://en.wikipedia.org/wiki/X.500"&gt;X.500&lt;/a&gt; is a series of computer networking standards covering electronic directory services. ISO incorporated it into OSI suite of protocols. The protocols defined by X.500 include DAP (Directory Access Protocol), DSP (Directory System Protocol), DISP (Directory Information Shadowing Protocol) and DOP (Directory Operational Bindings Management Protocol). DAP is a heavyweight protocol that operates over a full OSI protocol stack and requires a significant amount of computing resources. LDAP (Lightweight Directory Access Protocol), as its alternative, is designed to operate over TCP/IP and provides most of the functionality of DAP at a much lower cost.&lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Technically speaking, LDAP is a directory access protocol to an X.500 directory service. In early days, the typical architecture involves a proxy. Client connects to the proxy in LDAP and the proxy connects to X.500 server in DAP. Nowadays, it is common that LDAP is directly implemented in X.500 servers. &lt;/p&gt;&#10;&lt;p class="wp-block-paragraph"&gt;Because &lt;a href="https://en.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol"&gt;LDAP &lt;/a&gt;is based on a simpler subset of the standards contained within the X.500 standard, LDAP was sometimes called X.500-lite. While DAP and the other X.500 protocols can now use the TCP/IP networking stack, LDAP remains a popular directory access protocol.&lt;/p&gt;&#10;&lt;nav class="wp-post-navigation" aria-label="Post navigation"&gt;&#10;&lt;a rel="prev" href="https://static.digihunch.com/2020/01/several-ways-to-ensure-high-availability/"&gt;&lt;span class="wp-post-navigation-label"&gt;Previous Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;High Availability and Load Balancer&lt;/strong&gt;&lt;/a&gt;&#10;&lt;a rel="next" href="https://static.digihunch.com/2020/03/lightweight-directory-access-protocol-ldap/"&gt;&lt;span class="wp-post-navigation-label"&gt;Next Post&lt;/span&gt;&lt;strong class="wp-post-navigation-title"&gt;Lightweight Directory Access Protocol (LDAP)&lt;/strong&gt;&lt;/a&gt;&#10;&lt;/nav&gt;&#10;</description></item></channel></rss>